/* =====================================================================
   player-question-theme.css
   Redesigned QUESTION / ANSWER screens for the player device.

   SCOPING CONTRACT (do not break):
   - Every rule is prefixed with `body.q-redesign` so it is OFF by default.
   - Every rule targets `#qArea …` or a popup id (`#playerFast`).
   - NOTHING here targets a `#*GameInterface` selector, so minigames are
     physically untouched. Keep it that way.

   To enable:   document.body.classList.add('q-redesign')
   To roll back: remove the class. No other change needed.
   ===================================================================== */

/* ---- design tokens (from the approved mockup) ---- */
body.q-redesign {
  --q-bg:        #101018;   /* screen background            */
  --q-card:      #1b1b26;   /* inset panels / inputs        */
  --q-ink:       #ffffff;   /* primary text                 */
  --q-gold:      #f2a900;   /* brand / submit               */
  --q-gold-dk:   #b77c00;   /* cheese holes                 */
  --tile-a:      #e8324a;   /* red   */
  --tile-b:      #2f7df6;   /* blue  */
  --tile-c:      #f2a900;   /* gold  (dark ink)             */
  --tile-d:      #16a36a;   /* green */
  --tile-e:      #9b51e0;   /* purple*/
  --tile-f:      #ff6f3c;   /* orange*/
  --q-font:      'Archivo', system-ui, sans-serif;
  --q-display:   'Archivo Expanded', sans-serif;
}

/* ---- screen shell ---- */
body.q-redesign #qArea {
  background: var(--q-bg);
  color: var(--q-ink);
  font-family: var(--q-font);
}

/* ---- "Cheese Noir" SCREEN background ---- a fixed layer behind ALL content (z-index -1);
   minigame interfaces paint over it.
   Owner decision (2026-06-21): the host-chosen PHOTO background (set on <body> by
   player.js `_setPlayerBackgroundImage`) shows on the LOBBY / between-question screens,
   and a solid dark Cheese Noir backdrop is kept DURING a live question for tile/text
   contrast — mirroring the classic `body.question-active { background-image:none }` rule.
   So this ::before is a TRANSLUCENT veil by default (the photo reads through, dark-tinted
   with cheese-hole accents), and becomes OPAQUE only while `body.question-active`. */
body.q-redesign::before {
  content: "";
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(circle at 16% 22%, rgba(0,0,0,.45) 11px, transparent 12px),
    radial-gradient(circle at 73% 13%, rgba(0,0,0,.4)  14px, transparent 15px),
    radial-gradient(circle at 86% 62%, rgba(0,0,0,.42) 9px,  transparent 10px),
    radial-gradient(circle at 28% 80%, rgba(0,0,0,.4)  13px, transparent 14px),
    radial-gradient(circle at 52% 46%, rgba(0,0,0,.34) 8px,  transparent 9px),
    radial-gradient(circle at 6% 64%,  rgba(0,0,0,.36) 10px, transparent 11px),
    radial-gradient(120% 90% at 115% -12%, rgba(140,92,12,.22), transparent 55%),
    linear-gradient(150deg, rgba(28,18,7,.55) 0%, rgba(20,16,10,.5) 45%, rgba(14,12,18,.6) 100%);
}
/* During a live question: OPAQUE Cheese Noir backdrop (photo suppressed for max contrast). */
body.q-redesign.question-active::before {
  background:
    radial-gradient(circle at 16% 22%, rgba(0,0,0,.55) 11px, transparent 12px),
    radial-gradient(circle at 73% 13%, rgba(0,0,0,.46) 14px, transparent 15px),
    radial-gradient(circle at 86% 62%, rgba(0,0,0,.5)  9px,  transparent 10px),
    radial-gradient(circle at 28% 80%, rgba(0,0,0,.44) 13px, transparent 14px),
    radial-gradient(circle at 52% 46%, rgba(0,0,0,.38) 8px,  transparent 9px),
    radial-gradient(circle at 6% 64%,  rgba(0,0,0,.4)  10px, transparent 11px),
    radial-gradient(120% 90% at 115% -12%, rgba(140,92,12,.45), transparent 55%),
    linear-gradient(150deg, #1c1207 0%, #14100a 45%, #0e0c12 100%);
}

/* WHEEL FREEZE FIX (Android regression): while the spin wheel is open, drop this fixed
   full-screen multi-radial-gradient backdrop. Composited UNDER the 11-layer preserve-3d
   cylinder it stalled Android's compositor on the show frame (the 3D wheel worked before the
   redesign added this layer). The opaque #playerWheelDisplay overlay covers it, so hiding it has
   NO visible effect. body.wheel-open is toggled by wheel-popup-enhance.js on wheel show/hide. */
body.q-redesign.wheel-open::before { display: none !important; }

/* WHEEL FREEZE — ROOT FIX (2026-06-23): hiding the ::before + the overlay's OWN backdrop-filter
   (the #playerWheelDisplay rules below) was NOT enough. The live question UI sitting BEHIND the
   opaque, full-screen wheel overlay still carries several stacked backdrop-filter blur panels
   (qtui cards, the scoreboard drawer, media popups, the info bar). Compositing those live blurs on
   the wheel SHOW frame — while the whole question DOM is mounted (body.question-active) — is what
   pegs the main thread / crashes the tab (desktop included). It only hurts mid-question because the
   lobby has no question DOM and no opaque ::before. The overlay is opaque, so dropping EVERY backdrop
   blur while the wheel is up is INVISIBLE. body.wheel-open is set synchronously in PlayerWheel.show()
   (before paint), so these take effect on the same frame the wheel reveals. */
body.q-redesign.wheel-open *,
body.q-redesign.wheel-open *::before,
body.q-redesign.wheel-open *::after {
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
}
/* Belt-and-suspenders: also take the heavy live question UI out of paint/composite while the
   (opaque, full-screen) wheel overlay is up — it is fully covered, so this is invisible, and it
   removes EVERY animated/filtered layer behind the wheel (timer ring, gradient cards, tiles) on a
   real GPU. Headless cannot reproduce the compositor stall, so we over-correct. Explicit ids ONLY
   (never #playerWheelDisplay) so the wheel overlay is never hidden. visibility (not display) keeps
   layout stable so the fixed overlay does not reflow. */
body.q-redesign.wheel-open #qArea,
body.q-redesign.wheel-open #answerTiles,
body.q-redesign.wheel-open #buzzing-interface,
body.q-redesign.wheel-open .player-info-bar,
body.q-redesign.wheel-open #engagementBar { visibility: hidden !important; }

/* =====================================================================
   HEADER / brand bar — cheese-hole texture + prominent score & timer
   Adjust the selector to match your real header element.
   ===================================================================== */
body.q-redesign .player-info-bar {       /* the real top info bar (#playerInfoBar). "Cheese Noir":
                                            dark-brown base with dark cheese holes + gold text, to match
                                            the dark mockup. !important beats the stock brand gradient. */
  background:
    radial-gradient(circle at 18% 34%, rgba(0,0,0,.40) 7px,  transparent 8px),
    radial-gradient(circle at 62% 70%, rgba(0,0,0,.34) 9px,  transparent 10px),
    radial-gradient(circle at 88% 28%, rgba(0,0,0,.36) 6px,  transparent 7px),
    radial-gradient(circle at 38% 60%, rgba(0,0,0,.30) 5px,  transparent 6px),
    linear-gradient(135deg, #1a1206, #3a2a08) !important;
  color: #f5c542;
}
/* info-bar text stays gold on the noir bar; muted bits a touch dimmer */
body.q-redesign .player-info-bar,
body.q-redesign .player-info-bar #playerScoreDisplay,
body.q-redesign .player-info-bar #playerRankDisplay { color: #f5c542; }
body.q-redesign .player-info-bar #playerAccuracyDisplay,
body.q-redesign .player-info-bar .text-muted { color: #c9b87a !important; }

/* =====================================================================
   MCQ ANSWER TILES
   Preferred: renderer adds class "q-tile" to each option button and a
   <span class="q-tile__letter"> for the A/B/C/D chip.
   Fallback (no JS change): the `#choices .btn` block below styles the
   stock Bootstrap buttons and generates letters with a CSS counter.
   ===================================================================== */

/* --- preferred: explicit q-tile hook --- */
body.q-redesign #qArea .q-tile {
  display: flex; align-items: center; gap: 10px;
  min-height: 56px; padding: 0 14px;
  border: none; border-radius: 12px;
  font-size: 17px; font-weight: 800; line-height: 1.12; text-align: left;
  color: #fff; box-shadow: 0 3px 0 rgba(0,0,0,.25);
  width: 100%;
}
body.q-redesign #qArea .q-tile__letter {
  flex: 0 0 auto; width: 30px; height: 30px; border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,.22);
  font-family: var(--q-display); font-size: 17px; font-weight: 900;
}
body.q-redesign #qArea .q-tile:nth-of-type(6n+1){ background: var(--tile-a); }
body.q-redesign #qArea .q-tile:nth-of-type(6n+2){ background: var(--tile-b); }
body.q-redesign #qArea .q-tile:nth-of-type(6n+3){ background: var(--tile-c); color:#1a1206; }
body.q-redesign #qArea .q-tile:nth-of-type(6n+3) .q-tile__letter{ color:#1a1206; }
body.q-redesign #qArea .q-tile:nth-of-type(6n+4){ background: var(--tile-d); }
body.q-redesign #qArea .q-tile:nth-of-type(6n+5){ background: var(--tile-e); }
body.q-redesign #qArea .q-tile:nth-of-type(6n+6){ background: var(--tile-f); }
/* selected state — renderer toggles .is-selected */
body.q-redesign #qArea .q-tile.is-selected {
  box-shadow: 0 0 0 4px #fff, 0 0 18px rgba(0,0,0,.4);
  transform: scale(.99);
}

/* --- fallback: style raw #choices buttons, letters via counter --- */
body.q-redesign #qArea #choices { counter-reset: qopt; display:flex; flex-direction:column; gap:9px; }
body.q-redesign #qArea #choices .btn {
  counter-increment: qopt;
  position: relative; text-align: left; padding-left: 56px;
  min-height: 56px; border: none; border-radius: 12px;
  font-size: 17px; font-weight: 800; color:#fff;
  box-shadow: 0 3px 0 rgba(0,0,0,.25);
}
body.q-redesign #qArea #choices .btn::before {
  content: counter(qopt, upper-alpha);
  position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
  width: 30px; height: 30px; border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,.22);
  font-family: var(--q-display); font-weight: 900; font-size: 17px;
}
body.q-redesign #qArea #choices .btn:nth-of-type(6n+1){ background: var(--tile-a); }
body.q-redesign #qArea #choices .btn:nth-of-type(6n+2){ background: var(--tile-b); }
body.q-redesign #qArea #choices .btn:nth-of-type(6n+3){ background: var(--tile-c); color:#1a1206; }
body.q-redesign #qArea #choices .btn:nth-of-type(6n+4){ background: var(--tile-d); }
body.q-redesign #qArea #choices .btn:nth-of-type(6n+5){ background: var(--tile-e); }
body.q-redesign #qArea #choices .btn:nth-of-type(6n+6){ background: var(--tile-f); }

/* =====================================================================
   LIVE MCQ / MULTI-TAP / ORDERING TILES  — this app's REAL markup
   ---------------------------------------------------------------------
   The blocks above target #qArea #choices .btn, but the LIVE renderer
   (static/js/player/answer-renderers.js) builds:
       <div class="answer-tiles-container">
         <div class="answer-tile"><span class="answer-label">A</span>
                                   <span class="answer-text">…</span></div>
   …NOT #qArea #choices — so the rules above are inert here and THESE are
   what actually reskin the answers.
   Reveal/lock states (.correct / .incorrect / .go-wide-first-choice) are
   EXCLUDED from the color-coding so "Reveal Answer" still paints green/red
   and Going-Wide keeps its locked look. .answer-tile is unique to the
   question UI — no minigame uses it — so this stays minigame-safe.
   ===================================================================== */
body.q-redesign .answer-tiles-container .answer-tile {
  border: none;
  border-radius: 12px;
  color: #fff;
  box-shadow: 0 3px 0 rgba(0,0,0,.28);
}
body.q-redesign .answer-tiles-container .answer-tile:not(.correct):not(.incorrect):not(.go-wide-first-choice):nth-of-type(6n+1){ background: var(--tile-a); }
body.q-redesign .answer-tiles-container .answer-tile:not(.correct):not(.incorrect):not(.go-wide-first-choice):nth-of-type(6n+2){ background: var(--tile-b); }
body.q-redesign .answer-tiles-container .answer-tile:not(.correct):not(.incorrect):not(.go-wide-first-choice):nth-of-type(6n+3){ background: var(--tile-c); color:#1a1206; }
body.q-redesign .answer-tiles-container .answer-tile:not(.correct):not(.incorrect):not(.go-wide-first-choice):nth-of-type(6n+4){ background: var(--tile-d); }
body.q-redesign .answer-tiles-container .answer-tile:not(.correct):not(.incorrect):not(.go-wide-first-choice):nth-of-type(6n+5){ background: var(--tile-e); }
body.q-redesign .answer-tiles-container .answer-tile:not(.correct):not(.incorrect):not(.go-wide-first-choice):nth-of-type(6n+6){ background: var(--tile-f); }
/* the A/B/C/D letter → a contrasting chip */
body.q-redesign .answer-tiles-container .answer-label {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; min-width: 34px; flex: none;
  border-radius: 8px; background: rgba(0,0,0,.22); color: inherit;
  font-family: var(--q-display); font-weight: 900;
}
body.q-redesign .answer-tiles-container .answer-text { color: inherit; }
/* selected/clicked → ONE uniform DARKER SHADE for every tile type (owner 2026-07-03):
   MCQ, first-letter (alpha) and multi-tap "all that apply" all look IDENTICAL when
   tapped — a dimmed dark tile, NOT a bright highlight, and with no special accent on
   the most-recently-tapped tile. A single rule keeps the three types from drifting.
   Multi-tap accumulates (each tap stays dark); MCQ/alpha swap the single selection —
   either way every tapped tile shows the same shade. Reveal states still win. */
body.q-redesign .answer-tiles-container .answer-tile.selected:not(.correct):not(.incorrect),
body.q-redesign .answer-tiles-container[data-question-type="multi-tap"] .answer-tile.selected:not(.correct):not(.incorrect),
body.q-redesign .letter-tile.selected {
  background: #140e04 !important;
  color: rgba(255,255,255,.5) !important;
  box-shadow: inset 0 0 0 2px rgba(255,255,255,.10), inset 0 3px 9px rgba(0,0,0,.6) !important;
  filter: none !important;
  transform: none !important;
}
/* keep the A/B/C/D letter chip subtle on a darkened tile so nothing "pops" */
body.q-redesign .answer-tiles-container .answer-tile.selected:not(.correct):not(.incorrect) .answer-label {
  background: rgba(255,255,255,.10);
}

/* Multi-tap keeps position:relative (reveal badges etc. anchor to it); the old bright
   gold+white frame / scale / ✓ badge is GONE — the shared darker shade above is the
   single "locked in" signal, identical on every tapped tile (owner 2026-07-03). */
body.q-redesign .answer-tiles-container[data-question-type="multi-tap"] .answer-tile {
  position: relative;
  transition: background .12s ease, box-shadow .12s ease;
}

/* =====================================================================
   NUMERIC KEYPAD — live markup (answer-renderers.js):
     .numeric-container > .numeric-display
                        > .numeric-keypad > .numeric-key (.backspace/.submit)
   SCOPED to .numeric-container on purpose: the Math minigame reuses
   .numeric-key/.numeric-display inside #mathGameInterface, so a bare
   .numeric-key rule would bleed into it. This cannot.
   Only colors/font/radius are restyled — the keypad GRID layout and the
   responsive key sizing from style.css are left intact.
   ===================================================================== */
body.q-redesign .numeric-container .numeric-display {
  background: var(--q-card); border: 2px solid var(--q-gold); color:#fff;
  font-family: var(--q-display); font-weight: 900; border-radius: 12px;
}
/* Bigger keys that fill the available height (the container is fixed top..bottom): let the keypad
   grow and the rows share the space equally, so number buttons are large + easy to press. */
body.q-redesign .numeric-container { gap: 12px; }
body.q-redesign .numeric-container .numeric-keypad {
  flex: 1 1 auto; grid-auto-rows: 1fr; gap: 12px;
}
body.q-redesign .numeric-container .numeric-keypad .numeric-key {
  /* Lighter slate face + a clearly-visible border + a little depth so each key reads as a raised
     button against the near-black question background (owner 2026-07-10: keys were too dark to see). */
  background: linear-gradient(180deg, #454556, #343442);
  border: 1px solid rgba(255,255,255,.30);
  color:#fff; font-family: var(--q-display); font-weight: 800; border-radius: 14px;
  height: auto; min-height: 64px; font-size: clamp(30px, 9vw, 44px);
  box-shadow: 0 2px 0 rgba(0,0,0,.45), inset 0 1px 0 rgba(255,255,255,.10);
}
/* Backspace reads as a distinct "delete" key — a warm brick tint, not another grey slate. */
body.q-redesign .numeric-container .numeric-keypad .numeric-key.backspace {
  background: linear-gradient(180deg, #6f4a44, #513532); border-color: rgba(255,255,255,.24);
}
/* Submit is now a same-size tile in the bottom-right of the pad (owner 2026-07-10): keep it
   unmistakably GREEN and shrink the label so "Submit" fits the 1/3-width key. */
body.q-redesign .numeric-container .numeric-keypad .numeric-key.submit {
  background: var(--tile-d); border: none; color: #fff;
  font-size: clamp(15px, 4.2vw, 22px); letter-spacing: .01em;
}
/* Submit Answer CTA stays clearly GREEN under the dark q-redesign theme. */
body.q-redesign .numeric-container .numeric-submit-cta {
  background: #28a745; border: 1px solid #1e7e34; color:#fff;
  font-size: clamp(20px, 5.5vw, 26px); min-height: 60px; border-radius: 14px;
}
body.q-redesign .numeric-container .numeric-submit-cta:disabled { background:#4a5a4f; border-color:#3a463d; }

/* =====================================================================
   TEXT / FILL-BLANK / MATCHING / IMAGE-CHOICE / IMAGE-TILES
   live markup: every one of these renders inside .qtui-wrap
   (answer-renderers.js). .qtui-wrap is question-only — no minigame uses
   it (verified) — so scoping under it is minigame-safe. The on-screen
   QWERTY is not in the renderer; the native keyboard + .fb-input field
   covers text/short-answer questions.
   ===================================================================== */
/* shared submit button + hint */
body.q-redesign .qtui-wrap .qtui-submit {
  background: var(--q-gold); color:#1a1206; border:none;
  font-family: var(--q-display); font-weight: 900; border-radius: 11px;
}
body.q-redesign .qtui-wrap .qtui-hint { color:#b9b9c7; }
/* text + fill-blank input fields */
body.q-redesign .qtui-wrap .fb-input {
  background: var(--q-card); border: 2px solid var(--q-gold); color:#fff;
  font-weight: 800; border-radius: 12px;
}
/* matching */
body.q-redesign .qtui-wrap .match-col h4 { color: var(--q-gold); font-family: var(--q-display); }
body.q-redesign .qtui-wrap .match-item {
  background: var(--q-card); border: 2px solid #2f2f3d; color:#fff;
  font-weight: 800; border-radius: 11px;
}
/* image choice (a matched/selected tile keeps its JS tint / .sel ring) */
body.q-redesign .qtui-wrap .imgc-tile {
  background: var(--q-card); border: 2px solid #2f2f3d; border-radius: 12px; overflow: hidden;
}
body.q-redesign .qtui-wrap .imgc-tile.sel { box-shadow: 0 0 0 4px #fff; border-color:#fff; }
body.q-redesign .qtui-wrap .imgc-badge {
  background: rgba(0,0,0,.45); color:#fff; font-family: var(--q-display); font-weight: 900;
}
body.q-redesign .qtui-wrap .imgc-label { color:#fff; font-weight: 700; }

/* Ordering tiles use .answer-tile.ordering-tile — already reskinned by the
   .answer-tiles-container .answer-tile rules above. */

/* =====================================================================
   FASTEST POPUP — large player image + TIME + POINTS
   (#playerFast is OUTSIDE #qArea, so it is named explicitly here.)
   ===================================================================== */
body.q-redesign #playerFast .fastest-player-card {
  background: radial-gradient(circle at 50% 22%, #3a2a08, #0c0a06);
  color: #fff; border-radius: 22px;
}
body.q-redesign #playerFast .fastest-img {
  width: 220px; height: 220px; border-radius: 50%;
  object-fit: cover; border: 4px solid var(--q-gold);
  box-shadow: 0 8px 24px rgba(0,0,0,.45);
}
body.q-redesign #playerFast .fastest-team-name {
  font-family: var(--q-display); font-weight: 900; color:#fff;
}

/* Fast Track epic layers (cheese rain / fireworks / confetti) are added by
   fast-track-popup.js using the keyframes below + the existing confetti lib. */
@keyframes qFtCheeseFall   { 0%{transform:translateY(-60px) rotate(0);opacity:0}8%{opacity:1}100%{transform:translateY(640px) rotate(360deg);opacity:.9} }
@keyframes qFtPulse        { 0%,100%{transform:scale(1)}50%{transform:scale(1.06)} }
@keyframes qFtRing         { 0%{transform:scale(.6);opacity:.9}100%{transform:scale(2.4);opacity:0} }

/* =====================================================================
   ANNOUNCE FASTEST — stat pills injected by fastest-popup-enhance.js
   ===================================================================== */
body.q-redesign #playerFast .fastest-player-card {
  background: radial-gradient(circle at 50% 22%, #3a2a08, #0c0a06);
  border-radius: 22px; color: #fff;
}
body.q-redesign #playerFast .fastest-title {
  font-family: var(--q-display); font-weight: 900; color: #f5c542;
  letter-spacing: 1px;
}
body.q-redesign #playerFast .fastest-img {        /* large round avatar */
  width: 220px; height: 220px; border-radius: 50%;
  object-fit: cover; border: 4px solid var(--q-gold);
  box-shadow: 0 8px 24px rgba(0,0,0,.45);
}
body.q-redesign #playerFast .q-fast-stats {
  display: flex; gap: 10px; width: 100%; margin: 14px 0 6px;
}
body.q-redesign #playerFast .q-fast-pill {
  flex: 1 1 0; background: rgba(0,0,0,.28); border-radius: 14px;
  padding: 12px 8px; text-align: center;
}
body.q-redesign #playerFast .q-fast-pill__l {
  display: block; font-size: 10px; font-weight: 800; letter-spacing: 1px;
  color: rgba(255,255,255,.7);
}
body.q-redesign #playerFast .q-fast-pill__v {
  display: block; font-family: var(--q-display); font-weight: 900;
  font-size: 26px; line-height: 1; margin-top: 3px;
}

/* =====================================================================
   FAST TRACK — epic theme (.q-ft set by fast-track-popup-enhance.js)
   ===================================================================== */
body.q-redesign .q-ft .popup-card,
body.q-redesign .q-ft .ft-card,
body.q-redesign .q-ft .fastest-player-card {
  position: relative; overflow: hidden;
  background: radial-gradient(circle at 50% 30%, #7a2400, #1a0600 75%);
  border-radius: 22px; color: #fff;
}
body.q-redesign .q-ft .q-ft-fx {
  position: absolute; inset: 0; pointer-events: none; z-index: 0;
}
body.q-redesign .q-ft .q-ft-cheese {
  position: absolute; top: -40px;
  animation: qFtCheeseFall linear infinite;
  filter: drop-shadow(0 2px 3px rgba(0,0,0,.4));
}
body.q-redesign .q-ft .q-ft-fw {
  position: absolute; width: 5px; height: 5px; border-radius: 50%;
  background: var(--c); box-shadow: 0 0 14px 5px var(--c);
  animation: qFtBurst 1.8s ease-out infinite;
}
@keyframes qFtBurst { 0%{transform:scale(0);opacity:0}30%{opacity:1}70%{opacity:.8}100%{transform:scale(1);opacity:0} }
body.q-redesign .q-ft .fastest-title,
body.q-redesign .q-ft .popup-title {
  position: relative; z-index: 1;
  font-family: var(--q-display); font-weight: 900; font-size: 26px;
  color: #ffce6b; text-shadow: 0 2px 12px rgba(255,120,40,.7);
  animation: qFtPulse 1.1s ease-in-out infinite;
}
body.q-redesign .q-ft .q-ft-avatar { position: relative; z-index: 1; }
body.q-redesign .q-ft .q-ft-ring {
  position: absolute; left: 50%; top: 50%; width: 150px; height: 150px;
  margin: -75px 0 0 -75px; border-radius: 50%; border: 3px solid #ffce6b;
  animation: qFtRing 1.6s ease-out infinite; pointer-events: none; z-index: 0;
}

/* =====================================================================
   SPIN WHEEL POPUP — theme (.q-wheel set by wheel-popup-enhance.js)
   The 3D wheel itself (#wheel3dPlayer) is rendered by wheel-3d.js and is
   intentionally NOT restyled here.
   ===================================================================== */
body.q-redesign #playerWheelDisplay.q-wheel {
  background: rgba(8,8,14,.72); backdrop-filter: blur(4px);
}

/* =====================================================================
   WHEEL FREEZE FIX (mobile) — the player wheel overlay carried THREE
   stacked full-viewport backdrop-filter blurs (wheel-styles.css blur(5px),
   theme.css .wheel-popup-overlay blur(6px)!important, and the .q-wheel
   blur(4px) above). Compositing a live backdrop blur over the 11-layer
   preserve-3d cylinder froze the phone's main thread on the SHOW frame.
   The overlay backgrounds are already near-opaque, so we drop the live
   backdrop entirely and use a solid panel — no visible change, no GPU stall.
   Scoped to the PLAYER (#playerWheelDisplay under body.q-redesign); the big
   screen uses #wheelDisplay and is never under body.q-redesign, so unaffected.
   ===================================================================== */
body.q-redesign #playerWheelDisplay,
body.q-redesign #playerWheelDisplay.q-wheel {
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
  background: #07080e !important;   /* opaque — replaces the 3 translucent+blur layers */
}

/* CRITICAL (2026-06-23): the rule above only clears the OVERLAY itself. A live backdrop blur on a
   DESCENDANT — theme.css `.wheel-popup-overlay{backdrop-filter:blur(6px)!important}` and
   wheel-styles.css `.wheel-container{backdrop-filter:blur(5px)}` both sit on CHILDREN of
   #playerWheelDisplay — still composites over the 11-layer preserve-3d cylinder and hangs the phone's
   paint on the SHOW frame (the player log freezes right AFTER the JS finishes = a paint stall, and the
   host big screen paints the SAME cylinder fine precisely because it has NO backdrop blur). Kill
   backdrop-filter on EVERY descendant so the player wheel composites exactly like the working big
   screen. The overlay is opaque, so the blurs were invisible anyway — zero visual change. */
body.q-redesign #playerWheelDisplay * {
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
}

/* Mobile / touch only: drop the live-compositing per-segment shadow+transition
   and the infinite winner-pulse. The gradient fills + the rotateX preserve-3d
   cylinder are KEPT, so the wheel still looks and spins the same. Fine-pointer
   devices (the big screen / desktop) are NOT matched and keep the full effect. */
@media (pointer: coarse) {
  body.q-redesign #playerWheelDisplay .wheel-3d__segment-inner {
    box-shadow: none;
    transition: none;
  }
  body.q-redesign #playerWheelDisplay .wheel-3d__segment-inner.winner {
    box-shadow: 0 0 16px rgba(255, 215, 0, 0.7);
    animation: none;   /* no per-frame infinite pulse on the phone */
  }
}
body.q-redesign #playerWheelDisplay.q-wheel .popup-card {
  background: #101018; border-radius: 22px; color: #fff;
  box-shadow: 0 18px 50px rgba(0,0,0,.55);
}
body.q-redesign #playerWheelDisplay.q-wheel .popup-title {
  font-family: var(--q-display); font-weight: 900; color: var(--q-gold);
}
body.q-redesign #playerWheelDisplay.q-wheel #btnPlayerSpin {
  background: var(--tile-d); border: none;
  font-family: var(--q-display); font-weight: 900;
}
body.q-redesign #playerWheelDisplay.q-wheel #btnPlayerPass {
  background: var(--q-gold); color: #1a1206; border: none;
  font-family: var(--q-display); font-weight: 900;
}
body.q-redesign #playerWheelDisplay.q-wheel .wheel-result-card {
  background: linear-gradient(135deg, #3a2a08, #1a1206); border-radius: 16px;
}
body.q-redesign #playerWheelDisplay .wheel-result-text { color: #f5c542; }
body.q-redesign #playerWheelDisplay .q-pop { animation: qWheelPop .5s cubic-bezier(.2,1.4,.5,1); }
@keyframes qWheelPop { 0%{transform:scale(.7);opacity:0}60%{transform:scale(1.1)}100%{transform:scale(1);opacity:1} }

/* ── 3D wheel GPU DIET for the player phone (host big screen keeps the full effect) ──────────
   PROVEN cause of the freeze: the cylinder builds instantly, then locks the phone on the SHOW
   *paint*. wheel-3d.css gives every segment backface-visibility:visible → 13 segments paint BOTH
   faces = ~26 composited preserve-3d layers, each a gradient+shadow. The host GPU eats it; the
   phone can't. HALVE it: only front-facing segments paint, and flatten each to a solid fill + no
   shadow. Scoped to #wheel3dPlayer so the host display is byte-for-byte unchanged. */
body.q-redesign #wheel3dPlayer .wheel-3d__segment {
  -webkit-backface-visibility: hidden !important;
  backface-visibility: hidden !important;
}
body.q-redesign #wheel3dPlayer .wheel-3d__segment-inner {
  background: var(--segment-color, #3498db) !important;   /* flat fill, not a 2-stop gradient */
  box-shadow: none !important;
  transition: none !important;
  text-shadow: none !important;
}

/* =====================================================================
   FULL DARK SCREEN  — the whole player screen base goes dark (mockup #101018).
   The background + default text color are set globally, but MINIGAMES are
   SHIELDED: every #*GameInterface keeps its own light card + dark text, so a
   white default never lands on a white minigame card. Answer-tile / reveal /
   popup colors set earlier all win on their own higher-specificity rules.
   ===================================================================== */
body.q-redesign { background: var(--q-bg); color: var(--q-ink); }
body.q-redesign .player-scroll { background: transparent; }

/* generic panels (lobby / session / join cards) darken to match the theme */
body.q-redesign .card {
  background: var(--q-card); color: var(--q-ink); border-color: #2a2a38;
}

/* ...but minigame interfaces keep their designed LIGHT look + dark text.
   [id$="GameInterface"] matches #simonGameInterface, #mathGameInterface, ... */
body.q-redesign [id$="GameInterface"] { color: var(--text-dark, #111827); }
body.q-redesign [id$="GameInterface"] .card {
  background: var(--surface-light, #fff); color: var(--text-dark, #111827);
  border-color: var(--border-light, #e0e0e0);
}

/* question prompt + number sit directly on the dark base */
body.q-redesign #questionText,
body.q-redesign .question-text { color: var(--q-ink); }
body.q-redesign #qn-number { color: #8a8a9a !important; }   /* beats Bootstrap .text-muted !important */
body.q-redesign .question-metadata { color: #8a8a9a; }
body.q-redesign .question-meta-badge {
  background: var(--q-card); color: var(--q-ink); border-color: var(--q-gold);
}

/* =====================================================================
   TIMER RING  — conic-gradient countdown (mockup: 40px gold ring, dark
   inner disc, gold seconds). Built + driven by timer-ring.js from the
   timer_* socket events. The legacy "⏱️ Xs" text + bottom progress bar
   are hidden when q-redesign is on (the ring replaces them).
   ===================================================================== */
body.q-redesign #playerTimerDisplay { display: none !important; }      /* old "⏱️ Xs" text in the bar */
body.q-redesign #timerDisplay { display: none !important; }            /* old fixed bottom progress bar */
body.q-redesign #timer.legacy-ui-element { display: none !important; } /* old badge + progress */
body.q-redesign .q-timer-ring {
  width: 40px; height: 40px; border-radius: 50%; flex: 0 0 auto;
  display: none; align-items: center; justify-content: center;
  margin-left: 8px;
  background: conic-gradient(#f5c542 0%, rgba(255,255,255,.22) 0%);
}
body.q-redesign .q-timer-ring__inner {
  width: 31px; height: 31px; border-radius: 50%; background: #1a1206;
  display: flex; align-items: center; justify-content: center;
}
body.q-redesign .q-timer-ring__num {
  font-family: var(--q-display); font-weight: 900; font-size: 15px; color: #f5c542;
  line-height: 1;
}
/* Final-seconds shake ONLY (added by timer-ring.js when rem<=3). The ring is otherwise perfectly
   still — the old continuous scale "throb" read as constant jiggle and was distracting. This is a
   small side-to-side nudge that fires just for the count-down-to-zero moment, then stops. */
body.q-redesign .q-timer-ring--low { animation: qRingShake .5s ease-in-out infinite; }
@keyframes qRingShake {
  0%, 100% { transform: translateX(0); }
  25%      { transform: translateX(-1.5px); }
  75%      { transform: translateX(1.5px); }
}

/* =====================================================================
   SCORE DRAWER  — dark-theme the EXISTING drawer (#scoreboardDrawer, opened
   by tapping the info bar) + the chrome injected by score-drawer-enhance.js
   (pull handle, identity row, 3 stat pills). Position/animation unchanged.
   ===================================================================== */
body.q-redesign .scoreboard-drawer-overlay { background: rgba(0,0,0,.55); backdrop-filter: blur(3px); }
body.q-redesign .scoreboard-drawer {
  background: #101018; color: var(--q-ink);
  /* convert the existing TOP sheet into a bottom sheet (mockup). Reuses the
     existing `.active` class toggle for open/close — just reversed direction. */
  top: auto; bottom: 0; left: 0; right: 0; max-width: 520px; margin: 0 auto;
  border-radius: 22px 22px 0 0;
  max-height: 88vh;
  transform: translateY(100%);
  box-shadow: 0 -10px 30px rgba(0,0,0,.5);
}
body.q-redesign .scoreboard-drawer.active { transform: translateY(0); }
/* injected chrome */
body.q-redesign .q-drawer-head { padding: 4px 2px 2px; }
body.q-redesign .q-drawer-handle {
  width: 40px; height: 4px; border-radius: 3px; background: #3a3a48; margin: 0 auto 12px;
}
body.q-redesign .q-drawer-id { display: flex; align-items: center; gap: 11px; margin-bottom: 12px; }
body.q-redesign .q-drawer-avatar {
  width: 46px; height: 46px; border-radius: 13px; flex: 0 0 auto;
  background: linear-gradient(135deg, #f2a900, #d98800);
  display: flex; align-items: center; justify-content: center; font-size: 24px;
}
body.q-redesign .q-drawer-idtext { flex: 1; min-width: 0; }
body.q-redesign .q-drawer-name {
  font-family: var(--q-display); font-weight: 900; font-size: 17px; color: #fff;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
body.q-redesign .q-drawer-rank { font-size: 11px; color: #8a8a9a; font-weight: 700; }
body.q-redesign .q-drawer-x {
  width: 30px; height: 30px; border-radius: 9px; flex: 0 0 auto;
  background: #23232f; color: #fff; font-size: 16px; font-weight: 900;
  display: flex; align-items: center; justify-content: center; cursor: pointer;
}
body.q-redesign .q-drawer-pills { display: flex; gap: 7px; margin-bottom: 14px; }
body.q-redesign .q-pill {
  flex: 1 1 0; background: #1b1b26; border-radius: 12px; padding: 12px 8px; text-align: center;
}
body.q-redesign .q-pill-v { font-family: var(--q-display); font-weight: 900; font-size: 22px; line-height: 1; }
body.q-redesign .q-pill-l { font-size: 9px; font-weight: 800; letter-spacing: .8px; color: #8a8a9a; margin-top: 4px; }
/* existing drawer content → dark */
body.q-redesign #scoreboardContent { color: var(--q-ink); }
body.q-redesign .scoreboard-drawer .scoreboard-session-info,
body.q-redesign .scoreboard-drawer .scoreboard-session-info * { color: #cfcfe0; }
body.q-redesign .scoreboard-drawer .scoreboard-entry,
body.q-redesign .scoreboard-drawer .scoreboard-row,
body.q-redesign .scoreboard-drawer .scoreboard-player {
  background: #1b1b26; color: #fff; border-radius: 10px;
}
body.q-redesign .scoreboard-drawer .current-player {
  background: linear-gradient(135deg, #3a2a08, #1a1206) !important; color: #f5c542 !important;
}
/* exit + close buttons */
body.q-redesign .scoreboard-drawer-exit {
  background: #2a1414 !important; color: #ff6b6b !important;
  box-shadow: inset 0 0 0 1.5px rgba(255,107,107,.35);
}
body.q-redesign .scoreboard-drawer-close { background: #23232f !important; color: #fff !important; }

/* =====================================================================
   FIXES (round 2) — observed on the REAL new-UI question screen
   ---------------------------------------------------------------------
   The live question text is #questionText inside #questionHeaderContainer
   (set by mobile-layout.js), NOT #qArea/#questionText placeholder. That
   container had a WHITE background, so the white question text was
   invisible. Dark-theme the whole question-header band.
   ===================================================================== */
body.q-redesign #questionHeaderContainer,
body.q-redesign .question-header-container {
  background: var(--q-bg) !important; color: var(--q-ink);
  border: none !important; box-shadow: none !important;
}
body.q-redesign #questionText,
body.q-redesign .question-text {
  color: var(--q-ink) !important; background: transparent !important;
}
body.q-redesign #questionMetadata,
body.q-redesign .question-metadata { background: transparent !important; color: #8a8a9a; }
body.q-redesign #questionTextPopup .modal-content,
body.q-redesign #questionTextPopupText { background: #101018 !important; color: var(--q-ink) !important; }

/* HEADER → match the mockup: drop accuracy + rank (they live in the drawer
   now) and emphasize the Q-counter + score, keeping the timer ring at right. */
body.q-redesign .player-info-bar #playerAccuracyDisplay,
body.q-redesign .player-info-bar #playerRankDisplay { display: none !important; }
body.q-redesign .player-info-bar #questionCounterDisplay {
  font-family: var(--q-display); font-weight: 900; font-size: 14px; color: #f5c542;
  background: rgba(0,0,0,.18); border-radius: 8px; padding: 2px 8px;
}
body.q-redesign .player-info-bar #playerScoreDisplay {
  font-family: var(--q-display); font-weight: 900; font-size: 18px; color: #f5c542;
}
body.q-redesign .player-info-bar #playerNameDisplay {
  font-size: 11px; font-weight: 700; color: #c9b87a;
}

/* ANSWER TILES → only the real options, and they FILL the answer area.
   data-answer-text is the REAL answer (set even while the text is hidden as
   "—" pre-reveal), so this hides ONLY genuinely-empty slots, never A–D. */
body.q-redesign .answer-tiles-container .answer-tile[data-answer-text=""]:not(.go-wide-available):not(.go-wide-first-choice):not(.going-wide-second):not(.ordering-tile) { display: none !important; }
body.q-redesign .answer-tiles-container {
  display: flex; flex-direction: column; gap: 10px;
  flex: 1 1 auto; min-height: 0; padding: 10px 14px 14px;
}
body.q-redesign .answer-tiles-container .answer-tile { flex: 1 1 auto; }

/* =====================================================================
   FIXES (round 3) — remaining un-themed question types, found by
   rendering each type through the REAL renderer and detecting light
   backgrounds. exact_text spelling keyboard, alpha grid, drag-drop.
   ===================================================================== */
/* exact_text — on-screen spelling keyboard (renders into .numeric-container) */
body.q-redesign .sp-display {
  background: var(--q-card) !important; border: 2px solid var(--q-gold) !important;
  color: #fff !important; border-radius: 12px;
}
/* Letter keys mirror the number-pad keycaps (owner 2026-07-10): a lighter slate face, a
   clearly-visible rim and a little depth, so each letter reads as a raised, well-separated
   button against the near-black question screen instead of a flat dark tile. */
body.q-redesign .sp-key {
  background: linear-gradient(180deg, #454556, #343442) !important;
  border: 1px solid rgba(255,255,255,.30) !important;
  color: #fff !important; font-family: var(--q-display); font-weight: 800;
  border-radius: 12px !important; font-size: clamp(20px, 6vw, 28px) !important;
  box-shadow: 0 2px 0 rgba(0,0,0,.45), inset 0 1px 0 rgba(255,255,255,.10) !important;
}
body.q-redesign .sp-key:active {
  background: linear-gradient(180deg, #3a3a49, #2b2b37) !important;
  box-shadow: 0 1px 0 rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.06) !important;
}
/* Backspace — the same warm-brick "delete" tint as the number pad, so it's instantly findable. */
body.q-redesign .sp-key-wide {
  background: linear-gradient(180deg, #6f4a44, #513532) !important;
  border: 1px solid rgba(255,255,255,.24) !important; color: #fff !important;
}
/* Space — full-width slate keycap with a smaller, spaced label. */
body.q-redesign .sp-key-space {
  background: linear-gradient(180deg, #454556, #343442) !important;
  border: 1px solid rgba(255,255,255,.30) !important; color: #fff !important;
  font-size: clamp(13px, 3.5vw, 16px) !important; letter-spacing: .12em;
}

/* alpha — the A–Z "first letter" grid. Bigger, clearer keys (matches the numeric-pad treatment):
   a brighter outline so each letter is visually distinct, more gap between tiles, larger glyphs. */
body.q-redesign .letter-tile {
  /* Cheese-gold key faces so the letters pop off the dark background (owner 2026-07-10) —
     dark-brown glyphs on a warm gold wedge, unmistakable against the near-black question screen. */
  background: linear-gradient(160deg, #ffd451, #f2a900) !important; color: #241802 !important;
  border: 1px solid #b77c00 !important;   /* darker gold rim keeps each tile crisply separated */
  border-radius: 12px; font-size: clamp(30px, 9.5vw, 50px);   /* owner 2026-07-02: bigger letters in the squares */
  text-shadow: 0 1px 0 rgba(255,255,255,.28);
  box-shadow: 0 2px 6px rgba(0,0,0,.35);
}
body.q-redesign .letter-tile.combined-tile { font-size: clamp(18px, 6vw, 30px); }
body.q-redesign .alpha-tiles-container { gap: 9px; }
body.q-redesign .alpha-tile-row { gap: 9px; }
/* .letter-tile.selected → unified darker-shade rule near the top (owner 2026-07-03); no gold highlight. */

/* drag_drop — draggable items + drop zones (.dd-item was light) */
body.q-redesign .qtui-wrap .dd-item,
body.q-redesign .qtui-wrap .dd-chip {
  background: var(--q-card) !important; color: #fff !important; border: 2px solid #2f2f3d !important;
}
body.q-redesign .qtui-wrap .dd-zone {
  background: #15151d !important; color: #cfcfe0 !important; border: 2px dashed #3a3a48 !important;
}

/* =====================================================================
   FIXES (round 4) — owner playtest
   ---------------------------------------------------------------------
   (a) The question-header band + answer area sit on white surfaces from
       style.css; make sure nothing white shows behind/around the tiles.
   (b) Drawer leaderboard: .scoreboard-session-info has a LIGHT (#f8f9fa)
       background and the score span is BLUE (var(--brand) #667eea) / rank
       gray — unreadable on the dark sheet. Fix bg + span colors.
   (c) Tiles fill more: the answer tiles are position:fixed reserving 124px
       for the header + 75px at the bottom; the redesigned header is compact
       and the legacy bottom timer bar is hidden, so reclaim that space.
   ===================================================================== */

/* (a) no white behind the tiles — the question header + answer/legacy areas */
body.q-redesign .question-header-container,
body.q-redesign #questionHeaderContainer {
  background: var(--q-bg) !important; border-bottom: 1px solid #23232f !important;
}
body.q-redesign .answer-tiles-container { background: var(--q-bg); }
body.q-redesign #qArea { background: var(--q-bg) !important; }
/* The outer scroll shells stay TRANSPARENT so the cheese ::before shows through.
   They were forced opaque to prevent white bleed, but the cheese layer is itself a
   full-screen dark backdrop, so "no white" is preserved. The actual content
   surfaces (#qArea, .question-header-container, .answer-tiles-container above)
   keep their solid --q-bg for tile/text contrast. */
body.q-redesign main,
body.q-redesign #main-content,
body.q-redesign .player-scroll { background: transparent !important; }

/* (b) drawer leaderboard readability */
body.q-redesign .scoreboard-drawer .scoreboard-session-info {
  background: #1b1b26 !important; border: 1px solid #2a2a38 !important;
}
body.q-redesign .scoreboard-drawer .scoreboard-session-info,
body.q-redesign .scoreboard-drawer .scoreboard-session-info * { color: #cfcfe0 !important; }
body.q-redesign .scoreboard-drawer .scoreboard-session-info h6,
body.q-redesign .scoreboard-drawer h6 { color: #f5c542 !important; }
body.q-redesign .scoreboard-drawer hr { border-color: #2a2a38 !important; opacity: 1; }
body.q-redesign .scoreboard-drawer .scoreboard-entry {
  background: #1b1b26 !important; border: 1px solid #2a2a38 !important; color: #fff !important;
}
body.q-redesign .scoreboard-drawer .scoreboard-entry .rank { color: #8a8a9a !important; }
body.q-redesign .scoreboard-drawer .scoreboard-entry .team-name { color: #fff !important; }
body.q-redesign .scoreboard-drawer .scoreboard-entry .score { color: #f5c542 !important; }
body.q-redesign .scoreboard-drawer .scoreboard-entry.current-player,
body.q-redesign .scoreboard-drawer .scoreboard-entry.current-player .team-name,
body.q-redesign .scoreboard-drawer .scoreboard-entry.current-player .score { color: #f5c542 !important; }

/* (c) tiles fill more — shrink the reserved header/bottom bands (compact dark header,
   no legacy bottom timer bar). Long question text still opens the tap-to-expand popup. */
body.q-redesign { --player-question-header-height: 124px; --player-bottom-controls-height: 22px; }

/* dark scrollbar inside the drawer (the default light one stood out) */
body.q-redesign .scoreboard-drawer::-webkit-scrollbar { width: 8px; }
body.q-redesign .scoreboard-drawer::-webkit-scrollbar-thumb { background: #3a3a48; border-radius: 4px; }
body.q-redesign .scoreboard-drawer::-webkit-scrollbar-track { background: transparent; }

/* =====================================================================
   BUZZ + POLL screens — legacy #buzzing-interface (buzz / buzz_verbal
   question types AND the Poll-the-Audience lifeline that follows a buzz).
   These render OUTSIDE #qArea so the dark redesign never reached them:
   grey muted status text, light Bootstrap alert boxes and white vote
   buttons looked un-themed on the dark screen. The poll voting UI lives
   INSIDE #buzzing-interface and reuses .agree-disagree-btn, so scoping
   everything under #buzzing-interface themes BOTH screens at once and
   touches nothing else. The buzz button's own state colours (theme.css)
   and the .voted-selected ✔ state are intentionally left intact.
   ===================================================================== */
body.q-redesign #buzzing-interface { color: var(--q-ink); }

/* headings + status / helper text → readable gold/cream (was #495057 grey) */
body.q-redesign #buzzing-interface h5,
body.q-redesign #buzzing-interface h6 { color: #f5c542 !important; }
body.q-redesign #buzzing-interface #buzzer-status,
body.q-redesign #buzzing-interface .text-muted,
body.q-redesign #buzzing-interface p,
body.q-redesign #buzzing-interface .small { color: #c9b87a !important; }

/* AGREE / DISAGREE + POLL vote buttons → solid brand green / red on dark
   (base .agree-disagree-btn keeps its size, hover + ✔ voted-selected state) */
body.q-redesign #buzzing-interface .agree-disagree-btn { color: #fff !important; }
body.q-redesign #buzzing-interface .btn-success.agree-disagree-btn {
  background: var(--tile-d) !important; border: none !important;
}
body.q-redesign #buzzing-interface .btn-danger.agree-disagree-btn {
  background: var(--tile-a) !important; border: none !important;
}

/* status / info / locked panels → dark themed cards (were light alerts) */
body.q-redesign #buzzing-interface .alert-info,
body.q-redesign #buzzing-interface #poll-status {
  background: rgba(47,125,246,.12) !important;
  border: 1px solid rgba(47,125,246,.40) !important;
  color: #cfe0ff !important;
}
body.q-redesign #buzzing-interface .alert-warning,
body.q-redesign #buzzing-interface #buzzer-locked {
  background: rgba(242,169,0,.12) !important;
  border: 1px solid rgba(242,169,0,.45) !important;
  color: #f5c542 !important;
}
body.q-redesign #buzzing-interface #buzzer-locked h6,
body.q-redesign #buzzing-interface #buzzer-locked p { color: #f5c542 !important; }

/* vote-results bars → dark track + light labels (was .bg-light) */
body.q-redesign #buzzing-interface .bg-light { background: var(--q-card) !important; }
body.q-redesign #buzzing-interface .progress { background: rgba(255,255,255,.08) !important; }
body.q-redesign #buzzing-interface #buzz-vote-results .fw-bold,
body.q-redesign #buzzing-interface #buzzRevealStatus { color: #f1e9d2 !important; }

/* The base `.buzz-enabled` rule paints a SOLID red (#dc3545 !important, style.css:1651) — it was
   meant for the button, but #buzzing-interface ALSO carries .buzz-enabled, so the whole panel
   becomes a red rectangle behind the round buzzer (its !important even beats the intended subtle
   0.12 tint at style.css:2633). Keep ONLY the round red button: container stays transparent. */
body.q-redesign #buzzing-interface,
body.q-redesign #buzzing-interface.buzz-enabled,
body.q-redesign #buzzing-interface.buzz-enabled:hover { background: transparent !important; border-color: transparent !important; }

/* ===== the big BUZZ-IN button — ROUND red "buzzer" to match the mockup (§4):
   a circular button with a red radial gradient + glow rings + white BUZZ. The base
   .buzz-btn is a rounded rectangle; under the redesign we make it a CIRCLE and recolour
   each of buzz-ui-manager's 6 states (disabled/available/sending/accepted/rejected/locked). */
body.q-redesign #buzzing-interface #buzz-btn {
  width: min(66vw, 250px) !important;
  aspect-ratio: 1 / 1 !important;
  height: auto !important;
  min-height: 0 !important;
  border-radius: 50% !important;
  border: none !important;
  margin: 8px auto !important;
  padding: 0 !important;
  display: flex !important;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  font-family: var(--q-display);
  font-weight: 900;
  line-height: 1.05;
  -webkit-tap-highlight-color: transparent;
  transition: transform .12s ease, box-shadow .2s ease;
}
body.q-redesign #buzzing-interface #buzz-btn .buzz-btn-icon  { font-size: 30px; }
body.q-redesign #buzzing-interface #buzz-btn .buzz-btn-label { font-size: 26px; letter-spacing: .5px; }

/* disabled — "Waiting for host" (dimmed red, no glow/pulse) */
body.q-redesign #buzzing-interface #buzz-btn.buzz-disabled {
  background: radial-gradient(circle at 38% 32%, #5a2630, #371720) !important;
  color: rgba(255,255,255,.5) !important;
  box-shadow: 0 10px 26px rgba(0,0,0,.45), inset 0 -6px 14px rgba(0,0,0,.35) !important;
  cursor: default;
}
/* available — GO! vivid red buzzer, glow rings + pulse */
body.q-redesign #buzzing-interface #buzz-btn.buzz-available {
  background: radial-gradient(circle at 38% 32%, #ff5a72, #c41730) !important;
  color: #fff !important;
  box-shadow: 0 0 0 10px rgba(232,50,74,.18), 0 18px 44px rgba(232,50,74,.5) !important;
  animation: buzzPulseRed 1.2s ease-in-out infinite !important;
}
body.q-redesign #buzzing-interface #buzz-btn.buzz-available:active {
  transform: scale(.95);
  box-shadow: 0 0 0 6px rgba(232,50,74,.22), 0 8px 22px rgba(232,50,74,.5) !important;
  animation: none !important;
}
/* sending — tapped, awaiting server */
body.q-redesign #buzzing-interface #buzz-btn.buzz-sending {
  background: radial-gradient(circle at 38% 32%, #c9405a, #8d1326) !important;
  color: #fff !important;
  box-shadow: 0 10px 28px rgba(196,23,48,.5) !important;
  animation: none !important;
}
/* accepted — you buzzed first! (green) */
body.q-redesign #buzzing-interface #buzz-btn.buzz-accepted {
  background: radial-gradient(circle at 38% 32%, #34d399, #12894f) !important;
  color: #fff !important;
  box-shadow: 0 0 0 10px rgba(22,163,106,.18), 0 18px 44px rgba(22,163,106,.5) !important;
}
/* rejected / locked — someone else got it (muted slate) */
body.q-redesign #buzzing-interface #buzz-btn.buzz-rejected,
body.q-redesign #buzzing-interface #buzz-btn.buzz-locked {
  background: radial-gradient(circle at 38% 32%, #33333f, #1d1d28) !important;
  color: #9aa0ad !important;
  box-shadow: 0 8px 20px rgba(0,0,0,.45) !important;
  animation: none !important;
}
@keyframes buzzPulseRed {
  0%, 100% { transform: scale(1);    box-shadow: 0 0 0 10px rgba(232,50,74,.18), 0 18px 44px rgba(232,50,74,.5); }
  50%      { transform: scale(1.04); box-shadow: 0 0 0 16px rgba(232,50,74,.06), 0 22px 54px rgba(232,50,74,.7); }
}

/* ===== AGREE / DISAGREE — big green / red TILES (mockup §4: full tiles, 34px emoji
   + 20px bold label). Covers BOTH the buzz-judging buttons (#agree-btn / #disagree-btn,
   btn-success/btn-danger) and the poll-vote buttons (.agree-disagree-btn). ===== */
body.q-redesign #buzzing-interface #agree-btn,
body.q-redesign #buzzing-interface #disagree-btn,
body.q-redesign #buzzing-interface .agree-disagree-btn {
  min-height: 132px !important;
  border: none !important; border-radius: 16px !important; color: #fff !important;
  display: flex !important; flex-direction: column; align-items: center; justify-content: center;
  box-shadow: 0 5px 0 rgba(0,0,0,.3) !important;
}
body.q-redesign #buzzing-interface #agree-btn,
body.q-redesign #buzzing-interface .btn-success.agree-disagree-btn { background: #16a36a !important; }
body.q-redesign #buzzing-interface #disagree-btn,
body.q-redesign #buzzing-interface .btn-danger.agree-disagree-btn { background: #e8324a !important; }
body.q-redesign #buzzing-interface .agree-disagree-icon { font-size: 34px; line-height: 1; }
body.q-redesign #buzzing-interface .agree-disagree-label {
  font-family: var(--q-display); font-weight: 900; font-size: 20px; letter-spacing: .5px;
}
body.q-redesign #buzzing-interface #agree-btn:active,
body.q-redesign #buzzing-interface #disagree-btn:active,
body.q-redesign #buzzing-interface .agree-disagree-btn:active {
  transform: translateY(2px); box-shadow: 0 3px 0 rgba(0,0,0,.3) !important;
}

/* =====================================================================
   TOP BANNER cleanup — the redesign's Cheese Noir banner is #playerInfoBar
   (cheese-hole gradient, above). The LEGACY blue #playerStatsBar (Bootstrap
   .bg-primary) is a second, un-themed bar that renders right below it and
   clutters the top. The drawer can still be opened from #playerInfoBar, so the
   legacy bar is redundant under the redesign — hide it.
   ===================================================================== */
body.q-redesign #playerStatsBar { display: none !important; }

/* Practice launcher must never sit over a live question (it already z-indexes
   behind the question UI and JS hides it on question/minigame start; this is a
   belt-and-suspenders guard so it can't flash during question-active). */
body.q-redesign.question-active #practiceLauncher { display: none !important; }

/* Rivalry chip (engagement.js) is position:fixed at top:48px/right:8px — directly over the
   question header. The rival / head-to-head readout is between-questions info, so keep it OUT of
   the live question (it still shows in the lobby / scoreboard / reveal). The engagement.js gate
   already keeps it off entirely when Rivalry mode is disabled; this only handles the on case. */
body.q-redesign.question-active #engagementRivalry { display: none !important; }

/* =====================================================================
   GOING WIDE button → Cheese Noir gold. The base .go-wide-button is a teal
   gradient (#17a2b8) that clashes with the dark/gold theme; re-skin it to the
   gold "submit" gradient with a dark penalty chip so it reads on-brand.
   (Covers the new-UI #go-wide-btn-new and the legacy #go-wide-btn.)
   ===================================================================== */
body.q-redesign .go-wide-button,
body.q-redesign #go-wide-btn-new,
body.q-redesign #go-wide-btn {
  background: linear-gradient(135deg, #f7bb24, #e29800) !important;
  color: #1a1206 !important;
  border: none !important;
  box-shadow: 0 6px 16px rgba(242,169,0,.35) !important;
}
body.q-redesign .go-wide-penalty,
body.q-redesign #go-wide-btn .badge {
  background: #1a1206 !important; color: var(--q-gold) !important;
}

/* =====================================================================
   JOIN FLOW — frosted "Cheese Noir" reskin of the live #joinForm (PIN /
   team / avatar picker / buzzer / Join button) so the onboarding matches
   the mockup's dark glass cards over the cheese-art background. Scoped to
   #joinForm; the form keeps all its IDs + the avatar-picker markup intact.
   ===================================================================== */
body.q-redesign #joinForm {
  background: rgba(12,10,22,.66);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  border: 1px solid rgba(245,197,66,.16);
  border-radius: 18px;
  box-shadow: 0 14px 34px rgba(0,0,0,.5);
  padding: 20px 18px;
  max-width: 460px; margin-left: auto; margin-right: auto;
}
/* gold brand line above the heading (mockup "🧀 100 CHEESE TRIVIA") */
body.q-redesign #joinForm::before {
  content: "🧀 100 CHEESE TRIVIA";
  display: block; text-align: center;
  font-family: var(--q-display); font-weight: 900;
  font-size: 12px; letter-spacing: .6px; color: var(--q-gold);
  margin-bottom: 6px;
}
body.q-redesign #joinForm h3 {
  font-family: var(--q-display); font-weight: 900; color: var(--q-ink);
  text-align: center; letter-spacing: .5px; margin-bottom: 16px;
}
body.q-redesign #joinForm .form-label {
  color: var(--q-gold); font-weight: 800; letter-spacing: .8px;
  font-size: 11px; text-transform: uppercase;
}
/* NB: theme.css sets `.player-root .form-control{background:var(--surface-light)!important}`
   — so the join inputs need !important to land the dark frosted look. */
body.q-redesign #joinForm .form-control,
body.q-redesign #joinForm .form-select {
  background: rgba(255,255,255,.06) !important; color: var(--q-ink) !important;
  border: 1.5px solid rgba(255,255,255,.13) !important; border-radius: 12px !important;
  padding: 12px 14px; font-weight: 700;
}
body.q-redesign #joinForm .form-control::placeholder { color: rgba(255,255,255,.42); }
body.q-redesign #joinForm .form-control:focus,
body.q-redesign #joinForm .form-select:focus {
  border-color: var(--q-gold) !important; background: rgba(255,255,255,.09) !important;
  color: var(--q-ink) !important; box-shadow: 0 0 0 3px rgba(242,169,0,.2) !important;
}
/* dropdown options readable when the native popup opens */
body.q-redesign #joinForm .form-select option { background: #15131f; color: #fff; }
/* avatar picker (colours only — don't touch its layout) */
body.q-redesign #joinForm .avatar-picker-selected {
  background: rgba(255,255,255,.06); color: var(--q-ink);
  border: 1.5px solid rgba(255,255,255,.13); border-radius: 12px;
}
body.q-redesign #joinForm .avatar-picker-placeholder { color: rgba(255,255,255,.55); }
body.q-redesign #joinForm .avatar-picker-arrow { color: var(--q-gold); }
body.q-redesign #joinForm .avatar-picker-dropdown {
  background: #15131f; border: 1px solid rgba(245,197,66,.16); border-radius: 12px;
}
/* gold gradient Join button (mockup) */
body.q-redesign #joinForm #btnJoin {
  background: linear-gradient(135deg, #f7bb24, #e29800) !important;
  border: none !important; color: #1a1206 !important;
  font-family: var(--q-display); font-weight: 900; letter-spacing: .5px;
  border-radius: 14px !important; height: 52px;
  box-shadow: 0 8px 20px rgba(242,169,0,.32);
}
body.q-redesign #joinForm #btnJoin:active { transform: scale(.98); }
body.q-redesign #joinForm .connection-status { color: #9fe3c0 !important; }
body.q-redesign #joinForm #joinMsg { color: #f0a5a5; }
body.q-redesign #joinForm footer a { color: var(--q-gold); }

/* =====================================================================
   LOBBY WAITING CARD — "You're in! Waiting for the host…" (mockup §5).
   Created + toggled by static/js/player/lobby-card.js, which adds
   body.qr-lobby ONLY in the pure post-join lobby state (no question, no
   buzz, no minigame) and latches it off once the first round starts.
   ===================================================================== */
body.q-redesign #qrWaitingCard { display: none; }
body.q-redesign.qr-lobby #qrWaitingCard {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px; text-align: center; pointer-events: none;
  position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%);
  z-index: 40; width: min(86vw, 360px);
}
body.q-redesign #qrWaitingCard .qrw-cheese { font-size: 52px; line-height: 1; }
body.q-redesign.qr-lobby #qrWaitingCard .qrw-cheese { animation: qrwPulse 2.2s ease-in-out infinite; }
@keyframes qrwPulse { 0%,100% { transform: scale(1); } 50% { transform: scale(1.08); } }
body.q-redesign #qrWaitingCard .qrw-title {
  font-family: var(--q-display); font-weight: 900; font-size: 24px;
  color: var(--q-gold); line-height: 1.05;
}
body.q-redesign #qrWaitingCard .qrw-sub { font-size: 13px; color: #b9b29c; }
body.q-redesign #qrWaitingCard .qrw-namecard {
  margin-top: 6px; background: rgba(0,0,0,.5);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  border-radius: 14px; padding: 14px 22px;
  border: 1px solid rgba(245,197,66,.16); box-shadow: 0 8px 24px rgba(0,0,0,.4);
}
body.q-redesign #qrWaitingCard .qrw-namelabel {
  font-size: 10px; font-weight: 800; letter-spacing: 1px; color: #c9b87a;
}
body.q-redesign #qrWaitingCard .qrw-name {
  font-family: var(--q-display); font-weight: 900; font-size: 22px; color: #fff; margin-top: 2px;
}

/* =====================================================================
   ROUND 4 — gap-audit fixes (multi-agent audit 2026-06-22). Each block closes
   an un-themed / off-brand state the audit confirmed under body.q-redesign.
   All additive + scoped; the classic (flag-off) look is untouched. Most use
   !important to beat an injected light base or an inline color the theme
   otherwise can't reach.
   ===================================================================== */

/* Numeric keypad SUBMITTED state (base forces light grey #e0e0e0 !important). */
body.q-redesign .numeric-container .numeric-keypad.submitted .numeric-key {
  background: #23232f !important; color: #6f6f80 !important; border-color: transparent !important; opacity: .6;
}
body.q-redesign .numeric-container .numeric-keypad.submitted .numeric-key.submit {
  background: var(--tile-d) !important; color: #fff !important; opacity: 1;
}
body.q-redesign .numeric-container .numeric-display.submitted {
  background: #1c2a1f !important; border-color: #4caf50 !important; color: #eafff0 !important;
}
/* exact_text/numeric Submit button (spelling keyboard's submit sits directly under
   .numeric-container, outside .numeric-keypad, so it fell back to base green). */
body.q-redesign .numeric-container .numeric-key.submit {
  background: var(--tile-d) !important; color: #fff !important; border: none !important;
}

/* Going-Wide SECOND (locked) tile — base paints off-brand teal !important → gold-ring dark. */
body.q-redesign .answer-tiles-container .answer-tile.going-wide-second {
  background: #1b1206 !important; border: 2px solid var(--q-gold) !important; color: #fff !important;
  box-shadow: inset 0 0 0 2px var(--q-gold), 0 6px 18px rgba(0,0,0,.5) !important;
}

/* Armed ('.sel') drag/match/image tiles — injected light #e0f2fe is suppressed by the dark
   !important base, so the selection cue vanished; restore a gold-ring armed look. */
body.q-redesign .qtui-wrap .dd-item.sel,
body.q-redesign .qtui-wrap .match-item.sel {
  border-color: var(--q-gold) !important; background: #2a2418 !important; color: #fff !important;
  box-shadow: 0 0 0 2px var(--q-gold) inset, 0 0 10px rgba(242,169,0,.35) !important;
}
body.q-redesign .qtui-wrap .imgc-tile.sel {
  border-color: var(--q-gold) !important; box-shadow: 0 0 0 3px var(--q-gold) !important;
}
/* qtui SUBMITTED / disabled states (fill_blank/image_tiles/matching/drag_drop). */
body.q-redesign .qtui-wrap .qtui-submit:disabled { opacity: .55; }
body.q-redesign .qtui-wrap .fb-input:disabled {
  background: #15151d !important; color: #8a8a9a !important; -webkit-text-fill-color: #8a8a9a; opacity: 1;
}

/* Ordering pick-order badge — base is Bootstrap blue → gold. */
body.q-redesign .answer-tiles-container .ordering-tile .order-indicator {
  background: var(--q-gold) !important; color: #1a1206 !important;
  box-shadow: 0 2px 8px rgba(0,0,0,.5), inset 0 0 0 2px rgba(255,255,255,.85) !important;
}

/* Numeric Going-Wide ±1 panel (#numericGoingWide) — inline #666/#999/#17a2b8 text is dark on
   dark; !important beats inline. Gold heading + light body. */
body.q-redesign #numericGoingWide .going-wide-instruction,
body.q-redesign #numericGoingWide .going-wide-instruction * { color: rgba(255,255,255,.82) !important; }
body.q-redesign #numericGoingWide .going-wide-instruction > div:first-child { color: var(--q-gold) !important; }
body.q-redesign #numericGoingWide .going-wide-center {
  background: var(--q-card) !important; border-color: var(--q-gold) !important; color: #fff !important;
}

/* Question-text popup — inner card is an inline 'background:white' div (no .modal-content), so the
   old theme rule missed it; theme the whole card + heading/footer. */
body.q-redesign #questionTextPopup > div { background: #16161f !important; box-shadow: 0 10px 40px rgba(0,0,0,.6) !important; }
body.q-redesign #questionTextPopup, body.q-redesign #questionTextPopup * { color: var(--q-ink) !important; }
body.q-redesign #questionTextPopupText { background: #101018 !important; color: var(--q-ink) !important; }

/* Legacy #player-answer feedback box (.alert) — num_closest/cascade distance feedback. */
body.q-redesign #player-answer .alert {
  background: #1b1b26 !important; color: var(--q-ink) !important; border-color: #2a2a38 !important;
}

/* Pinpoint hint text — lift the muted grey on the dark sheet. */
body.q-redesign .pinpoint-hint { color: #b9b9c7 !important; }

/* Scoreboard drawer muted helper text (Leaderboard / Waiting / No scores) + connection pill. */
body.q-redesign .scoreboard-drawer .text-muted,
body.q-redesign #scoreboardContent .text-muted { color: #8a8a9a !important; }
body.q-redesign .scoreboard-drawer .scoreboard-session-info span[style*="border-radius"] {
  background: #2a2a38 !important; color: #f5c542 !important; border: 1px solid #3a3a48 !important;
}

/* Mode indicator badge — GW was Bootstrap teal → gold (matches the go-wide button). */
body.q-redesign .mode-icon-small.mode-icon-gw {
  background: linear-gradient(135deg, #f7bb24, #e29800) !important; color: #1a1206 !important;
}

/* Sound toggle button — sound-toggle.js sets the bg inline (#28a745 on / #6c757d off); beat it via
   !important and key the on-state off aria-pressed so it's on-brand. */
body.q-redesign #playerSoundToggleBtn {
  background: #23232f !important; color: var(--q-ink) !important; box-shadow: inset 0 0 0 1px #3a3a48;
}
body.q-redesign #playerSoundToggleBtn[aria-pressed="true"] { background: var(--tile-d) !important; }

/* Buzz/poll progress-bar fill — bg-info teal default → gold; keep warning/danger urgency. */
body.q-redesign #buzzing-interface .progress-bar,
body.q-redesign #buzzing-interface .progress-bar.bg-info { background: var(--q-gold) !important; }
body.q-redesign #buzzing-interface .progress-bar.bg-warning { background: #f59e0b !important; }
body.q-redesign #buzzing-interface .progress-bar.bg-danger { background: #e0413f !important; }

/* Avatar picker dropdown tiles + labels — base light-grey tiles cluster inside the dark dropdown;
   selected name was dark-on-dark. */
body.q-redesign #joinForm .avatar-picker-item { background: rgba(255,255,255,.05) !important; border-color: transparent !important; }
body.q-redesign #joinForm .avatar-picker-item:hover { background: rgba(255,255,255,.10) !important; border-color: rgba(245,197,66,.4) !important; }
body.q-redesign #joinForm .avatar-picker-item.selected { background: rgba(242,169,0,.18) !important; border-color: var(--q-gold) !important; }
body.q-redesign #joinForm .avatar-picker-item.no-avatar { background: rgba(255,255,255,.05) !important; }
body.q-redesign #joinForm .avatar-item-name,
body.q-redesign #joinForm .avatar-picker-name { color: var(--q-ink) !important; }
body.q-redesign #joinForm .avatar-placeholder-icon { background: rgba(255,255,255,.10) !important; color: var(--q-gold) !important; }

/* Toast notifications (.trivia-notification) — inline light pastel boxes → one dark skin. */
body.q-redesign .trivia-notification {
  background: #1a1410 !important; color: #f5e9c8 !important;
  border: 1px solid rgba(212,175,55,.4) !important; box-shadow: 0 4px 14px rgba(0,0,0,.5) !important;
}

/* Host event-media popup — inline purple gradient → Cheese Noir. */
body.q-redesign #eventMediaPopup {
  background: linear-gradient(135deg, #1a1206, #3a2a08) !important;
  color: #fff !important; border: 2px solid var(--q-gold) !important;
}

/* Engagement urgency is now applied to the VISIBLE #qTimerRing (timer.js re-targets it; the
   legacy badge it used to animate is display:none). The ring already pulses on its own near
   time-up, so we DON'T re-add a competing scale-pulse for the ≤5s '.eng-timer-pulse' state —
   we add a distinct FINAL-SECOND shake (≤1s '.eng-timer-shake') the ring doesn't otherwise do.
   The keyframe is uniquely named so it can never collide with engagement.js's own engTimer*
   definitions (which aren't even injected on the player). */
body.q-redesign #qTimerRing.eng-timer-shake { animation: qrRingShake .18s linear infinite !important; }
@keyframes qrRingShake { 0%,100% { transform: translateX(0); } 30% { transform: translateX(-3px); } 70% { transform: translateX(3px); } }
