:root {
  /* Dark theme (default) */
  --bg: #0b0d12;
  --bg-2: #05070a;
  --panel: #171c25;
  --panel-2: #1f2530;
  --panel-3: #262d3a;
  --border: #2c3341;
  --border-soft: #232936;
  --text: #eef1f6;
  --text-dim: #8b93a1;
  --accent: #4f7cff;
  --accent-2: #7c5cff;
  --green: #22c55e;
  --blue: #4f7cff;
  --red: #ef4444;
  --amber: #eab308;
  --gold: #d9a840;
  --mafia: #8a2332;
  --mafia-rgb: 138, 35, 50;
  --shadow: rgba(0,0,0,.55);
  --shadow-soft: rgba(0,0,0,.3);
  --radius-lg: 18px;
  --radius-md: 14px;
  --radius-sm: 10px;
  --font-display: 'Manrope', -apple-system, BlinkMacSystemFont, sans-serif;
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  /* Both set from JS (see updateSafeArea in app.js) while the Mini App is in fullscreen:
       --safe-top   the device notch / status bar height (safeAreaInset.top)
       --pill-band  the height of Telegram's own floating Back/menu pill row, which it
                    draws directly below the notch (contentSafeAreaInset.top)
     The pills own the strip from --safe-top to --safe-top + --pill-band. Both stay 0
     outside fullscreen, where Telegram draws no pills over the page at all. */
  --safe-top: 0px;
  --pill-band: 0px;
  /* Horizontal insets (safeAreaInset.left/right) — a notch in landscape, a curved
     display edge, or Telegram's own floating controls. Set from JS alongside the
     others; 0 outside fullscreen. --gutter is the minimum breathing room the layout
     keeps at the screen edges regardless, so nothing ever sits flush against it. */
  --safe-left: 0px;
  --safe-right: 0px;
  --gutter: 6px;
  /* Telegram's bottom inset (Android gesture/nav bar). `env(safe-area-inset-bottom)` is
     0 inside its WebView even when the system bar overlaps the page, so anything docked
     to the bottom must use --gap-bottom below, never env() alone. */
  --safe-bottom: 0px;
  /* Whichever of the two is actually correct on this device. */
  --gap-bottom: max(env(safe-area-inset-bottom, 0px), var(--safe-bottom));
}

:root[data-theme="light"] {
  --bg: #eef0f4;
  --bg-2: #dde1e8;
  --panel: #ffffff;
  --panel-2: #f3f5f8;
  --panel-3: #e9ecf1;
  --border: #dde1e8;
  --border-soft: #e6e9ef;
  --text: #14171f;
  --text-dim: #6b7280;
  --accent: #3860ec;
  --accent-2: #7c5cff;
  --green: #16a34a;
  --blue: #3860ec;
  --red: #dc2626;
  --amber: #b45309;
  --gold: #a3781f;
  --mafia: #b91c1c;
  --mafia-rgb: 185, 28, 28;
  --shadow: rgba(20,24,32,.16);
  --shadow-soft: rgba(20,24,32,.08);
}

/* touch-action: manipulation removes the ~300ms tap delay AND stops a double-tap from
   being interpreted as "zoom" on iOS/Android in-app browsers — the viewport's
   maximum-scale/user-scalable alone isn't reliably honored by Telegram's WebView. */
html, body { touch-action: manipulation; }
* { box-sizing: border-box; }
body {
  margin: 0;
  background: var(--bg-2);
  color: var(--text);
  display: flex;
  flex-direction: column;
  align-items: center;
  min-height: 100vh;
  padding: 16px;
  -webkit-font-smoothing: antialiased;
}
:root[data-theme="light"] body { background: var(--bg-2); }

.icon { width: 1em; height: 1em; display: inline-block; vertical-align: -0.15em; flex-shrink: 0; }
.icon-sm { width: 14px; height: 14px; }
.icon-md { width: 18px; height: 18px; }
.icon-lg { width: 26px; height: 26px; }
.icon-xl { width: 34px; height: 34px; }

.proto-nav {
  width: 100%;
  max-width: 900px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 10px 14px;
  margin-bottom: 16px;
  font-size: 13px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 10px;
  align-items: center;
}
.proto-nav__label { color: var(--text-dim); margin-right: 4px; }
.proto-nav__link {
  color: var(--text-dim);
  text-decoration: none;
  padding: 4px 8px;
  border-radius: 6px;
  border: 1px solid transparent;
}
.proto-nav__link:hover { color: var(--text); border-color: var(--border); }
.proto-nav__link.is-active { color: var(--text); background: var(--panel-2); border-color: var(--accent); }

/* #popupLayer sits as a sibling of .phone-frame (see index.php) so timed popups
   (role reveal, elimination notice) survive setFrame()'s innerHTML wipe on the next
   poll re-render — it overlays the exact same box since #app is position:relative
   and this is inset:0 within it. */
/* z-index 80 keeps popups above the chat FAB (60) and the composer overlay (70). At 40
   the pencil button floated on top of the dimmed role-reveal card, and an open composer
   could cover the elimination popup's dismiss button. */
#popupLayer { position: absolute; inset: 0; pointer-events: none; z-index: 80; }
.popup-overlay {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  padding: 24px;
  /* Start below Telegram's own Back / ⌄ / ⋯ pills. A tall card (a Pro player's profile
     with the full stats breakdown) was centred in the whole screen and its top — photo,
     name — sat behind those pills. */
  padding-top: calc(var(--safe-top) + var(--pill-band) + 16px);
  padding-bottom: calc(var(--safe-bottom, 0px) + 24px);
  background: rgba(0,0,0,.72); backdrop-filter: blur(3px);
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .25s ease, visibility 0s linear .25s;
}
.popup-overlay.is-open { opacity: 1; visibility: visible; pointer-events: auto; transition: opacity .25s ease; }
.popup-card {
  background: linear-gradient(180deg, var(--panel-2), var(--panel));
  border: 1px solid var(--border-soft);
  border-radius: 20px;
  padding: 30px 26px;
  text-align: center;
  max-width: 100%;
  box-shadow: 0 24px 60px var(--shadow);
  transform: scale(.9);
  transition: transform .25s cubic-bezier(.32,.72,0,1);
}
.popup-overlay.is-open .popup-card { transform: scale(1); }
/* Never taller than the space left under the pills: the card's own scroll area
   (.profile-scroll) shrinks instead of the card running off the screen. */
.popup-card { max-height: 100%; }
.popup-card.profile-card { display: flex; flex-direction: column; }
.popup-card.profile-card .profile-scroll { flex: 1 1 auto; min-height: 0; }
.popup-card .popup-icon { width: 52px; height: 52px; margin: 0 auto 14px; color: var(--accent); }
.popup-card.is-mafia .popup-icon { color: var(--mafia); }
.popup-card .popup-kicker { font-size: 12px; text-transform: uppercase; letter-spacing: .08em; color: var(--text-dim); font-weight: 700; }
.popup-card .popup-role { font-family: var(--font-display); font-size: 26px; font-weight: 800; margin: 4px 0 10px; }
.popup-card.is-mafia .popup-role { color: var(--mafia); }
.popup-card p { margin: 0; color: var(--text-dim); font-size: 13px; line-height: 1.4; }
.popup-card .btn { margin-top: 16px; }

.phone-frame {
  position: relative;
  width: 390px;
  max-width: 100%;
  background:
    radial-gradient(1200px 300px at 50% -80px, rgba(79,124,255,.10), transparent 60%),
    var(--bg);
  border: 1px solid var(--border);
  border-radius: 24px;
  overflow: hidden;
  min-height: 680px;
  /* Every screen's content is inset by this, so nothing — the logo lockup, the header
     buttons, the chat FAB — can end up underneath Telegram's floating controls or on a
     curved display edge. Applied once here rather than in each component's own padding,
     which is why the per-screen paddings below are unchanged. */
  padding-left: calc(var(--safe-left) + var(--gutter));
  padding-right: calc(var(--safe-right) + var(--gutter));
  display: flex;
  flex-direction: column;
  box-shadow: 0 24px 70px var(--shadow), inset 0 1px 0 rgba(255,255,255,.03);
}

.topbar {
  /* Windowed / no-pill case: ordinary padding, offset by the notch if there is one. */
  padding: calc(var(--safe-top) + 16px) 16px 12px;
  text-align: center;
  border-bottom: 1px solid var(--border-soft);
  position: relative;
  background: linear-gradient(180deg, rgba(79,124,255,.06), transparent);
}

/* Fullscreen with Telegram's pill row present (see updateSafeArea in app.js).
   The header starts exactly at the top of the pill band rather than below it, and the
   title is centered INSIDE that band — so the title shares a line with Telegram's Back
   and menu pills on every device, however tall its notch or pill row happens to be,
   instead of leaving an empty strip beside them. */
:root.has-pill-band .topbar {
  padding-top: var(--safe-top);
}
:root.has-pill-band .topbar h1 {
  min-height: var(--pill-band);
  display: flex;
  align-items: center;
  justify-content: center;
  /* The pills float in the corners of that same band, so keep the title clear of them.
     Telegram does not report their width; this is sized for the widest case (a labelled
     "Back" pill on the left, chevron + kebab on the right) and the title already
     ellipsizes, so a long room name shortens rather than sliding underneath. */
  padding-left: 96px;
  padding-right: 96px;
  box-sizing: border-box;
}
.topbar::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
  background: linear-gradient(90deg, transparent, var(--accent), var(--accent-2), transparent);
  opacity: .5;
}
.topbar h1 {
  font-family: var(--font-display); font-size: 18px; margin: 0; font-weight: 800;
  letter-spacing: -.01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.topbar .sub { color: var(--text-dim); font-size: 12px; margin-top: 3px; display: flex; align-items: center; justify-content: center; gap: 5px; }

/* A row of controls (back/share/theme buttons) that sits BELOW the title, in normal
   document flow — never pinned to the top corners of the screen, so it can never
   collide with Telegram's own floating Close/menu pills in fullscreen mode. */
.header-actions-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 14px 0; flex-shrink: 0; }
.header-actions-row:empty { display: none; }
.header-actions-row > .spacer { flex: 1; }

.header-back-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: var(--text-dim);
  cursor: pointer;
  padding: 6px 12px 6px 10px;
  font-size: 12.5px;
  font-weight: 700;
}
.header-back-btn:active { transform: scale(.96); }
.header-back-btn.danger { color: #ffb4bb; border-color: rgba(239,68,68,.4); background: rgba(239,68,68,.12); }

.header-share-btn {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
}
.header-share-btn:active { transform: scale(.92); }

/* The create-room sheet stacks .profile-field blocks directly inside
   .modal-sheet__body, which has no row gap of its own (.profile-form's 12px gap is what
   spaces these out on the profile screen, and this sheet is not that form). So the name
   input sat flush against this toggle. Spacing it here rather than on .profile-field
   keeps the profile screen — where the gap already comes from the flex parent — unchanged. */
.visibility-toggle { display: flex; gap: 8px; margin-top: 12px; }
.visibility-opt {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 10px 8px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: var(--text-dim);
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
}
.visibility-opt.is-active { background: linear-gradient(180deg, var(--accent), color-mix(in srgb, var(--accent) 80%, black)); border-color: transparent; color: #fff; }
.visibility-hint { margin: 8px 2px 0; font-size: 12px; color: var(--text-dim); line-height: 1.4; }

.stepper { display: flex; align-items: center; justify-content: space-between; background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 6px; }
.stepper__btn {
  width: 36px; height: 36px; border-radius: var(--radius-sm); border: none; background: var(--panel-3); color: var(--text);
  font-size: 18px; font-weight: 800; display: flex; align-items: center; justify-content: center; cursor: pointer;
}
.stepper__btn:active { transform: scale(.92); }
.stepper__btn:disabled { opacity: .35; cursor: default; transform: none; }
.stepper__value { font-family: var(--font-display); font-size: 16px; font-weight: 800; }

/* Slider + its live readout (create-room discussion length). The readout is a fixed
   width so the track does not jump sideways as "2 daqiqa" becomes "2.5 daqiqa". */
.range-row { display: flex; align-items: center; gap: 12px; }
.range-value {
  font-family: var(--font-display); font-size: 14px; font-weight: 800;
  min-width: 74px; text-align: right; font-variant-numeric: tabular-nums;
}
.range {
  -webkit-appearance: none; appearance: none;
  flex: 1; height: 4px; border-radius: 999px; background: var(--panel-3);
  outline: none; margin: 0;
}
/* The thumb needs its own rule per engine — a combined selector is dropped whole by
   both of them. 22px keeps it inside Telegram's touch target on a phone. */
.range::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 22px; height: 22px; border-radius: 50%; cursor: pointer;
  background: var(--accent); border: 2px solid var(--panel);
  box-shadow: 0 2px 8px -2px var(--shadow);
}
.range::-moz-range-thumb {
  width: 22px; height: 22px; border-radius: 50%; cursor: pointer; border: 2px solid var(--panel);
  background: var(--accent); box-shadow: 0 2px 8px -2px var(--shadow);
}
.range:active::-webkit-slider-thumb { transform: scale(1.1); }

/* Round icon-only button for the header row — the labelled "Chiqish" pill ate most of
   the row's width, leaving nowhere to put the pregame note. */
.header-icon-btn {
  width: 32px; height: 32px; flex-shrink: 0;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: var(--text-dim);
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
  padding: 0;
}
.header-icon-btn:active { transform: scale(.92); }
.header-icon-btn.danger { color: #ffb4bb; border-color: rgba(239,68,68,.4); background: rgba(239,68,68,.14); }

.pregame-banner {
  margin: 10px 14px 0; padding: 12px 14px; border-radius: var(--radius-md);
  background: linear-gradient(180deg, rgba(79,124,255,.14), rgba(79,124,255,.04));
  border: 1px solid rgba(79,124,255,.3); font-size: 12.5px; color: var(--text); display: flex; gap: 10px; align-items: center;
}
.pregame-banner .pregame-timer { font-family: var(--font-display); font-weight: 800; font-size: 14px; font-variant-numeric: tabular-nums; flex-shrink: 0; }
.pregame-banner.is-ready { background: linear-gradient(180deg, rgba(234,179,8,.16), rgba(234,179,8,.04)); border-color: rgba(234,179,8,.4); }
/* Same banner, shrunk to sit inline in .header-actions-row beside the exit button. It is
   the flexible element in that row, so a long note ellipsizes rather than pushing the
   share button off the edge. */
.pregame-banner.is-inline {
  margin: 0; padding: 6px 10px; border-radius: 999px;
  font-size: 11.5px; gap: 6px; min-width: 0; flex: 1;
}
.pregame-banner.is-inline > div { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pregame-banner.is-inline .icon { flex-shrink: 0; }
.pregame-banner.is-inline .pregame-timer { font-size: 12.5px; }

.theme-toggle {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--panel-2);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-dim);
  cursor: pointer;
  padding: 0;
}
.theme-toggle:active { transform: scale(.94); }
.theme-toggle .icon-moon { display: none; }
:root[data-theme="light"] .theme-toggle .icon-sun { display: none; }
:root[data-theme="light"] .theme-toggle .icon-moon { display: inline-block; }

.timer {
  /* In the normal flow, centred UNDER the title. It was absolutely centred (covering the
     title), then pinned right — but in fullscreen Telegram floats its own Close/menu
     pills over the top-right corner, which would sit straight on top of it. Below the
     title is the only place that collides with neither. */
  margin: 6px auto 0;
  width: max-content;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: 15px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 5px 13px;
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--text);
  box-shadow: 0 6px 16px -12px var(--shadow);
}
.timer .icon { color: var(--text-dim); }
/* Inline variant: the SAME pill, moved up onto the title's line — "1-kun [02:35]" —
   instead of sitting on a row of its own. That is ~27px of header back on every in-game
   screen, which is 27px more chat. Everything that makes it a pill (background, border,
   radius, shadow, the clock glyph, is-danger going solid red) comes from .timer above
   and is deliberately NOT overridden here; only the box is re-laid-out. It keeps the
   .timer class because updateLiveBits() finds the element by it.

   Sized down from 15px: in fullscreen the pill band leaves the title roughly 152px, and
   at the full size the pill pushed two-digit days past that and ellipsized. */
.topbar h1 .timer--inline {
  display: inline-flex;
  vertical-align: middle;
  position: relative; top: -1px;   /* optical centring against the heavier title text */
  margin: 0 0 0 7px;
  width: auto;
  font-size: 12.5px;
  padding: 3px 9px;
  gap: 4px;
}
/* The glyph is 14px in the stacked pill; at this size it is the difference between
   "Oxirgi so'z" fitting in fullscreen and being ellipsized. */
.topbar h1 .timer--inline .icon { width: 12px; height: 12px; }
/* Fullscreen only: Telegram's pill band reserves 96px on each side of the title, leaving
   roughly 152px for title + pill, and the clock glyph is 16px of that. The pill reads as
   a timer without it (it is the only number in the header), and dropping it is what keeps
   the longest titles — "Tanishuv", "Oxirgi so'z" — from ellipsizing. Windowed mode has
   the room, so it keeps the glyph. */
:root.has-pill-band .topbar h1 .timer--inline .icon { display: none; }
:root.has-pill-band .topbar h1 .timer--inline { padding: 3px 8px; }

@keyframes blink { 0%,100% { opacity: 1; } 50% { opacity: .6; } }

.btn-row { display: flex; gap: 10px; padding: 12px 16px; }
/* An auto-start lobby renders no start button, but the empty row still cost 24px of
   padding — which is the dead gap that appeared between the player grid and the chat. */
.btn-row:empty { display: none; }
.btn {
  flex: 1;
  text-align: center;
  padding: 11px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: var(--text);
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  transition: transform .08s ease;
}
.btn:active { transform: scale(.97); }
.btn.primary { background: linear-gradient(180deg, var(--accent), color-mix(in srgb, var(--accent) 80%, black)); border-color: transparent; color: #fff; box-shadow: 0 6px 16px -4px rgba(79,124,255,.55); }
.btn.success { background: linear-gradient(180deg, var(--green), color-mix(in srgb, var(--green) 78%, black)); border-color: transparent; color: #06210f; box-shadow: 0 6px 16px -4px rgba(34,197,94,.4); }
.btn.danger { background: linear-gradient(180deg, var(--red), color-mix(in srgb, var(--red) 78%, black)); border-color: transparent; color: #fff; box-shadow: 0 6px 16px -4px rgba(239,68,68,.4); }
.btn.ghost { background: transparent; box-shadow: none; }
.btn.block { width: 100%; }
.btn.icon-btn { flex: 0 0 44px; padding: 10px; }
.btn.btn-compact { flex: 0 0 auto; padding: 10px 16px; }
.btn:disabled, .btn.disabled { opacity: .4; cursor: default; transform: none !important; box-shadow: none; }

.btn-row--split { justify-content: space-between; }
.btn-group { display: flex; gap: 8px; }

.quickjoin {
  margin: 4px 16px 12px;
  padding: 13px;
  border-radius: var(--radius-md);
  text-align: center;
  font-weight: 800;
  font-family: var(--font-display);
  letter-spacing: -.01em;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  border: none;
  color: #fff;
  text-decoration: none;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  box-shadow: 0 10px 24px -8px rgba(124,92,255,.55);
}
.quickjoin:active { transform: scale(.98); }

.section-title { padding: 14px 14px 6px; font-size: 12.5px; color: var(--text-dim); font-weight: 800; text-transform: uppercase; letter-spacing: .06em; display: flex; align-items: center; gap: 6px; }

.card {
  margin: 6px 14px;
  background: linear-gradient(180deg, var(--panel-2), var(--panel));
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
  box-shadow: 0 1px 0 rgba(255,255,255,.02) inset, 0 10px 24px -14px var(--shadow);
  padding: 12px;
}

.room-list { flex: 1; min-height: 0; padding: 4px 12px 16px; display: flex; flex-direction: column; gap: 9px; overflow-y: auto; }
/* Generic scrollable body for screens that are just a long stack of content with no
   pinned header of their own (summary, replay, profile, room preview) — without this,
   .phone-frame's overflow:hidden simply clipped anything taller than the screen, which
   is why the "back to menu" button on the summary screen was unreachable. Same flex
   trick as .chat/.room-list: this is the one flex:1 child that grows/shrinks to fill
   whatever's left below the topbar, and scrolls internally instead of the whole frame. */
.scroll-page { flex: 1; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.room-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: linear-gradient(180deg, var(--panel-2), var(--panel));
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm);
  padding: 12px 13px;
  font-size: 13px;
  text-decoration: none;
  color: inherit;
  gap: 8px;
  box-shadow: 0 6px 16px -12px var(--shadow);
}
.room-row:active { transform: scale(.98); }
.room-row .name { font-weight: 800; font-family: var(--font-display); }
.room-row .meta { color: var(--text-dim); flex: 1; }
.room-row .count { font-weight: 700; color: var(--green); font-variant-numeric: tabular-nums; }
.room-row .icon { color: var(--text-dim); }

/* The lobby's player grid + start button never scroll — they stay fixed at the top,
   and only the chat below scrolls in its own box (phone-frame clips overflow, .chat
   is the sole flex:1 child that grows/shrinks to fill whatever's left). lobby-top's
   ::after is a soft fade overlapping the seam so messages read as sliding away
   underneath the grid rather than just stopping abruptly. */
.lobby-top { position: relative; z-index: 2; flex-shrink: 0; }
.lobby-top::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -13px; height: 13px;
  /* matches .phone-frame's own background so the fade actually blends in */
  background: linear-gradient(180deg, var(--bg), transparent);
  pointer-events: none;
}

.chat {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  /* A bottom margin is what makes the card visibly END — with `margin-bottom: 0` its
     rounded bottom corners sat exactly on the frame edge (and under Android's gesture
     bar), so the block read as running off the screen. --gap-bottom keeps it clear of
     the system bar as well. */
  /* 4px + the frame's own 6px gutter = 10px from the screen edge. The chat is the widest
     thing on these screens and every pixel of it is content. */
  margin: 6px 4px calc(10px + var(--gap-bottom));
  background: var(--panel);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
  overflow: hidden;
}
/* 8px, not 14: with the card's own padding on top of it the first avatar sat 34px from
   the screen edge, which on a phone is a column of wasted space down the side of the one
   thing this screen is for. See .chat / .chat-card below — they give up their horizontal
   padding entirely, so this is the whole inset. */
.chat-messages { flex: 1; overflow-y: auto; padding: 12px 8px; display: flex; flex-direction: column; gap: 10px; }
.msg { display: flex; gap: 8px; align-items: flex-start; }
.msg img { width: 28px; height: 28px; border-radius: 50%; flex-shrink: 0; object-fit: cover; box-shadow: 0 0 0 2px var(--panel-2); }
.msg .bubble { background: var(--panel-2); border-radius: 10px; padding: 6px 10px; font-size: 13.5px; max-width: 78%; overflow-wrap: anywhere; }
.msg .bubble .name { display: block; font-size: 11px; color: var(--accent); font-weight: 700; margin-bottom: 2px; }
.msg.is-mafia .bubble { background: rgba(var(--mafia-rgb), .16); border: 1px solid rgba(var(--mafia-rgb), .4); }
.msg.is-mafia .bubble .name { color: #f3a1ab; }
/* The viewer's own messages: flipped to the right with their avatar on the right too,
   so at a glance it's obvious which bubbles are theirs (same convention as any chat app). */
.msg.is-mine { flex-direction: row-reverse; }
.msg.is-mine .bubble { background: var(--accent); color: #fff; }
.msg.is-mine .bubble .name { display: none; } /* it's you — no need to label it */
.msg.is-mine.is-mafia .bubble { background: var(--mafia); border-color: var(--mafia); }
/* Server-authored announcements (night deaths, vote results, day/night transitions) —
   rendered as a centered pill rather than a chat bubble, so they double as a visible
   "new block starts here" divider between one day's conversation and the next. */
.msg-system {
  align-self: center;
  max-width: 92%;
  text-align: center;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--text-dim);
  background: var(--panel-3);
  border: 1px solid var(--border-soft);
  border-radius: 999px;
  padding: 5px 12px;
  margin: 2px 0;
}
.chat-input-row { display: flex; gap: 8px; padding: 10px 12px; border-top: 1px solid var(--border-soft); background: var(--panel-2); }
.chat-input-row input {
  flex: 1;
  background: var(--panel-3);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 10px 14px;
  color: var(--text);
  font-size: 13.5px;
}
.chat-input-row input::placeholder { color: var(--text-dim); }
.chat-input-row.locked input { opacity: .35; }
.locked-note { text-align: center; font-size: 12px; color: var(--text-dim); padding: 6px 0 0; display: flex; align-items: center; justify-content: center; gap: 6px; }

/* Round pencil FAB + centered composer popup — replaces the old always-visible inline
   chat-input-row. Both live in #chatComposerLayer, OUTSIDE #frame/.phone-frame, so a
   full poll re-render never tears them down mid-type. #app is the positioning parent
   (max-width:480px, centered) so the FAB sits at the phone frame's own corner, not the
   real browser viewport's, on wide screens. */
/* CRITICAL: both elements below set display:flex, and an author `display` rule BEATS
   the browser's built-in `[hidden] { display: none }` — so `el.hidden = true` from JS
   silently did nothing and the FAB + composer showed on every screen, main menu
   included. These two rules are what actually make hiding them work. */
.chat-fab[hidden],
.chat-composer-overlay[hidden] { display: none !important; }
.chat-fab {
  /* Anchored to #app (the centered, max-width:480px column) rather than the raw
     viewport, so on a wide screen the button sits at the phone frame's own corner. */
  position: absolute;
  right: 16px;
  bottom: calc(16px + var(--gap-bottom));
  width: 50px;
  height: 50px;
  border-radius: 50%;
  border: none;
  background: var(--accent);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 6px 18px rgba(0,0,0,.35);
  z-index: 60;
  cursor: pointer;
}
.chat-fab .icon { width: 22px; height: 22px; }
/* Screens with their own bottom action row (the mafia night confirm/cancel pair) lift
   the FAB above it — at 50px square sitting bottom-right it landed exactly on top of the
   44px "Bekor qilish" button and swallowed the tap, so mafia could not cancel a pick. */
#app.has-bottom-actions .chat-fab { bottom: calc(74px + var(--gap-bottom)); }
.chat-composer-overlay {
  position: fixed;
  top: 0; left: 0; right: 0;
  /* Height comes from --app-height (Telegram's viewportHeight / visualViewport), which
     shrinks when the on-screen keyboard opens — so "the bottom" here means the bottom of
     the still-visible area, i.e. directly above the keyboard. */
  /* Capped at 100dvh for the same reason as .phone-frame — a client that over-reports its
     viewport height would dock this input BELOW the keyboard, which is the exact bug this
     bottom-docked overlay exists to prevent. */
  height: min(var(--app-height, 100dvh), 100dvh);
  background: rgba(0,0,0,.35);
  display: flex;
  /* Docked to the BOTTOM, not centred. Centring put the field in the middle of the
     screen while the keyboard pushed everything around it, which is what made typing
     feel like the layout was coming apart. Sitting just above the keyboard is where a
     text field belongs, and the chat stays readable above it. */
  align-items: flex-end;
  justify-content: center;
  padding: 0 10px calc(10px + var(--gap-bottom));
  z-index: 70;
}
.chat-composer-sheet {
  width: 100%;
  max-width: 440px;
  display: flex;
  gap: 8px;
  align-items: center;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 8px;
  box-shadow: 0 10px 30px rgba(0,0,0,.4);
  animation: composer-rise .18s ease-out;
}
@keyframes composer-rise { from { transform: translateY(12px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
.chat-composer-sheet input {
  flex: 1;
  background: var(--panel-3);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 10px 14px;
  color: var(--text);
  font-size: 14px;
}
.chat-composer-sheet input::placeholder { color: var(--text-dim); }

.legend { display: flex; align-items: center; gap: 14px; justify-content: center; font-size: 11.5px; color: var(--text-dim); padding: 0 14px; }
.legend-item { display: flex; align-items: center; gap: 5px; }
.legend-dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; }

.mafia-chat-panel {
  /* flex:1 + min-height:0 makes this fill the frame exactly like the daytime .chat card
     does. It used to be a thin strip pinned above the kill grid, holding one or two
     lines, while two thirds of the screen sat empty — and this panel is where the mafia
     actually decide the game. */
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  margin: 6px 4px 0;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: linear-gradient(180deg, rgba(var(--mafia-rgb),.24), rgba(var(--mafia-rgb),.05));
  border: 1px solid var(--mafia);
  animation: slidein .35s ease-out;
}
@keyframes slidein { from { transform: translateY(-16px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
.mafia-chat-panel .label { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: #f3a1ab; padding: 10px 12px 0; font-weight: 800; display: flex; align-items: center; gap: 6px; }
.mafia-chat-panel .chat-input-row { background: transparent; border-top: 1px solid rgba(var(--mafia-rgb),.35); }

.player-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 9px;
  padding: 8px 10px;
}
/* Rooms can hold up to 16 players — a flat 6-column grid gets uncomfortably wide once
   there are more than ~12, so past that point we switch to 8 columns. Cells use minmax(0,1fr)
   so they're free to shrink below their content's natural size instead of overflowing the
   row, and the avatar inside is sized as a PERCENTAGE of the cell (not a fixed px) via
   aspect-ratio, so it always scales down to fit — that's what actually prevents the crop,
   at 6 columns or 8. */
/* One class per column count, chosen by gridColsClass() in app.js so that 6-8 players
   sit in a single row and 9-16 split into two balanced ones (9 -> 5/4, 13 -> 7/6).
   Cells use minmax(0,1fr) so they can shrink below their content's natural size instead
   of overflowing the row, and the avatar inside is a PERCENTAGE of the cell via
   aspect-ratio rather than a fixed px — that is what prevents the crop at any width. */
.player-grid.cols-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 6px; }
.player-grid.cols-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 5px; }
.player-grid.cols-7 { grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; }
.player-grid.cols-8 { grid-template-columns: repeat(8, minmax(0, 1fr)); gap: 4px; }
/* From 7 columns up the cells are too narrow for the default padding and name size. */
.player-grid.cols-7 .player-cell,
.player-grid.cols-8 .player-cell { padding: 5px 2px; border-width: 1px; }
.player-grid.cols-7 .player-cell .pname,
.player-grid.cols-8 .player-cell .pname { font-size: 8.5px; margin-top: 3px; }

/* The grid inside a card was paying for the inset TWICE — the card's own 12px plus the
   grid's 8px/10px, which put the first cell 23px from the frame. The card is the frame,
   so the grid gives up its padding entirely and the card tightens to 6px. Cards that do
   not hold a grid are untouched, and so are the two NIGHT grids (the kill grid and the
   role-action grid), which sit directly on the page with no card around them. */
.card > .player-grid { padding: 0; }
.card.card--grid { padding: 6px; }
.player-cell {
  background: linear-gradient(180deg, var(--panel-2), var(--panel));
  border: 2px solid var(--border-soft);
  border-radius: var(--radius-sm);
  padding: 8px 3px;
  text-align: center;
  cursor: pointer;
  position: relative;
  box-shadow: 0 6px 14px -10px var(--shadow);
  transition: transform .08s ease;
  /* NOT overflow:hidden — the vote-count badge is deliberately positioned half outside
     the cell's top-right corner (like an app-icon notification badge) and would get
     clipped by it. The avatar can't overflow anyway since it's sized as a % of the cell. */
  min-width: 0;
}
.player-cell:active { transform: scale(.95); }
.player-cell img {
  display: block;
  width: 68%;
  aspect-ratio: 1 / 1;
  margin: 0 auto 4px;
  border-radius: 50%;
  object-fit: cover;
  box-shadow: 0 0 0 2px var(--panel-2);
}
.player-cell .pname {
  font-size: 10.5px; line-height: 1.2; font-weight: 600; margin-top: 1px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block;
}
/* Mafia night-kill grid: blue the instant ANY mafia member has picked a target (visible
   to every mafia member immediately, not just once someone hits Confirm), green only
   once enough of them have converged on the same target — Confirm only unlocks then. */
.player-cell.is-picked, .player-cell.partial-pick { border-color: var(--blue); box-shadow: 0 0 0 2px rgba(79,124,255,.25); }
.player-cell.consensus-pick { border-color: var(--green); box-shadow: 0 0 0 2px rgba(34,197,94,.25); background: rgba(34,197,94,.12); }
/* Partial agreement on a 3+ mafia team: --agree is set inline (agreeing members /
   team size) so the green starts pale with two pickers and deepens with each further
   member who joins in, instead of the all-or-nothing blue->green flip. */
.player-cell.agree-pick {
  border-color: rgba(34,197,94, calc(.30 + .70 * var(--agree, .5)));
  box-shadow: 0 0 0 2px rgba(34,197,94, calc(.10 + .20 * var(--agree, .5)));
  background: rgba(34,197,94, calc(.04 + .10 * var(--agree, .5)));
}
/* How many mafia members are on this face right now — the colour alone can't say
   "2 of 4" on a bigger team. */
.player-cell .pick-count {
  position: absolute; top: 3px; left: 3px; min-width: 15px; height: 15px;
  padding: 0 3px; border-radius: 8px; background: var(--green); color: #fff;
  font-size: 9.5px; font-weight: 800; line-height: 15px; text-align: center;
}
.player-cell.is-dead { opacity: .35; filter: grayscale(1); cursor: default; }
.avatar-heat-wrap { position: relative; display: inline-block; margin-bottom: 4px; }
.avatar-heat-wrap img { display: block; margin-bottom: 0 !important; }
.vote-heat {
  position: absolute; inset: 0; border-radius: 50%; background: var(--red);
  pointer-events: none; mix-blend-mode: normal;
}
.player-cell .vote-count {
  position: absolute; top: -7px; right: -7px; z-index: 3;
  background: var(--red); color: #fff; font-size: 10.5px; font-weight: 800;
  border-radius: 999px; min-width: 18px; height: 18px; display: flex; align-items: center; justify-content: center;
  padding: 0 4px; box-shadow: 0 0 0 2px var(--panel), 0 2px 6px rgba(0,0,0,.4);
  line-height: 1;
}
.player-cell .role-tag {
  display: inline-block; margin-top: 2px; font-size: 9px; padding: 1px 5px; border-radius: 6px; background: var(--panel-3); color: var(--text-dim);
}
.player-cell .role-tag.mafia { background: var(--mafia); color: #fff; }

.confirm-row { display: flex; gap: 10px; padding: 4px 14px 14px; }

.role-card {
  margin: 40px 20px;
  padding: 30px 20px;
  border-radius: var(--radius-lg);
  text-align: center;
  border: 1px solid var(--border);
  background: radial-gradient(circle at 50% 0%, rgba(var(--mafia-rgb),.32), var(--panel) 70%);
  box-shadow: 0 20px 50px -20px var(--shadow);
}
.role-card .icon-xl { color: var(--text-dim); margin-bottom: 6px; }
.role-card .badge { font-size: 12px; color: var(--text-dim); text-transform: uppercase; letter-spacing: .1em; font-weight: 700; }
.role-card .role-name { font-family: var(--font-display); font-size: 27px; font-weight: 800; margin: 10px 0 6px; letter-spacing: -.01em; }
.role-card .role-desc { font-size: 13.5px; color: var(--text-dim); line-height: 1.55; }
.role-card.team-mafia { border-color: var(--mafia); }
.role-card.team-mafia .icon-xl { color: #f3a1ab; }

.action-panel { margin: 6px 14px 14px; padding: 15px; background: linear-gradient(180deg, var(--panel-2), var(--panel)); border-radius: var(--radius-md); border: 1px solid var(--border-soft); box-shadow: 0 10px 24px -16px var(--shadow); }
.action-panel h3 { margin: 0 0 4px; font-size: 14.5px; font-family: var(--font-display); font-weight: 800; display: flex; align-items: center; gap: 7px; }
.action-panel p { margin: 0 0 10px; font-size: 12.5px; color: var(--text-dim); }

.waiting-screen { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 30px; gap: 10px; color: var(--text-dim); }
.waiting-screen .big { font-size: 15px; color: var(--text); font-weight: 700; font-family: var(--font-display); }
.pulse-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--accent); animation: pulse 1.4s infinite; }
@keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(79,124,255,.6);} 70% { box-shadow: 0 0 0 12px rgba(79,124,255,0);} 100% { box-shadow: 0 0 0 0 rgba(79,124,255,0);} }

.death-banner, .disconnect-banner, .info-banner { margin: 12px 14px 0; padding: 11px 12px; border-radius: var(--radius-sm); font-size: 13px; text-align: center; display: flex; align-items: center; justify-content: center; gap: 7px; }

/* The row under the header: the phase's info banner and the sound toggle, side by side.
   The banner keeps its own look and simply gives up the width the button needs. Screens
   with no banner (night, the vote, final words) still render the row — bare — so the
   button never moves between phases, which is what makes it findable. */
.banner-row { display: flex; align-items: center; gap: 8px; margin: 12px 14px 0; }
.banner-row > .info-banner,
.banner-row > .death-banner { margin: 0; flex: 1; min-width: 0; }
.banner-row.is-bare { justify-content: flex-end; }
.sound-toggle {
  flex: none; width: 42px; height: 42px; border-radius: 50%; padding: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--panel-2); border: 1px solid var(--border);
  color: var(--accent); cursor: pointer;
  box-shadow: 0 6px 16px -12px var(--shadow);
  transition: transform .12s ease, color .2s ease, background .2s ease;
}
.sound-toggle .icon { width: 19px; height: 19px; }
/* Muted reads as "switched off" rather than "a different colour": the fill goes too. */
.sound-toggle.is-muted { color: var(--text-dim); background: transparent; }
.sound-toggle:active { transform: scale(.94); }
/* In the lobby the toggle joins the existing header control row, where the other buttons
   are 34px — matching them matters more there than matching the banner's height. */
.header-actions-row .sound-toggle { width: 34px; height: 34px; }
.header-actions-row .sound-toggle .icon { width: 17px; height: 17px; }
.death-banner { background: rgba(239,68,68,.12); border: 1px solid var(--red); }
.info-banner { background: rgba(79,124,255,.12); border: 1px solid var(--blue); color: var(--text-dim); }
.disconnect-banner { background: rgba(234,179,8,.12); border: 1px solid var(--amber); font-size: 12.5px; }
.disconnect-banner .icon { color: var(--amber); }

.tabs { display: flex; gap: 6px; padding: 10px 14px 0; }
.tab { flex: 1; text-align: center; font-size: 12px; font-weight: 600; padding: 9px; border-radius: var(--radius-sm); background: var(--panel); border: 1px solid var(--border-soft); color: var(--text-dim); text-decoration: none; display: flex; align-items: center; justify-content: center; gap: 5px; }
.tab.is-active { color: #fff; border-color: transparent; background: linear-gradient(180deg, var(--accent), color-mix(in srgb, var(--accent) 80%, black)); }

/* Bottom-sheet modal: starts translated fully off-screen + transparent, slides up and
   fades in when .is-open is added. Kept in the DOM at all times (never [hidden]) so the
   transition has something to animate between — toggling display:none can't transition. */
.modal-overlay {
  position: absolute; inset: 0; background: rgba(0,0,0,.6); backdrop-filter: blur(2px);
  display: flex; align-items: flex-end;
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .22s ease, visibility 0s linear .22s;
}
.modal-overlay.is-open { opacity: 1; visibility: visible; pointer-events: auto; transition: opacity .22s ease; }
.modal-sheet {
  width: 100%; background: var(--panel); border-radius: 20px 20px 0 0; padding: 0 16px 18px;
  max-height: 75%; display: flex; flex-direction: column; border-top: 1px solid var(--border);
  box-shadow: 0 -20px 50px var(--shadow);
  transform: translateY(100%);
  transition: transform .28s cubic-bezier(.32,.72,0,1);
}
.modal-overlay.is-open .modal-sheet { transform: translateY(0); }

/* Centered-dialog variant: used for forms (e.g. create-room) so the keyboard opening
   never covers the input — it stays vertically centered above the keyboard instead of
   pinned to the bottom of the screen. Slides in with a scale+fade instead of translateY. */
.modal-overlay.modal-center { align-items: center; padding: 16px; }
.modal-overlay.modal-center .modal-sheet {
  border-radius: 20px; max-height: 80%; border-top: none;
  transform: scale(.92); opacity: 0;
  transition: transform .22s cubic-bezier(.32,.72,0,1), opacity .18s ease;
}
.modal-overlay.modal-center.is-open .modal-sheet { transform: scale(1); opacity: 1; }
.modal-sheet__head {
  position: sticky; top: 0; z-index: 1; background: var(--panel);
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 16px 0 10px; margin-bottom: 4px; border-bottom: 1px solid var(--border-soft);
}
.modal-sheet__head h3 { margin: 0; font-size: 15.5px; font-family: var(--font-display); font-weight: 800; display: flex; align-items: center; gap: 7px; }
.modal-sheet__close {
  flex: 0 0 auto; width: 30px; height: 30px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--border); background: var(--panel-2); color: var(--text-dim); cursor: pointer; padding: 0;
}
.modal-sheet__close:active { transform: scale(.92); }
.modal-sheet__body { overflow-y: auto; padding-top: 12px; }
.vote-line { display: flex; justify-content: space-between; font-size: 13px; padding: 7px 0; border-bottom: 1px solid var(--border-soft); }
.vote-line:last-child { border-bottom: none; }

.info-intro { font-size: 12.5px; color: var(--text-dim); line-height: 1.55; margin: 0 0 14px; }
.info-intro b { color: var(--text); }
.role-info-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; }
.role-info-row {
  display: flex; gap: 10px; align-items: flex-start;
  background: var(--panel-2); border: 1px solid var(--border-soft); border-radius: var(--radius-sm); padding: 11px;
}
.role-info-row .icon { color: var(--text-dim); margin-top: 1px; }
.role-info-row.is-mafia { background: rgba(var(--mafia-rgb), .14); border-color: rgba(var(--mafia-rgb), .4); }
.role-info-row.is-mafia .icon { color: #f3a1ab; }
.role-info-row__name { font-size: 13px; font-weight: 700; margin-bottom: 2px; font-family: var(--font-display); }
.role-info-row__desc { font-size: 12px; color: var(--text-dim); line-height: 1.4; }

.summary-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 9px; padding: 12px 14px; }
.summary-card { background: linear-gradient(180deg, var(--panel-2), var(--panel)); border: 1px solid var(--border-soft); border-radius: var(--radius-sm); padding: 10px 8px; text-align: center; box-shadow: 0 8px 18px -14px var(--shadow); }
.summary-card img { width: 38px; height: 38px; border-radius: 50%; object-fit: cover; box-shadow: 0 0 0 2px var(--panel-2); }
.summary-card .pname { font-size: 10px; margin-top: 5px; font-weight: 600; }
.summary-card .role-tag { display: inline-block; margin-top: 3px; font-size: 9px; padding: 1px 5px; border-radius: 6px; background: var(--panel-3); color: var(--text-dim); }
.summary-card .role-tag.mafia { background: var(--mafia); color: #fff; }
.summary-card.is-dead { opacity: .5; }
/* The debrief screen shows the same reveal grid ABOVE a live chat, so it has to give
   most of the frame back: more per row, smaller cards, and its own scroll box capped at
   a third of the screen so the conversation always stays visible underneath. */
.postgame-roles { flex-shrink: 0; max-height: 33%; overflow-y: auto; }
.postgame-roles .section-title { padding: 8px 14px 2px; }
.summary-grid.is-compact { grid-template-columns: repeat(4, 1fr); gap: 6px; padding: 4px 14px 10px; }
.summary-grid.is-compact .summary-card { padding: 6px 4px; }
.summary-grid.is-compact .summary-card img { width: 28px; height: 28px; }
.summary-grid.is-compact .summary-card .pname { font-size: 9px; margin-top: 3px; }
.summary-grid.is-compact .summary-card .role-tag { font-size: 8px; padding: 1px 4px; }

.winner-banner { margin: 14px; padding: 18px; border-radius: var(--radius-md); text-align: center; font-family: var(--font-display); font-weight: 800; font-size: 17px; letter-spacing: -.01em; background: linear-gradient(135deg, #22c55e, #16a34a); color: #06210f; display: flex; align-items: center; justify-content: center; gap: 9px; box-shadow: 0 16px 34px -14px rgba(34,197,94,.5); }
/* Same banner, half the height — the debrief screen needs the room for the roles strip
   and the chat, and the result is already known by then. */
.winner-banner.is-compact { margin: 8px 14px; padding: 9px 14px; font-size: 14px; box-shadow: none; }
.winner-banner.mafia { background: linear-gradient(135deg, var(--mafia), #ef4444); color: #fff; box-shadow: 0 16px 34px -14px rgba(239,68,68,.5); }

.log-list { padding: 4px 14px 16px; display: flex; flex-direction: column; gap: 6px; overflow-y: auto; }
.log-line { font-size: 12.5px; color: var(--text-dim); padding: 8px 10px; background: var(--panel); border-radius: var(--radius-sm); border: 1px solid var(--border-soft); display: flex; align-items: flex-start; gap: 6px; }
.log-line b { color: var(--text); }
.log-line .tag { font-size: 10px; padding: 2px 7px; border-radius: 6px; background: var(--panel-3); margin-right: 6px; flex-shrink: 0; white-space: nowrap; font-weight: 700; }

.replay-block { margin: 10px 14px 0; border: 1px solid var(--border-soft); border-radius: var(--radius-md); overflow: hidden; box-shadow: 0 10px 24px -18px var(--shadow); }
.replay-block .replay-block__head { font-size: 11.5px; text-transform: uppercase; letter-spacing: .05em; font-weight: 800; padding: 9px 12px; display: flex; align-items: center; gap: 6px; background: var(--panel-2); color: var(--text-dim); }
.replay-block.is-mafia .replay-block__head { background: rgba(var(--mafia-rgb),.18); color: #f3a1ab; }
.replay-block__body { padding: 10px 12px; display: flex; flex-direction: column; gap: 8px; background: var(--panel); }
.replay-block__body .msg .bubble { background: var(--panel-2); }
.replay-block.is-mafia .msg .bubble { background: rgba(var(--mafia-rgb), .14); }
.day-divider { margin: 18px 14px 0; display: flex; align-items: center; gap: 10px; color: var(--gold); font-family: var(--font-display); font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .08em; }
.day-divider::before, .day-divider::after { content: ""; flex: 1; height: 1px; background: linear-gradient(90deg, transparent, var(--border)); }
.day-divider::before { background: linear-gradient(90deg, transparent, var(--border)); }
.day-divider::after { background: linear-gradient(90deg, var(--border), transparent); }

.replay-form { margin: 40px 20px; text-align: center; }
.replay-form .icon-xl { color: var(--text-dim); margin-bottom: 10px; }
.replay-form input { width: 100%; text-align: center; letter-spacing: .12em; font-size: 16px; font-weight: 700; padding: 13px; border-radius: var(--radius-sm); border: 1px solid var(--border); background: var(--panel-2); color: var(--text); margin-bottom: 12px; }

.countdown-big { font-size: 44px; font-weight: 800; text-align: center; margin: 8px 0; font-variant-numeric: tabular-nums; font-family: var(--font-display); }

/* Profile screen */
.profile-hero { display: flex; flex-direction: column; align-items: center; padding: 26px 20px 10px; gap: 10px; }
.profile-avatar-wrap { position: relative; }
.profile-avatar-wrap img { width: 92px; height: 92px; border-radius: 50%; object-fit: cover; box-shadow: 0 0 0 4px var(--panel-2), 0 12px 28px -12px var(--shadow); }
.profile-avatar-edit {
  position: absolute; bottom: -2px; right: -2px; width: 32px; height: 32px; border-radius: 50%;
  background: linear-gradient(180deg, var(--accent), color-mix(in srgb, var(--accent) 80%, black));
  color: #fff; display: flex; align-items: center; justify-content: center; border: 3px solid var(--panel); cursor: pointer;
  z-index: 3;
}
/* A frame spills past the avatar, so the camera button steps out past the frame. */
.profile-avatar-wrap:has(.avf) .profile-avatar-edit { bottom: -16px; right: -16px; }
.profile-form { padding: 6px 16px; display: flex; flex-direction: column; gap: 12px; }
.profile-field label { display: block; font-size: 11.5px; color: var(--text-dim); font-weight: 700; text-transform: uppercase; letter-spacing: .05em; margin-bottom: 6px; }
.profile-field input[type="text"] {
  width: 100%; background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 12px 14px; color: var(--text); font-size: 14px; font-family: var(--font-display); font-weight: 700;
}
.profile-lock-note { margin: 0 16px; padding: 12px; background: rgba(234,179,8,.1); border: 1px solid var(--amber); border-radius: var(--radius-sm); font-size: 12.5px; color: var(--text); display: flex; gap: 8px; align-items: flex-start; }
.profile-lock-note .icon { color: var(--amber); flex-shrink: 0; margin-top: 1px; }

/* Detective's investigation results — the role's entire payoff, previously never
   rendered anywhere because the server kept the results to itself. */
.action-panel.investigations { margin: 10px 14px 0; }
.investigation-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 6px 0; font-size: 13px; border-top: 1px solid var(--border-soft);
}
.investigation-row:first-of-type { border-top: none; }
.investigation-row .dim { color: var(--text-dim); font-size: 11.5px; }
.investigation-row .verdict { font-weight: 800; font-size: 12px; }
.investigation-row .verdict.is-mafia { color: #f3a1ab; }
.investigation-row .verdict.is-clean { color: var(--green); }

/* Confirmation that a night choice is locked in, shown under the mafia kill grid. */
.decision-banner {
  margin: 10px 14px 0;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  background: rgba(34,197,94,.14);
  border: 1px solid rgba(34,197,94,.45);
  color: var(--text);
  font-size: 12.5px;
  display: flex; align-items: center; gap: 8px;
}
.decision-banner .icon { color: var(--green); }

/* The player you personally voted for — orange, so your own choice is unmistakable
   among everyone else's vote counts. */
.player-cell.my-vote { border-color: var(--amber); box-shadow: 0 0 0 2px rgba(234,179,8,.55); }
.player-cell.my-vote .pname { color: var(--amber); font-weight: 800; }
/* Your own face during the vote: visible, but never a target.

   This used to be a "siz" label pinned to the bottom-right corner of the cell, which
   landed straight on top of the player's own name — a name is as wide as the cell, and
   the badge was absolutely positioned over it. The cell now says the same thing with
   colour instead: sunk into the background, dimmed, no ring. It reads as "not one of
   the choices" at a glance and costs no space. */
.player-cell.is-self {
  background: rgba(0, 0, 0, .42);
  border-color: transparent;
  box-shadow: none;
}
.player-cell.is-self img { opacity: .45; }
.player-cell.is-self .pname { color: var(--text-dim); }

/* The detective's night grid, once a verdict is in: the answer goes on the face, not
   only in the list above it. Red for a mafioso, green for anyone who came back clean —
   the same two colours the verdict list uses, so the two panels agree. Kept as a tinted
   background plus a border rather than a solid fill, so the avatar underneath is still
   recognisable and the cell still reads as tappable (a verdict does not stop the
   detective re-checking someone — the Godfather is exactly why they might). */
.player-cell.verdict-mafia {
  background: rgba(220, 38, 38, .22);
  border-color: rgba(243, 161, 171, .55);
}
.player-cell.verdict-clean {
  background: rgba(34, 197, 94, .18);
  border-color: rgba(34, 197, 94, .5);
}
.player-cell.verdict-mafia .pname { color: #f3a1ab; }
.player-cell.verdict-clean .pname { color: var(--green); }

/* Post-game debrief banner on the summary screen. */
.postgame-note {
  margin: 6px 14px 0;
  padding: 8px 12px;
  border-radius: var(--radius-sm);
  background: var(--panel-2);
  border: 1px solid var(--border-soft);
  color: var(--text-dim);
  font-size: 12.5px;
  display: flex; align-items: center; gap: 8px;
}
.postgame-note b { color: var(--text); }

/* In-app notifications, replacing the browser's "domain says:" alert box. Sits above
   everything (popups included) and never blocks interaction. */
#toastLayer {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  display: flex; flex-direction: column-reverse; align-items: center; gap: 8px;
  padding: 0 14px calc(18px + env(safe-area-inset-bottom, 0px));
  pointer-events: none;
  z-index: 90;
}
.toast {
  display: flex; align-items: center; gap: 9px;
  max-width: 100%;
  padding: 11px 14px;
  border-radius: 12px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  color: var(--text);
  font-size: 13px;
  line-height: 1.35;
  box-shadow: 0 10px 30px var(--shadow);
  opacity: 0;
  transform: translateY(10px);
  transition: opacity .22s ease, transform .22s ease;
}
.toast.is-open { opacity: 1; transform: translateY(0); }
.toast .icon { color: var(--amber); flex-shrink: 0; }
.toast.is-success .icon { color: var(--green); }

/* Post-game debrief: the summary screen becomes a chat screen while the window is open,
   so it behaves exactly like the in-game chat (fills the frame, newest at the bottom). */
.postgame-chat { flex: 1; min-height: 0; display: flex; flex-direction: column; margin: 0 14px 12px; }
.postgame-chat .chat-messages { flex: 1; min-height: 0; }
/* ---------------------------------------------------------------- replay ---- */
/* One-tap code chip: tapping it copies the t.me deep link, which is the thing people
   actually want to send — the bare code is useless on its own. */
.replay-code-chip {
  display: flex; align-items: center; gap: 8px; width: calc(100% - 28px);
  margin: 12px 14px 0; padding: 11px 13px; cursor: pointer;
  background: linear-gradient(180deg, var(--panel-2), var(--panel));
  border: 1px solid var(--border-soft); border-radius: var(--radius-md);
  color: var(--text); font-family: inherit; font-size: 13px; text-align: left;
  transition: transform .08s ease, border-color .15s ease;
}
.replay-code-chip:active { transform: scale(.985); border-color: var(--blue); }
.replay-code-chip__code { font-weight: 800; letter-spacing: .04em; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.replay-code-chip__hint {
  display: inline-flex; align-items: center; gap: 4px; flex-shrink: 0;
  font-size: 11px; font-weight: 700; color: var(--blue);
  text-transform: uppercase; letter-spacing: .04em;
}

/* Jump-to-day chips — a long game's transcript is a lot to scroll. */
.replay-day-jump { display: flex; gap: 6px; overflow-x: auto; padding: 10px 14px 2px; }
.replay-day-jump::-webkit-scrollbar { display: none; }
.replay-day-chip {
  flex-shrink: 0; padding: 5px 11px; border-radius: 999px; cursor: pointer;
  background: var(--panel-2); border: 1px solid var(--border-soft);
  color: var(--text-dim); font-family: inherit; font-size: 11.5px; font-weight: 700;
}
.replay-day-chip:active { border-color: var(--blue); color: var(--text); }

/* The transcript is the in-game chat, rendered as one flowing block. Same .msg /
   .msg-system styling the live game uses, so a replay reads exactly like the room did. */
.replay-transcript { padding: 10px 12px; display: flex; flex-direction: column; gap: 10px; }
.replay-transcript .day-divider { margin: 6px 0 2px; }
/* Roles are public once a game is over, so every speaker carries the role they turned
   out to have — that is what makes the day chat worth re-reading. */
.msg-role {
  display: inline-block; margin-left: 6px; padding: 0 5px; border-radius: 5px;
  background: var(--panel-3); color: var(--text-dim);
  font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em;
  vertical-align: middle;
}
.msg-role.is-mafia { background: var(--mafia); color: #fff; }
.msg-secret {
  /* block-level flex so the "maxfiy" marker sits on its OWN line above the message
     instead of running into the first words of it */
  display: flex; align-items: center; gap: 3px; margin-bottom: 2px;
  font-size: 9.5px; font-weight: 700; color: #f3a1ab; text-transform: uppercase; letter-spacing: .04em;
}
.msg-secret .icon { width: 11px; height: 11px; }


/* ============================================================================
   PHASE ATMOSPHERE
   Every screen used to be the same grey card on the same grey background, so the
   UI never told you which part of the game you were in and nothing built tension.
   app.js stamps data-phase="night|day|vote|over" on <html>, and each phase
   re-tints a handful of the tokens everything else is already built from — so the
   whole app changes mood without a single component being rewritten.
   ============================================================================ */
html[data-phase] body { transition: background-color .5s ease; }
/* The atmospheric wash is a PSEUDO-ELEMENT at z-index:-1, not a real element.
   The first version inserted a <div> and then had to lift every sibling with
   `.phone-frame > *:not(.phase-tint) { position: relative }` to keep it behind them —
   which turned the modal overlays (position:fixed) into in-flow flex items. They then
   ate the frame's height and squeezed the room list on the main menu down to 20px.
   z-index:-1 paints below the frame's content and above the page background with no
   side effects on layout at all. */
.phone-frame::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  transition: background .5s ease, opacity .5s ease;
}
.phone-frame { position: relative; }

/* --- NIGHT: cold, deep, closed-in ------------------------------------------ */
:root:not([data-theme="light"])[data-phase="night"] {
  --bg: #070912;
  --bg-2: #03040a;
  --panel: #121728;
  --panel-2: #182036;
  --panel-3: #1f2942;
  --border-soft: #1d2540;
  --accent: #6f8cff;
}
:root[data-phase="night"] .phone-frame::before {
  background:
    radial-gradient(120% 60% at 50% 0%, rgba(79,124,255,.16), transparent 70%),
    radial-gradient(100% 70% at 50% 100%, rgba(0,0,0,.75), transparent 60%);
}
/* The night belongs to whoever is awake in it: the frame takes the colour of YOUR
   role, so "my screen went red" is a thing players say out loud. */
:root:not([data-theme="light"])[data-phase="night"][data-role-side="mafia"] {
  --panel: #1c1013; --panel-2: #241417; --panel-3: #2f191d; --border-soft: #33191f;
  --accent: #e0576b;
}
:root[data-phase="night"][data-role-side="mafia"] .phone-frame::before {
  background:
    radial-gradient(120% 60% at 50% 0%, rgba(var(--mafia-rgb),.42), transparent 70%),
    radial-gradient(100% 70% at 50% 100%, rgba(0,0,0,.8), transparent 60%);
}
:root[data-phase="night"][data-role-side="doctor"] .phone-frame::before {
  background:
    radial-gradient(120% 60% at 50% 0%, rgba(34,197,94,.20), transparent 70%),
    radial-gradient(100% 70% at 50% 100%, rgba(0,0,0,.75), transparent 60%);
}
:root[data-phase="night"][data-role-side="detective"] .phone-frame::before {
  background:
    radial-gradient(120% 60% at 50% 0%, rgba(79,124,255,.24), transparent 70%),
    radial-gradient(100% 70% at 50% 100%, rgba(0,0,0,.75), transparent 60%);
}
:root[data-phase="night"][data-role-side="vigilante"] .phone-frame::before {
  background:
    radial-gradient(120% 60% at 50% 0%, rgba(234,179,8,.20), transparent 70%),
    radial-gradient(100% 70% at 50% 100%, rgba(0,0,0,.75), transparent 60%);
}

/* --- DAY: the same room the players were just talking in -------------------- */
/* This phase used to run a warm gold palette (--accent: #c9a86a), which is what
   coloured your own chat bubbles, every sender's name and the compose FAB. The
   daytime discussion is the SAME conversation the lobby was — the day skin turning
   it gold made the app look like it had changed screens when nothing had happened
   but the night ending. So `day` deliberately holds the app's default cool palette:
   it inherits --bg/--panel*/--accent from :root and paints no wash of its own,
   which is exactly what the pre-game lobby looks like.

   Night and vote still re-tint, so the phases that MUST feel different (your role's
   night, and the town turning on itself) are the only ones that do. Note this block
   covers `intro` as well — app.js maps both intro and day_discuss to phase "day" —
   which is what keeps the pre-night-1 chat and the day chat looking identical.

   If day should feel distinct again later, add a faint wash HERE using the accent
   blue (rgba(79,124,255,...)) rather than reintroducing an --accent override — the
   accent is load-bearing for the chat and reading it as "who is talking" matters
   more than atmosphere. */
:root[data-phase="day"] .phone-frame::before { background: none; }
:root[data-theme="light"][data-phase="night"] { --bg: #e7eaf5; --bg-2: #d5dae9; --panel: #fff; --panel-2: #f2f4fb; --accent: #3a5bd9; }
/* LIGHT THEME + a tinted phase. The phase blocks above re-tint --bg/--panel* to dark
   values but never touch --text, so on a light-theme phone (where --text is near-black)
   the vote and final-words screens came out as dark-grey panels with black text on them:
   readable for nobody, and only ever seen by players whose phone is in light mode, which
   is why it looked random. Every tinted phase now has a LIGHT counterpart, and the dark
   ones are scoped with :not([data-theme="light"]) so they can never apply here. */
:root[data-theme="light"][data-phase="night"][data-role-side="mafia"] {
  --panel: #fff5f5; --panel-2: #ffecec; --panel-3: #ffe0e0; --border-soft: #f3d3d3; --accent: #c0392f;
}
:root[data-theme="light"][data-phase="vote"] {
  --bg: #f7ecec; --bg-2: #efdcdc; --panel: #fff; --panel-2: #fdf2f2; --panel-3: #f8e6e6;
  --border-soft: #f0d8d8; --accent: #c0392f;
}
/* The wash itself is a dark radial gradient; at light-theme opacities it only needs to
   hint, not dim. */
:root[data-theme="light"] .phone-frame::before { opacity: .45; }

/* --- VOTE: the town turning on itself -------------------------------------- */
:root:not([data-theme="light"])[data-phase="vote"] {
  /* --vote-heat runs 0 -> 1 across the voting window (set from JS every poll). The red
     starts almost colourless and saturates as the clock runs down, so the pressure of
     the vote is something you feel building rather than a flat red screen. */
  --vote-heat: 0;
  --bg: #0f0c0d;
  --bg-2: #070505;
  --panel: #1a1416;
  --panel-2: #23191c;
  --panel-3: #2c1f23;
  --border-soft: #291c20;
  --accent: #e07070;
}
:root[data-phase="vote"] .phone-frame::before {
  background: radial-gradient(120% 60% at 50% 0%,
    rgba(239, 68, 68, calc(.05 + .22 * var(--vote-heat))), transparent 70%);
  /* Deliberately SLOW — a fast blink on a full-screen red wash is genuinely unpleasant
     and would hurt to look at for 30 seconds. 2.6s is a breath, not a strobe. */
  animation: voteBreathe 2.6s ease-in-out infinite;
}
@keyframes voteBreathe {
  0%, 100% { opacity: calc(.55 + .45 * var(--vote-heat)); }
  50%      { opacity: calc(.85 + .15 * var(--vote-heat)); }
}

/* ============================================================================
   TIMER BAR — a 30-second night is the tensest thing in the game and it used to
   be a static grey pill. This drains across the top of the frame, warms to amber
   and then to red, and pulses in the final seconds.
   ============================================================================ */
.timer-bar {
  position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: rgba(255,255,255,.06); z-index: 5; overflow: hidden;
}
.timer-bar__fill {
  height: 100%; width: 100%; transform-origin: left center;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  transition: transform 1s linear, background .4s ease;
}
.timer-bar.is-warn .timer-bar__fill { background: linear-gradient(90deg, var(--amber), #f59e0b); }
.timer-bar.is-danger .timer-bar__fill { background: linear-gradient(90deg, var(--red), #ff8080); animation: timerPulse 2s ease-in-out infinite; }
@keyframes timerPulse { 0%, 100% { opacity: 1; } 50% { opacity: .6; } }

/* Role-coloured accents inside the night action panel. */
.action-panel.role-doctor { border-color: rgba(34,197,94,.4); }
.action-panel.role-detective { border-color: rgba(79,124,255,.45); }
.action-panel.role-vigilante { border-color: rgba(234,179,8,.4); }


/* ============================================================================
   MAIN MENU HERO — the first screen had no identity at all: a plain centred
   title over a list of rows, indistinguishable from a settings page.
   ============================================================================ */
.menu-hero {
  /* flex-shrink:0 matters: .phone-frame is a flex column with overflow:hidden, so
     without it the hero was compressed by the room list below and its own contents were
     clipped — the emblem showed as a sliver at the top of the screen with the wordmark
     cut off entirely. */
  position: relative; flex-shrink: 0; text-align: center;
  /* --pill-band is part of the top offset, not just --safe-top. In fullscreen Telegram
     floats its Close/menu pills in that band OVER the page, and the hero was starting
     underneath them — the logo sat behind Telegram's own buttons. Starting below the
     band is what keeps the lockup clear of them on every device. */
  padding: calc(var(--safe-top) + var(--pill-band) + 14px) 20px 12px;
  overflow: hidden;
}
.menu-hero__glow {
  position: absolute; inset: -40% -20% auto -20%; height: 200px; pointer-events: none;
  /* Warm amber, not the app's purple accent: the emblem and wordmark are both gold,
     and a violet wash behind gold artwork read as a colour clash rather than a glow. */
  background: radial-gradient(60% 100% at 50% 0%, rgba(201,168,106,.28), transparent 70%);
}
/* Horizontal lockup — emblem beside the wordmark rather than stacked above it. Stacked,
   the hero ate close to half the screen on a phone and pushed the room list out of
   sight; side by side it costs ~90px instead of ~230px for the same identity. */
.menu-hero__lockup {
  position: relative; margin: 0;
  display: flex; align-items: center; justify-content: center; gap: 10px;
  /* It is still an <h1>: reset the heading's own type so only the images show. */
  font-size: 0; line-height: 0;
}
.menu-hero__emblem {
  /* Width AND height are pinned so nothing reflows between preload and decode. */
  flex: none; width: 88px; height: 88px;
  filter: drop-shadow(0 8px 20px rgba(0,0,0,.55));
}
.menu-hero__wordmark {
  flex: none; width: 132px; height: auto;
  filter: drop-shadow(0 5px 14px rgba(0,0,0,.5));
}

/* The lockup is wider than the stacked version was, so on a short screen shrink it
   rather than letting it crowd the row of buttons underneath. */
@media (max-height: 700px) {
  .menu-hero { padding: calc(var(--safe-top) + var(--pill-band) + 8px) 20px 8px; }
  .menu-hero__emblem { width: 68px; height: 68px; }
  .menu-hero__wordmark { width: 104px; }
}

/* Room rows: who is waiting in there, not just how many. */
.room-row__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 7px; }
.room-row__title { display: flex; align-items: center; gap: 8px; }
.room-row__title .name { font-weight: 700; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.room-row__foot { display: flex; align-items: center; gap: 8px; }
.room-row__foot .meta { color: var(--text-dim); font-size: 11.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.avatar-stack { display: inline-flex; align-items: center; flex-shrink: 0; }
.avatar-stack img {
  width: 22px; height: 22px; border-radius: 50%; object-fit: cover;
  border: 2px solid var(--panel); margin-right: -8px;
}
.avatar-stack img:first-child { margin-left: 0; }
.avatar-stack__more {
  margin-left: 12px; font-size: 10.5px; font-weight: 700; color: var(--text-dim);
}
.menu-empty {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 34px 24px; text-align: center; color: var(--text-dim); font-size: 13px;
}
.menu-empty .icon { width: 34px; height: 34px; opacity: .35; }
.menu-empty .dim { font-size: 11.5px; opacity: .7; }

/* The quick-join button is the primary action on the menu, so it gets the weight —
   "Yangi xona" moves to the secondary row above it. */
.quickjoin { margin: 6px 16px 4px; padding: 16px; font-size: 15.5px; flex-shrink: 0; }
.section-title { flex-shrink: 0; }


/* ============================================================================
   NIGHT SKY — shown to players with no night action (townspeople and
   spectators), who previously stared at a single blinking dot for 30 seconds.
   Transform/opacity only, so the compositor does the work and there is no JS
   timer to keep alive across a poll re-render.
   ============================================================================ */
/* The whole idle night view is centred in whatever height is left, rather than
   sitting at the top with a screenful of nothing under it. */
.night-idle {
  min-height: 100%; display: flex; flex-direction: column; justify-content: center;
  padding-bottom: 40px;
}
.night-scene {
  position: relative; height: 240px; flex-shrink: 0; overflow: hidden;
  margin: 0;
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 14%, #000 82%, transparent);
          mask-image: linear-gradient(180deg, transparent, #000 14%, #000 82%, transparent);
}
.night-moon {
  position: absolute; left: 50%; top: 50%; width: 132px; height: 132px;
  margin: -66px 0 0 -66px; z-index: 1;
  animation: moonFloat 11s ease-in-out infinite alternate;
  filter: drop-shadow(0 0 26px rgba(242, 223, 174, .38));
}
.night-moon svg { width: 100%; height: 100%; display: block; }
@keyframes moonFloat {
  from { transform: translateY(-9px) rotate(-1.5deg); }
  to   { transform: translateY(9px)  rotate(1.5deg); }
}

/* Each cloud crosses the full width and fades in and out on the way, so they
   never pop in or out at the edges. Sizes/speeds/delays are set inline per
   cloud — same silhouette, but nothing reads as repeated. */
/* Soft, low-contrast and slightly blurred: at full opacity these read as solid grey
   blobs pasted over the sky rather than cloud. Two of them sit BEHIND the moon and two
   in front (z-index below), which is what gives the scene any depth. */
.night-cloud {
  position: absolute; left: 0; height: auto; color: #46527a; opacity: .26;
  filter: blur(2.5px);
  will-change: transform;
  animation-name: cloudDrift;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}
@keyframes cloudDrift {
  0%   { transform: translateX(-140%); opacity: 0; }
  15%  { opacity: 1; }
  75%  { opacity: 1; }
  100% { transform: translateX(calc(100vw + 60px)); opacity: 0; }
}
.night-cloud.is-1 { z-index: 2; }
.night-cloud.is-3 { z-index: 2; }
.night-cloud.is-2 { z-index: 0; }
.night-cloud.is-4 { z-index: 0; }
.night-star {
  position: absolute; width: 3px; height: 3px; border-radius: 50%;
  background: #dfe6ff; box-shadow: 0 0 6px rgba(223,230,255,.8);
  animation: starTwinkle 3.6s ease-in-out infinite;
}
@keyframes starTwinkle { 0%, 100% { opacity: .25; transform: scale(.8); } 50% { opacity: .95; transform: scale(1); } }

/* .waiting-screen is flex:1 by default, so inside the centred .night-idle column it
   stretched and pushed the caption far below the sky. Here it hugs its own content and
   sits directly under the moon. */
.night-wait { flex: 0 0 auto; padding: 10px 30px 0; }

@media (prefers-reduced-motion: reduce) {
  .night-moon, .night-cloud, .night-star { animation: none; }
  .night-cloud { opacity: .4; transform: translateX(20vw); }
}


/* The boot failure screen — replaces an eternal "Yuklanmoqda..." with something that
   says what went wrong and what to do about it. */
.boot-error {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 10px; padding: 30px 26px; text-align: center; color: var(--text-dim);
}
.boot-error__icon { width: 46px; height: 46px; color: var(--accent); opacity: .9; }
.boot-error__title {
  font-family: var(--font-display); font-size: 17px; font-weight: 800; color: var(--text);
}
.boot-error p { margin: 0; font-size: 13.5px; line-height: 1.55; max-width: 300px; }
.boot-error .btn {
  /* .block is flex:1, which in this COLUMN made the button stretch to fill the frame */
  flex: 0 0 auto; margin-top: 10px; min-width: 210px;
}
.boot-error__code {
  margin-top: 6px; font-size: 10.5px; opacity: .45; letter-spacing: .03em;
  font-variant-numeric: tabular-nums;
}
/* ============================================================================
   STATS & LEADERBOARD
   The profile screen used to be a name field and nothing else; these are the
   blocks renderStatsBlock()/renderLeaderboard() emit. Everything reuses the
   existing tokens — no new colours — so the two screens can't drift away from
   the rest of the app when the palette is touched.
   ============================================================================ */

/* Right-hand note on a section heading ("2-mavsum · 24 kun qoldi"). */
.section-title__right {
  margin-left: auto; font-weight: 600; font-size: 11px; color: var(--text-dim);
  letter-spacing: 0; text-transform: none;
}

/* The rank/points pill under the avatar. Gold, because it is the one element on
   the screen that is meant to be shown off. */
.profile-rank-pill {
  display: inline-flex; align-items: center; gap: 8px; padding: 6px 14px; border-radius: 999px;
  background: linear-gradient(135deg, rgba(217,168,64,.22), rgba(217,168,64,.07));
  border: 1px solid rgba(217,168,64,.45);
  font-family: var(--font-display); font-weight: 800; font-size: 12.5px; color: var(--gold);
}
.profile-rank-pill .sep { width: 1px; height: 12px; background: rgba(217,168,64,.4); }

/* Four headline numbers. Two columns, because three made the labels wrap on a
   narrow phone and four put them at 9px. */
.stat-tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; padding: 10px 16px 0; }
.stat-tile {
  background: var(--panel); border: 1px solid var(--border-soft);
  border-radius: var(--radius-md); padding: 12px 13px;
}
.stat-tile .v {
  font-family: var(--font-display); font-weight: 800; font-size: 23px; line-height: 1;
  /* Tabular figures so the four tiles' numbers line up with each other and don't
     jiggle as they change. */
  font-variant-numeric: tabular-nums;
}
.stat-tile .v.is-good { color: var(--green); }
.stat-tile .v.is-gold { color: var(--gold); }
.stat-tile .l { margin-top: 5px; font-size: 11px; color: var(--text-dim); font-weight: 600; }

.stat-card {
  margin: 10px 16px 0; background: var(--panel); border: 1px solid var(--border-soft);
  border-radius: var(--radius-md); padding: 13px;
}

/* Town vs mafia win rate. */
.stat-side { display: flex; align-items: center; gap: 10px; font-size: 13px; }
.stat-side + .stat-side { margin-top: 11px; padding-top: 11px; border-top: 1px solid var(--border-soft); }
.stat-side__name { font-weight: 700; width: 74px; flex: none; display: flex; align-items: center; gap: 7px; }
.stat-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.stat-dot.is-town { background: var(--accent); }
.stat-dot.is-mafia { background: #e06a78; }
.stat-bar { flex: 1; height: 7px; border-radius: 99px; background: var(--panel-3); overflow: hidden; }
.stat-bar i { display: block; height: 100%; border-radius: 99px; }
.stat-bar i.is-town { background: linear-gradient(90deg, var(--accent), var(--accent-2)); }
.stat-bar i.is-mafia { background: linear-gradient(90deg, var(--mafia), #e06a78); }
.stat-side__pc {
  width: 68px; flex: none; text-align: right; font-family: var(--font-display);
  font-weight: 700; font-size: 12px; color: var(--text-dim); font-variant-numeric: tabular-nums;
}
.stat-side__pc b { color: var(--text); }

/* One row per role the player has actually held — roles they've never drawn are
   simply absent rather than shown as an empty 0-game row. */
.stat-role { display: flex; align-items: center; gap: 11px; padding: 11px 0; border-top: 1px solid var(--border-soft); }
.stat-role:first-child { border-top: none; padding-top: 2px; }
.stat-role__ic {
  width: 32px; height: 32px; border-radius: 9px; flex: none;
  background: var(--panel-2); color: var(--accent);
  display: flex; align-items: center; justify-content: center;
}
.stat-role.is-mafia .stat-role__ic { color: #e06a78; background: rgba(var(--mafia-rgb), .22); }
.stat-role__main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.stat-role__name { font-weight: 700; font-size: 13px; }
.stat-role__sub { font-size: 11px; color: var(--text-dim); margin-top: 2px; }
.stat-role__rate {
  flex: none; font-family: var(--font-display); font-weight: 800; font-size: 13px;
  color: var(--text-dim); font-variant-numeric: tabular-nums;
}
.stat-role__rate.is-good { color: var(--green); }

.stat-streak {
  margin: 10px 16px 0; display: flex; align-items: center; gap: 10px; padding: 11px 13px;
  border-radius: var(--radius-md); font-size: 12.5px;
  background: rgba(34,197,94,.09); border: 1px solid rgba(34,197,94,.35);
}
.stat-streak b { color: var(--green); }

.stats-empty { padding: 30px 16px; }
/* The last element before the bottom of a scrolling screen, so the final row
   never sits flush against the edge (or under Android's gesture bar). */
.stats-foot { height: calc(20px + var(--gap-bottom)); }

/* ---- leaderboard ---- */
.lb-tabs { display: flex; gap: 7px; padding: 4px 16px 2px; }
.lb-tab {
  flex: 1; padding: 9px; border-radius: var(--radius-sm); border: 1px solid var(--border);
  background: transparent; color: var(--text-dim); font-weight: 700; font-size: 12px; cursor: pointer;
}
.lb-tab.is-active {
  color: #fff; border-color: transparent;
  background: linear-gradient(180deg, var(--accent), color-mix(in srgb, var(--accent) 80%, black));
}
.lb-row {
  display: flex; align-items: center; gap: 11px; margin: 8px 16px 0; padding: 10px 12px;
  background: var(--panel); border: 1px solid var(--border-soft); border-radius: var(--radius-md);
}
.lb-row.is-me {
  border-color: var(--accent);
  background: linear-gradient(180deg, rgba(79,124,255,.16), rgba(79,124,255,.06));
}
.lb-rank {
  width: 24px; flex: none; text-align: center; font-family: var(--font-display);
  font-weight: 800; font-size: 14px; color: var(--text-dim); font-variant-numeric: tabular-nums;
}
.lb-row.is-top .lb-rank { color: var(--gold); }
.lb-row img { width: 36px; height: 36px; border-radius: 50%; object-fit: cover; flex: none; }
.lb-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.lb-name { font-weight: 700; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lb-you { color: var(--accent); font-size: 11px; font-style: normal; }
.lb-sub { font-size: 11px; color: var(--text-dim); margin-top: 2px; }
.lb-score {
  flex: none; text-align: right; font-family: var(--font-display); font-weight: 800;
  font-size: 14px; color: var(--gold); font-variant-numeric: tabular-nums;
}
.lb-score span { display: block; font-family: inherit; font-weight: 600; font-size: 10px; color: var(--text-dim); margin-top: 1px; }
/* Separator before the pinned "your position" row, for a player outside the top 50. */
.lb-sep {
  margin: 18px 16px 0; padding-top: 12px; border-top: 1px solid var(--border-soft);
  font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--text-dim);
}

/* The home-screen-shortcut offer on the summary screen (see considerHomeScreenPrompt in
   app.js). Deliberately a calm card rather than a modal: it appears after a game the
   player just enjoyed, and an interrupting dialog there would read as nagging. */
.home-screen-prompt {
  margin: 12px 16px 0; padding: 13px; border-radius: var(--radius-md);
  background: linear-gradient(180deg, rgba(217,168,64,.13), rgba(217,168,64,.05));
  border: 1px solid rgba(217,168,64,.4);
}
.home-screen-prompt__text { display: flex; gap: 10px; align-items: flex-start; font-size: 12.5px; line-height: 1.45; }
.home-screen-prompt__text .icon { color: var(--gold); flex-shrink: 0; margin-top: 1px; }
.home-screen-prompt__actions { display: flex; gap: 8px; margin-top: 11px; }
.home-screen-prompt__actions .btn { flex: 1; }

/* "Share to story" on the summary screen. Gold rather than the app's blue primary: it
   sits directly under the replay-share button and the two must not read as the same
   action. Hidden until app.js confirms the client actually supports shareToStory. */
.btn.btn-story {
  background: linear-gradient(180deg, rgba(217,168,64,.20), rgba(217,168,64,.08));
  border-color: rgba(217,168,64,.5); color: var(--gold);
}
.btn.btn-story .icon { color: var(--gold); }

/* ============================================================================
   SETTINGS ROWS (profile screen)
   A real <input type="checkbox"> is kept in the DOM and visually hidden rather
   than replaced by a div: it keeps keyboard focus, the label-click target, and
   screen-reader semantics for free, and .setting-row__box is just its skin.
   ============================================================================ */
.settings-card {
  margin: 10px 16px 0; background: var(--panel); border: 1px solid var(--border-soft);
  border-radius: var(--radius-md); padding: 4px 13px;
}
.setting-row {
  display: flex; align-items: flex-start; gap: 12px; padding: 12px 0; cursor: pointer;
}
.setting-row + .setting-row { border-top: 1px solid var(--border-soft); }
/* Hidden from sight, not from the accessibility tree or the tab order. */
.setting-row input[type="checkbox"] {
  position: absolute; opacity: 0; width: 0; height: 0;
}
.setting-row__box {
  flex: none; width: 24px; height: 24px; border-radius: 7px; margin-top: 1px;
  border: 2px solid var(--border); background: var(--panel-2);
  display: flex; align-items: center; justify-content: center;
  color: transparent; transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.setting-row input:checked + .setting-row__box {
  background: linear-gradient(180deg, var(--accent), color-mix(in srgb, var(--accent) 80%, black));
  border-color: transparent; color: #fff;
}
/* Visible focus ring for keyboard users, since the real input is invisible. */
.setting-row input:focus-visible + .setting-row__box {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 45%, transparent);
}
.setting-row__text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.setting-row__name { font-size: 13.5px; font-weight: 700; }
.setting-row__desc { font-size: 11.5px; color: var(--text-dim); line-height: 1.45; }

/* ============================================================================
 TABLE MODE

 Playing around a real table: the app narrates and referees, the talking
 happens out loud, and there is no chat. Everything below is new UI that the
 online game has no use for — it is kept in one block rather than threaded
 through the sections above so that it is obvious what belongs to which mode.

 Every one of these rules was drawn and checked first in public/table-mock.html,
 which renders each table screen against this same stylesheet.
 ============================================================================ */
/* ---- the majority button ----
   There is no host, so a table action is a vote: you press, you are counted, and it
   fires when enough of the living have pressed. The fill is the tally made physical,
   and the line underneath names who is still missing — that is what makes the fifth
   person press it. */
.consensus { display: grid; gap: 8px; padding: 0 14px 12px; }
.consensus__btn {
  position: relative; overflow: hidden; width: 100%; display: block; text-align: left;
  padding: 11px 13px; border-radius: var(--radius-sm);
  border: 1px solid var(--border); background: var(--panel-2); color: var(--text);
  font-family: var(--font-display); font-weight: 800; font-size: 13.5px;
}
.consensus__fill {
  position: absolute; inset: 0 auto 0 0; width: 0;
  background: rgba(79,124,255,.26); transition: width .35s cubic-bezier(.32,.72,0,1);
}
.consensus__row { position: relative; display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.consensus__tally { font-variant-numeric: tabular-nums; font-size: 12.5px; color: var(--text-dim); flex-shrink: 0; }
.consensus__who {
  position: relative; margin-top: 4px; font-family: var(--font-body); font-weight: 500;
  font-size: 11px; color: var(--text-dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.consensus__btn.is-mine { border-color: var(--accent); }
.consensus__btn.is-mine .consensus__tally { color: #9db4ff; }
.consensus__btn.is-done { border-color: var(--green); }
.consensus__btn.is-done .consensus__fill { background: rgba(34,197,94,.3); }
.consensus__btn.is-done .consensus__tally { color: #6ee7a0; }

/* ---- the out-loud day ----
   Nobody is reading their phone during discussion, so the timer stops being a pill in
   the header and becomes the screen. */
.table-clock { flex: 1; display: grid; place-content: center; text-align: center; gap: 6px; padding: 16px 24px; }
.table-clock__time { font-family: var(--font-display); font-weight: 800; font-size: 58px; font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
.table-clock__time.is-hot { color: var(--red); }
.table-clock__label { font-size: 12.5px; color: var(--text-dim); line-height: 1.5; }

/* ---- the narrator ----
   The app's existing system messages, set large and paced, instead of stacked in a
   chat nobody is looking at. Holds until the room has finished groaning: it advances
   on a majority, not a timer. */
.narr { flex: 1; display: grid; align-content: center; gap: 10px; padding: 10px 20px; }
.narr__line { font-family: var(--font-display); font-weight: 700; font-size: 15px; line-height: 1.4; text-align: center; color: var(--text-dim); }
.narr__line.is-big { font-size: 21px; color: var(--text); }
.narr__line.is-dead { color: #ff9aa5; }
.narr__line.is-reveal { color: var(--gold); }
.narr__rule { height: 1px; background: var(--border-soft); margin: 4px 30px; }

/* ---- the sheep field ----
   Sits on top of the app's own night sky. Two sizes: `is-full` for a player with no
   night action, `is-band` for one who has a panel above. The band NEVER overlaps the
   action panel — a mistapped sheep must never land on the kill grid and pick a
   target by accident. */
.sheep { position: relative; overflow: hidden; flex-shrink: 0; }
.sheep.is-full { flex: 1; min-height: 0; }
.sheep.is-band { height: 38%; margin-top: auto; border-top: 1px solid var(--border-soft); }
.sheep .night-scene { position: absolute; inset: 0; height: auto; }
.sheep__title { position: absolute; top: 10px; left: 0; right: 0; text-align: center; font-size: 11.5px; color: var(--text-dim); z-index: 3; }
.fence {
  position: absolute; left: 0; right: 0; bottom: 30%; height: 1px; z-index: 2;
  background: linear-gradient(90deg, transparent, rgba(160,174,214,.35) 20%, rgba(160,174,214,.35) 80%, transparent);
}
.fence::before, .fence::after { content: ""; position: absolute; bottom: -7px; width: 1px; height: 14px; background: rgba(160,174,214,.35); }
.fence::before { left: 32%; }
.fence::after  { left: 64%; }

.ewe { position: absolute; bottom: 24%; left: -70px; width: 56px; height: 42px; z-index: 3; animation: eweWalk linear forwards; }
.ewe__hop { width: 100%; height: 100%; animation: eweHop ease-in-out infinite; }
.ewe svg { width: 100%; height: 100%; display: block; }
@keyframes eweWalk { to { transform: translateX(calc(100vw + 140px)); } }
@keyframes eweHop  { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-18px); } }
.ewe.is-counted { animation-play-state: paused; }
.ewe.is-counted .ewe__hop { animation: none; transform: scale(1.35); opacity: 0; transition: transform .32s ease, opacity .32s ease; }

.plus1 { position: absolute; z-index: 4; font-family: var(--font-display); font-weight: 800; font-size: 13px; color: #fff; pointer-events: none; animation: plusRise .7s ease-out forwards; }
@keyframes plusRise { to { transform: translateY(-26px); opacity: 0; } }

.sheep__hud {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 4; padding: 9px 13px;
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  font-size: 11px; color: var(--text-dim);
  background: linear-gradient(180deg, transparent, rgba(0,0,0,.45));
}
.sheep__count { font-family: var(--font-display); font-weight: 800; font-size: 13px; color: var(--text); font-variant-numeric: tabular-nums; }
/* The awake meter is the 10-second window made visible: it refills on a tap and
   drains when you ignore the flock. Empty means you slept — which costs you
   tomorrow's VOTE, never your life. Nobody gets eliminated by a slow phone. */
.awake { flex: 1; max-width: 110px; height: 4px; border-radius: 999px; background: rgba(255,255,255,.1); overflow: hidden; }
.awake i { display: block; height: 100%; width: 100%; background: var(--green); transition: width .3s linear, background .3s ease; }
.awake.is-low i { background: var(--amber); }

/* ---- main menu: scan sits beside Tezkor qo'shilish ----
   The quick-join button keeps its size; the scanner is a square the same height next
   to it, because scanning is how you join the table you are already sitting at. */
.quickjoin-row { display: flex; gap: 10px; margin: 6px 16px 4px; flex-shrink: 0; align-items: stretch; }
.quickjoin-row .quickjoin { margin: 0; flex: 1; }
.scan-btn {
  flex: 0 0 58px; display: grid; place-items: center; border-radius: var(--radius-md);
  background: var(--panel-2); border: 1px solid var(--border); color: var(--text);
}
.scan-btn .icon { width: 30px; height: 30px; }
.scan-btn__cap { font-size: 9px; color: var(--text-dim); font-weight: 700; letter-spacing: .04em; margin-top: 2px; }

/* Mockup-only: the stack needs an explicit flex basis here because these rows are
   hand-built rather than rendered by the app's own room-list code. */


/* ---- create room: a third mode ---- */

/* The deeplink under the QR. Same value the QR encodes, so a plain camera app and
   the in-app scanner land in exactly the same place. */
.deeplink-row { display: flex; align-items: center; justify-content: center; gap: 7px; margin-top: 10px; }
.deeplink-row button {
  display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 700;
  color: var(--accent); background: none; border: none; padding: 4px;
}
.deeplink-url { text-align: center; font-size: 10px; color: var(--text-dim); margin-top: 4px; word-break: break-all; padding: 0 10px; }

/* ---- the ten seconds before the role card ---- */
.countdown-screen { flex: 1; display: grid; place-content: center; text-align: center; gap: 14px; padding: 30px 26px; }
.countdown-screen .ring {
  width: 108px; height: 108px; margin: 0 auto; border-radius: 50%;
  display: grid; place-items: center; font-family: var(--font-display); font-weight: 800; font-size: 40px;
  background: conic-gradient(var(--amber) 0 70%, var(--panel-2) 0);
  position: relative;
}
.countdown-screen .ring::before { content: ""; position: absolute; inset: 7px; border-radius: 50%; background: var(--bg); }
.countdown-screen .ring span { position: relative; }
.countdown-screen .msg { font-size: 13.5px; line-height: 1.55; color: var(--text); }

/* ---- shortened replay ---- */
.replay-line { display: flex; gap: 9px; padding: 9px 11px; border-radius: var(--radius-sm); background: var(--panel); border: 1px solid var(--border-soft); font-size: 12.5px; color: var(--text-dim); align-items: flex-start; }
.replay-line b { color: var(--text); }
.replay-line .tag { font-size: 9.5px; padding: 2px 6px; border-radius: 6px; background: var(--panel-3); flex-shrink: 0; font-weight: 800; white-space: nowrap; }
.replay-line .tag.is-vote { background: rgba(79,124,255,.2); color: #9db4ff; }
.replay-line .tag.is-night { background: rgba(var(--mafia-rgb),.28); color: #f3a1ab; }

/* ---- lobby ---- */
.qr { width: 136px; height: 136px; margin: 0 auto; padding: 8px; border-radius: 10px; background: #fff; display: grid; grid-template-columns: repeat(21, 1fr); }
.qr i { display: block; aspect-ratio: 1; }
.qr i.on { background: #0b0d12; }
.join-code { text-align: center; margin-top: 9px; font-size: 11.5px; color: var(--text-dim); }
.join-code b { color: var(--text); letter-spacing: .12em; font-family: var(--font-display); }
.roster { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; padding: 0 14px; }
.chip { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px 4px 4px; border-radius: 999px; background: var(--panel-2); border: 1px solid var(--border-soft); font-size: 11px; font-weight: 600; }
.chip img { width: 19px; height: 19px; border-radius: 50%; object-fit: cover; }
.chip.is-ready { border-color: rgba(34,197,94,.5); background: rgba(34,197,94,.12); }
.chip.is-ready::after { content: "✓"; color: var(--green); font-weight: 800; }

/* ---- the private card ---- */
.hold-note { margin: 0 14px 12px; padding: 10px 12px; border-radius: var(--radius-sm); background: rgba(234,179,8,.1); border: 1px solid var(--amber); font-size: 12px; display: flex; gap: 8px; align-items: center; }
.hold-note .icon { color: var(--amber); flex-shrink: 0; }

/* ---- who voted for whom ---- */
.vlist { display: grid; gap: 5px; padding: 2px 14px; }
.vrow { display: flex; align-items: center; gap: 7px; font-size: 12px; padding: 6px 9px; border-radius: 8px; background: var(--panel-2); border: 1px solid var(--border-soft); }
.vrow img { width: 19px; height: 19px; border-radius: 50%; object-fit: cover; flex-shrink: 0; }
.vrow .arrow { color: var(--text-dim); }
.vrow .tgt { font-weight: 700; }
.vrow.is-me { border-color: var(--accent); }
.vrow .tag { margin-left: auto; font-size: 10px; color: var(--text-dim); }

/* ---- the dead player's phone ----
   No header, no timer, no colour: the screen goes dark for the rest of the game.
   That removes two tells at once — no glow from their phone at night, and no hands
   moving while the living count sheep. */
.dead-screen { flex: 1; display: grid; place-content: center; gap: 8px; text-align: center; padding: 34px; color: #454d5c; }
.dead-screen .x { font-family: var(--font-display); font-weight: 800; font-size: 15px; color: #6b7383; }
.dead-screen .s { font-size: 12px; }

/* Who you are working with. Online the mafia meet in the secret chat, so this line only
   exists in table mode — where the role card is the one and only place it can be said. */
.role-card__team { margin-top: 12px; font-size: 12px; color: var(--text-dim); }
.role-card__team b { color: var(--text); }
.role-card.team-mafia .role-card__team b { color: #f3a1ab; }

/* A table game's replay is nothing but narration — no bubbles, no speakers — so its
   lines are cards rather than the dim separators a chat log uses. The reveal keeps the
   gold it had on the night: it is what people scroll back for. */
.replay-line {
  padding: 9px 11px; border-radius: var(--radius-sm); background: var(--panel);
  border: 1px solid var(--border-soft); font-size: 12.5px; color: var(--text-dim);
  line-height: 1.45;
}
.replay-line + .replay-line { margin-top: 6px; }
.replay-line.is-reveal { color: var(--gold); font-weight: 700; border-color: rgba(217,168,64,.35); }
/* =====================================================================================
   PREMIUM
   -------------------------------------------------------------------------------------
   Three visible things: a badge before a name, a frame around an avatar, and the
   profile card either of them opens. Badges and frames are WebP artwork under
   assets/img/badges and assets/img/frames (keys = Premium::ICONS / FRAMES).

   The server decides who is premium; this file only draws it. Nothing here keys off
   anything but the markup premiumBadge()/avatarHtml() emit.
   ===================================================================================== */

/* --- the badge next to a name ------------------------------------------------------ */
/* The badge is an <img> of real artwork (assets/img/badges/*.webp) that carries its
   own colour — which is most of why it reads as premium rather than as a UI icon. */
/* `img.prem-badge`, not `.prem-badge`: the badge is an <img>, and every avatar context
   already has a rule like `.msg img { width: 28px }` at the same specificity that lands
   EARLIER in this file. Without the element selector the badge inherits the avatar's
   size and a crown turns up in a chat bubble twice the height of the name. */
img.prem-badge {
  display: inline-block; vertical-align: -2px;
  width: 14px; height: 14px; flex: none;
  /* BEFORE the name, so the gap belongs on the right. */
  margin-right: 4px;
  /* An avatar-sized badge must never stretch a chat row. */
  object-fit: contain;
}
img.prem-badge.is-big { width: 20px; height: 20px; vertical-align: -3px; }
img.prem-badge.is-xl  { width: 30px; height: 30px; margin: 0; vertical-align: middle; }

/* --- the corner badge on a grid cell ----------------------------------------------- */
/* In a 4-column grid the name is about 90px wide and a crown appended to it wraps or
   clips, so in a grid the badge goes where the vote count goes: the corner. Left, not
   right — the right corner is already the vote count, and during the day both can be on
   the same cell at once. */
.player-cell .prem-cell,
.summary-card .prem-cell {
  /* INSIDE the cell, not hanging off its corner. Hung outside it was clipped by the
     grid card's own edge on the top row — the first row of a 4-column grid is exactly
     where the most-looked-at players sit.
     TOP-RIGHT, because top-LEFT is where the mafia night grid puts .pick-count ("2 of 4
     have chosen this face") and the two would sit exactly on top of each other. The
     voting grid, which owns the top-right corner for its vote count, does not draw this
     badge at all — see renderDayVote. */
  position: absolute; top: 3px; right: 3px; z-index: 3;
  /* SIZED RELATIVE TO THE CELL, not in fixed pixels. A 4-player grid gives an 80px cell
     and a 16-player grid gives a 32px one — at a fixed 19px the badge covered almost the
     entire avatar in a full room, which is exactly the room where it matters most.
     Clamped at both ends so it stays legible small and never dominates when large. */
  width: clamp(10px, 26%, 18px); aspect-ratio: 1 / 1; height: auto;
  border-radius: 999px;
  display: flex; align-items: center; justify-content: center;
  background: var(--panel);
  box-shadow: 0 0 0 1.5px var(--panel), 0 2px 6px rgba(0,0,0,.45);
}
.player-cell img.prem-cell__art,
.summary-card img.prem-cell__art { width: 72%; height: 72%; object-fit: contain; display: block; }
/* The badge dims with the cell it is on: on your own (untargetable) cell and on a dead
   player, a full-brightness crown floating over a greyed-out face reads as a rendering
   bug rather than a badge. */
.player-cell.is-self .prem-cell,
.player-cell.is-dead .prem-cell,
.summary-card.is-dead .prem-cell { opacity: .45; }

/* --- the frame around an avatar ---------------------------------------------------- */
/* Every frame is a picture (public/assets/img/frames/<key>.webp), and every picture is
   normalised the same way: the avatar hole sits dead centre and its radius is a fixed
   share of the canvas. That is what lets these few numbers fit all 48 frames.

   .avf takes the size the bare avatar had in that context (the per-context rules
   below), so nothing in the layout moves when a player becomes premium. Inside it the
   photo shrinks to --av of the box and the artwork is laid over it at --art, centred,
   spilling past the box on every side. The ratio between the two is fixed by the
   artwork (--art = --av * 1.9 / 1.06): change one, recompute the other.
   The spill is deliberate — a crown or a pair of wings needs room outside the circle —
   and it never catches a tap (pointer-events: none). */
.avf {
  --av: 82%; --art: 147%;
  position: relative; display: inline-block; flex: none; line-height: 0;
  vertical-align: middle;
}
.avf > img:first-child {
  position: absolute; left: calc((100% - var(--av)) / 2); top: calc((100% - var(--av)) / 2);
  width: var(--av) !important; height: var(--av) !important;
  margin: 0 !important; border: 0 !important; border-radius: 50%; object-fit: cover; display: block;
  box-shadow: none !important;
}
.avf > img.avf__art {
  position: absolute; left: calc((100% - var(--art)) / 2); top: calc((100% - var(--art)) / 2);
  width: var(--art) !important; height: var(--art) !important;
  max-width: none !important; margin: 0 !important; border: 0 !important; border-radius: 0 !important;
  background: none !important; box-shadow: none !important; object-fit: contain;
  pointer-events: none; z-index: 2;
}

/* Per-context sizing: each is the size that context already gave the bare <img>. */
.msg .avf { width: 28px; height: 28px; }
.vrow .avf, .chip .avf { width: 19px; height: 19px; }
.lb-row .avf { width: 36px; height: 36px; }
.summary-card .avf { width: 38px; height: 38px; }
.summary-grid.is-compact .summary-card .avf { width: 28px; height: 28px; }
.player-cell .avf { display: block; width: 68%; height: auto; aspect-ratio: 1/1; margin: 0 auto 4px; }
.avatar-heat-wrap:has(.avf) { display: block; width: 68%; margin: 0 auto 4px; }
.avatar-heat-wrap .avf { width: 100%; margin: 0; }
.profile-avatar-wrap .avf { width: 92px; height: 92px; }
.profile-card .avf { width: 68px; height: 68px; }
.prem-pick .avf { width: 30px; height: 30px; }
.avatar-stack .avf { width: 26px; height: 26px; }
/* In a tight grid cell the frame's spill would run into the neighbouring face, so it
   stays a little closer to the photo there. Same ratio, smaller box. */
.player-cell .avf { --av: 86%; --art: 154%; }

/* --- the profile card --------------------------------------------------------------- */
.profile-card { text-align: left; max-width: 330px; }
.profile-card.is-premium { border-color: rgba(217,168,64,.45); }
.profile-head { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.profile-face {
  width: 68px; height: 68px; border-radius: 999px; object-fit: cover; flex: 0 0 auto;
  background-color: var(--panel-2);
}
.profile-id { min-width: 0; }
.profile-name {
  font-family: var(--font-display, inherit); font-weight: 800; font-size: 18px;
  color: var(--text); display: flex; align-items: center; gap: 2px;
  /* A long name must truncate rather than push the badge off the card. */
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.profile-tier {
  font-size: 11px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase;
  color: var(--gold); margin-top: 2px;
}
.profile-bio {
  font-size: 13px; line-height: 1.45; color: var(--text-dim);
  background: var(--panel-2); border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm); padding: 9px 11px; margin-bottom: 12px;
  /* 150 characters of a language with no spaces would otherwise run off the card. */
  overflow-wrap: anywhere;
}
.profile-stats { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 10px; }
.pstat {
  background: var(--panel-2); border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm); padding: 8px 10px;
  display: flex; flex-direction: column; gap: 1px;
}
.pstat b { font-size: 17px; font-weight: 800; color: var(--text); }
.pstat span { font-size: 11px; color: var(--text-dim); }
.profile-points {
  display: flex; align-items: center; gap: 6px; justify-content: center;
  font-size: 12.5px; color: var(--text-dim); margin-bottom: 10px;
}
.profile-points .icon { color: var(--gold); }
.profile-empty {
  font-size: 13px; color: var(--text-dim); text-align: center;
  padding: 14px 0 16px;
}
/* Something that opens a card has to LOOK like it does, or nobody discovers it. */
[data-profile] { cursor: pointer; }
/* In a chat bubble the NAME is the target — the bubble itself is the message, and
   tapping a message must not open a profile — so the name carries the hint. */
.msg .name[data-profile] { text-decoration: underline dotted rgba(255,255,255,.22); text-underline-offset: 3px; }
/* A whole row or cell that is the target gets a press state instead of an underline:
   the row is already an obvious block, and underlining a name inside a tappable row
   suggests the name is the only part that works. */
.lb-row[data-profile], .vrow[data-profile], .player-cell.is-tappable { transition: background-color .12s, transform .12s; }
.lb-row[data-profile]:active, .vrow[data-profile]:active { background: var(--panel-2); }
.player-cell.is-tappable:active { transform: scale(.95); }

/* --- the settings panel -------------------------------------------------------------- */
.premium-card .premium-state {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  font-size: 12.5px; color: var(--text-dim); margin-bottom: 12px;
}
.premium-card .premium-state b { color: var(--gold); }
.premium-card .premium-state .sep { width: 3px; height: 3px; border-radius: 999px; background: var(--text-dim); }
.prem-group { margin-bottom: 14px; }
.prem-group:last-child { margin-bottom: 0; }
.prem-group > label {
  display: flex; align-items: center; justify-content: space-between;
  font-size: 11.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--text-dim); margin-bottom: 7px;
}
.prem-count { font-weight: 600; letter-spacing: 0; text-transform: none; }
/* Wraps rather than scrolls: six swatches at 44px fit two rows on the narrowest phone,
   and a horizontal scroller hides options people never discover. */
.prem-row { display: flex; flex-wrap: wrap; gap: 8px; }
.prem-pick {
  width: 44px; height: 44px; border-radius: var(--radius-sm);
  background: var(--panel-2); border: 1px solid var(--border-soft);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; padding: 0; transition: border-color .12s, transform .12s;
}
.prem-pick:active { transform: scale(.94); }
.prem-pick.is-on { border-color: var(--gold); box-shadow: 0 0 0 2px rgba(217,168,64,.3); }
.premium-card textarea {
  width: 100%; resize: none; font: inherit; font-size: 13.5px; line-height: 1.45;
  background: var(--panel-2); color: var(--text);
  border: 1px solid var(--border-soft); border-radius: var(--radius-sm);
  padding: 9px 11px; box-sizing: border-box;
}
.premium-card textarea:focus { outline: none; border-color: var(--accent); }

/* --- the pitch shown to free accounts ------------------------------------------------ */
.premium-pitch__lead { font-size: 13px; line-height: 1.5; color: var(--text-dim); margin-bottom: 12px; }
.btn.premium {
  background: linear-gradient(135deg, #f5d585, #d9a840 55%, #b8862a);
  color: #2a1e08; border-color: transparent; font-weight: 800;
}
.btn.premium .icon { color: #2a1e08; }

/* The premium popup's crown takes the premium colour, not the app's accent blue — a blue
   crown on a card selling a gold badge is selling the wrong thing. */
.popup-icon.is-gold { color: var(--gold); }

/* --- the premium picker sheet --------------------------------------------------------- */
/* The settings screen shows ONE swatch per choice; the catalogue (thirty icons, thirty
   frames) lives behind it. Sixty tap targets inline would bury the name field and the
   notification switch that most people actually came to this screen for. */
.prem-current {
  display: flex; align-items: center; gap: 10px; width: 100%;
  background: var(--panel-2); border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm); padding: 9px 11px; margin-bottom: 10px;
  color: var(--text); font: inherit; cursor: pointer; text-align: left;
  transition: border-color .12s;
}
.prem-current:active { border-color: var(--gold); }
.prem-current__label {
  font-size: 11.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--text-dim); flex: none; min-width: 58px;
}
.prem-current__value { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0; font-size: 13.5px; }
.prem-current__value > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prem-current > .icon:last-child { color: var(--text-dim); flex: none; }
/* A frame swatch is a real avatar with a real frame on it, wrapper and all, so what the
   row shows is exactly what the player will get. */
.prem-preview { display: inline-flex; flex: none; }
.prem-preview .avf, .prem-preview > img { width: 30px; height: 30px; }
.prem-preview > img { border-radius: 50%; background-color: var(--panel); }
.prem-preview .avf > img { background-color: var(--panel); }

.picker-card { width: 100%; max-width: 340px; padding: 0; overflow: hidden; text-align: left; }
.picker-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 14px 16px 10px; border-bottom: 1px solid var(--border-soft);
}
.picker-head h3 { margin: 0; font-size: 15px; font-weight: 800; }
/* Scrolls inside the sheet rather than growing it: thirty frames at 76px each is taller
   than any phone, and a sheet that runs off the screen hides its own close button. */
.picker-grid {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px;
  padding: 14px 16px 18px; max-height: 62vh; overflow-y: auto;
}
/* No names in the grid — the picture is the choice, and dropping the label is what
   lets each picture be big enough to judge. The name is still in title/aria-label, and
   the chosen one is spelled out on the settings row after picking. */
.picker-grid.is-frames { grid-template-columns: repeat(3, 1fr); gap: 12px; padding-top: 18px; }
.picker-cell {
  display: flex; align-items: center; justify-content: center;
  aspect-ratio: 1 / 1; padding: 0;
  background: var(--panel-2); border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm);
  cursor: pointer; color: var(--text); font: inherit;
  transition: border-color .12s, transform .12s;
}
.picker-cell:active { transform: scale(.94); }
.picker-cell.is-on { border-color: var(--gold); box-shadow: 0 0 0 2px rgba(217,168,64,.3); }
.picker-cell img.prem-badge.is-xl { width: 62%; height: 62%; margin: 0; }
/* Frame box at 58% of the cell; the artwork spills to ~85%, so it fills the tile
   without touching its edges. */
.picker-cell .prem-preview { width: 58%; aspect-ratio: 1 / 1; }
.picker-cell .prem-preview .avf,
.picker-cell .prem-preview > img { width: 100%; height: 100%; }

/* --- the profile card's scrolling body ------------------------------------------------ */
/* A premium card carries the full sides-and-roles breakdown, which is taller than a
   phone. The head and the close button stay put; only the stats scroll. */
.profile-scroll { max-height: 52vh; overflow-y: auto; margin: 0 -4px; padding: 0 4px; }
.profile-detail .section-title { margin-left: 0; margin-right: 0; }
.profile-detail .stat-tiles,
.profile-detail .stat-card,
.profile-detail .stat-streak { margin-left: 0; margin-right: 0; }


/* --- report a player ("Shikoyat qilish") ---------------------------------------------- */
.report-link {
  display: flex; align-items: center; justify-content: center; gap: 6px; width: 100%;
  margin: 10px 0 2px; padding: 8px; background: none; border: 0; cursor: pointer;
  font: inherit; font-size: 13px; font-weight: 700; color: #ff9aa2;
}
.report-link:disabled { color: var(--text-dim); cursor: default; }
/* The dark theme's soft pink (#ff9aa2) is almost invisible on the light card — players
   on the light theme reported the button as "gone". A proper red there. */
:root[data-theme="light"] .report-link:not(:disabled):not(.block-link) { color: #d92d3a; }
.report-form { display: flex; flex-direction: column; gap: 10px; text-align: left; }
.report-title { display: flex; align-items: center; gap: 8px; font-weight: 800; font-size: 16px; margin-bottom: 4px; }
.report-opt {
  display: flex; align-items: center; gap: 12px; padding: 12px 14px; cursor: pointer;
  background: var(--panel-2); border: 1px solid var(--border-soft); border-radius: var(--radius-sm);
  font-weight: 600;
}
.report-opt input { width: 20px; height: 20px; accent-color: var(--red); flex: none; }
.report-opt:has(input:checked) { border-color: rgba(239,68,68,.6); background: rgba(239,68,68,.1); }
.report-note { font-size: 12px; color: var(--text-dim); }
.report-warn { display: flex; gap: 8px; align-items: flex-start; font-size: 12px; line-height: 1.4; padding: 10px; border-radius: 10px; background: rgba(245,166,35,.12); border: 1px solid rgba(245,166,35,.4); color: var(--text); }
.report-warn .icon { flex: 0 0 auto; color: #f5a623; margin-top: 1px; }
.report-form .btn-row { display: flex; gap: 8px; }
.report-form .btn-row .btn { flex: 1; }

/* --- notification interval ----------------------------------------------------------- */
.setting-select {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 10px 2px 2px; margin-top: 8px; border-top: 1px solid var(--border-soft);
  font-size: 13.5px; font-weight: 600; color: var(--text);
}
.setting-select select {
  font: inherit; font-size: 13.5px; color: var(--text); background: var(--panel-2);
  border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 7px 10px;
}
.setting-select select:disabled { opacity: .45; }

/* --- premium: "Begonalarga taklif yuborish" ------------------------------------------ */
.btn.invite-gold {
  margin-top: 0; color: var(--gold); background: rgba(217,168,64,.08);
  border: 1.5px solid var(--gold); box-shadow: 0 0 0 3px rgba(217,168,64,.12), 0 6px 18px -8px rgba(217,168,64,.55);
  font-weight: 800;
}
.btn.invite-gold .icon { color: var(--gold); }
.btn.invite-gold:disabled { opacity: .55; box-shadow: none; }
.popup-card .btn.invite-gold { margin-top: 12px; background: linear-gradient(135deg, #f5d585, #d9a840 55%, #b8862a); color: #2a1e08; }
.popup-card .btn.invite-gold .icon { color: #2a1e08; }
.popup-title { font-weight: 800; font-size: 17px; margin: 4px 0 8px; }
.invite-explain { text-align: left; font-size: 13.5px; line-height: 1.5; color: var(--text-dim); }
.invite-explain p { margin: 0 0 8px; color: var(--text); }
.invite-explain ul { margin: 0 0 10px; padding-left: 18px; }
.invite-count { display: flex; align-items: center; gap: 6px; padding: 8px 10px; border-radius: var(--radius-sm);
  background: rgba(217,168,64,.1); color: var(--text); }

/* A banner row with nothing but the sound toggle takes NO height: the toggle is lifted
   into the header bar, to the right of the title, instead of sitting alone on a row of
   wasted space. */

/* Frame artwork must never paint over a sheet or popup opened on top of it: each
   framed avatar is its own stacking context, so the art's z-index stays inside it. */
.avf { isolation: isolate; }
.modal-overlay { z-index: 50; }

/* --- flip cards: role at game start, role of an eliminated player ------------------- */
.popup-card.is-flip { background: none; border: 0; box-shadow: none; padding: 0; width: min(300px, 84vw); overflow: visible; }
.flip3d { perspective: 1200px; width: 100%; aspect-ratio: 3 / 4; cursor: pointer; }
.flip3d__inner { position: relative; width: 100%; height: 100%; transform-style: preserve-3d;
  transition: transform .9s cubic-bezier(.6,.05,.3,1); }
.flip3d.is-turned .flip3d__inner { transform: rotateY(180deg); }
.flip3d__face { position: absolute; inset: 0; backface-visibility: hidden; -webkit-backface-visibility: hidden;
  border-radius: 22px; padding: 22px 18px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
  text-align: center; background: linear-gradient(180deg, var(--panel-2), var(--panel)); border: 2px solid var(--border);
  box-shadow: 0 24px 60px rgba(0,0,0,.6); }
.flip3d__back { transform: rotateY(180deg); }
.flip3d__back p { font-size: 13px; line-height: 1.45; color: var(--text-dim); margin: 6px 0 0; }
.flip3d__back.is-town { border-color: rgba(34,197,94,.7); box-shadow: 0 24px 60px rgba(0,0,0,.6), 0 0 40px rgba(34,197,94,.3);
  background: linear-gradient(180deg, #16301f, #11201a); }
.flip3d__back.is-town .popup-icon, .flip3d__back.is-town .popup-role { color: var(--green); }
.flip3d__back.is-mafia { border-color: rgba(239,68,68,.75); box-shadow: 0 24px 60px rgba(0,0,0,.6), 0 0 44px rgba(239,68,68,.4);
  background: linear-gradient(180deg, #3a1419, #221014); }
.flip3d__back.is-mafia .popup-icon, .flip3d__back.is-mafia .popup-role { color: #ff6b6b; }
.flip3d__front .flip-logo { width: 86%; max-width: 280px; height: auto; margin-bottom: 18px; filter: drop-shadow(0 6px 14px rgba(0,0,0,.6)); }
.flip-hint { font-family: var(--font-display); font-weight: 800; font-size: 17px; line-height: 1.35; }
.flip-tap { margin-top: 12px; display: inline-flex; align-items: center; gap: 6px; padding: 7px 14px; border-radius: 999px;
  background: rgba(79,124,255,.15); color: var(--accent); font-weight: 700; font-size: 13px; animation: flipTap 1.4s ease-in-out infinite; }
@keyframes flipTap { 50% { transform: scale(1.07); background: rgba(79,124,255,.28); } }
.flip3d:not(.is-turned) .flip3d__front { animation: flipIdle 2.4s ease-in-out infinite; }
@keyframes flipIdle { 50% { box-shadow: 0 24px 60px rgba(0,0,0,.6), 0 0 36px rgba(124,92,255,.45); } }
.is-elim .flip3d__front { border-color: rgba(239,68,68,.7); }
.flip3d__front .flip-face, .flip3d__front .avf { width: 110px; height: 110px; border-radius: 50%; object-fit: cover; }
.flip-name { font-family: var(--font-display); font-weight: 800; font-size: 22px; margin-top: 10px; }
.flip-sub { color: var(--text-dim); font-size: 13px; }

/* --- "... yozmoqda" ------------------------------------------------------------------ */
.typing-row { animation: typingIn .25s ease-out both; }
.typing-row .bubble { display: flex; flex-direction: column; }
.typing-dots { display: inline-flex; gap: 4px; padding: 5px 0 2px; }
.typing-dots i { width: 7px; height: 7px; border-radius: 50%; background: var(--text-dim); animation: typingBob 1s infinite; }
.typing-dots i:nth-child(2) { animation-delay: .15s; }
.typing-dots i:nth-child(3) { animation-delay: .3s; }
@keyframes typingBob { 0%, 60%, 100% { transform: translateY(0); opacity: .45; } 30% { transform: translateY(-4px); opacity: 1; } }
@keyframes typingIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* Sound toggle on a section title (screens with no banner) — no header, no empty row. */
.section-title.has-sound { padding-top: 8px; padding-bottom: 4px; }
.section-title.has-sound .sound-toggle { margin-left: auto; width: 32px; height: 32px; flex-shrink: 0; }
.section-title.has-sound .sound-toggle .icon { width: 16px; height: 16px; }
.banner-row.is-solo { justify-content: flex-end; margin-top: 8px; }
/* The corner crown is absolute: without this it escaped to the frame's corner. */
.summary-card { position: relative; }
/* Post-game roles: same 6-8 per row as the in-game grids. */
.summary-grid.is-compact.cols-5 { grid-template-columns: repeat(5, minmax(0,1fr)); }
.summary-grid.is-compact.cols-6 { grid-template-columns: repeat(6, minmax(0,1fr)); }
.summary-grid.is-compact.cols-7 { grid-template-columns: repeat(7, minmax(0,1fr)); gap: 4px; }
.summary-grid.is-compact.cols-8 { grid-template-columns: repeat(8, minmax(0,1fr)); gap: 4px; }
.summary-grid.is-compact .summary-card { min-width: 0; padding: 5px 2px; }
.summary-grid.is-compact .summary-card .pname { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.summary-grid.is-compact .summary-card .role-tag { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 7.5px; padding: 1px 3px; }
.summary-grid.is-compact .summary-card > img { width: 70%; height: auto; aspect-ratio: 1/1; margin: 0 auto; display: block; }
.summary-grid.is-compact .summary-card > .avf { width: 70%; height: auto; aspect-ratio: 1/1; margin: 0 auto; }
.postgame-roles { max-height: 40%; }
/* Voting: chat is read-only, so the grid gets the room — 4 per row, full names. */
.vote-grid-card { flex: 0 1 auto; min-height: 0; overflow-y: auto; }
.player-grid.cols-4.vote-grid { grid-template-columns: repeat(4, minmax(0,1fr)); gap: 8px; }
.vote-grid .player-cell { padding: 8px 4px; }
.vote-grid .player-cell .pname { font-size: 12px; }
.vote-grid .player-cell > .avatar-heat-wrap > img { width: 62%; }

.chat.vote-chat { flex: 1 1 0; min-height: 22%; }
.vote-grid .avatar-heat-wrap:has(.avf) { width: 66%; }
.vote-grid .avatar-heat-wrap .avf { width: 100%; }
/* Compact post-game strip: the frame already marks premium; the corner crown just crowds it. */
.summary-grid.is-compact .prem-cell { display: none; }

/* Day-discussion roster bar: who is left, by role, beside the sound toggle. */
.roster-bar { gap: 6px; flex-wrap: nowrap; overflow: hidden; }
.roster-bar .rchip {
  display: inline-flex; align-items: center; gap: 4px; flex-shrink: 0;
  padding: 4px 7px; border-radius: 999px;
  background: var(--panel-2); border: 1px solid var(--border-soft);
  font-size: 12px; font-weight: 800; color: var(--text);
}
.roster-bar .rchip .icon { width: 14px; height: 14px; color: var(--text-dim); }
.roster-bar .rchip.is-mafia { background: rgba(214, 58, 58, .14); border-color: rgba(214, 58, 58, .4); color: #ffb3b3; }
.roster-bar .rchip.is-mafia .icon { color: #ff8a8a; }
.roster-bar .rchip.is-out { opacity: .35; }
.roster-bar .sound-toggle { margin-left: auto; width: 32px; height: 32px; flex-shrink: 0; }
.roster-bar .sound-toggle .icon { width: 16px; height: 16px; }

/* ---------- reply to a message ---------- */
.msg { position: relative; }
.msg .reply-btn {
  width: 26px; height: 26px; border-radius: 50%; align-self: center; flex-shrink: 0;
  background: var(--panel-3); border: 1px solid var(--border); color: var(--text-dim);
  display: flex; align-items: center; justify-content: center; padding: 0;
}
.msg .reply-btn .icon { width: 14px; height: 14px; }
.msg-system + .msg .reply-btn, .msg .reply-btn:active { opacity: .85; }
/* Swipe-to-reply: the row itself is translated by the touch handler. */
.msg.is-swiping .reply-btn { background: var(--accent); border-color: var(--accent); color: #fff; }
/* The quoted message inside a bubble. */
.quote {
  display: block; border-left: 3px solid var(--accent); background: rgba(255,255,255,.06);
  border-radius: 6px; padding: 3px 7px; margin: 0 0 4px; font-size: 11.5px; line-height: 1.25; cursor: pointer;
}
.quote .qn { display: block; color: var(--accent); font-weight: 800; font-size: 11px; }
.quote .qt { display: block; color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.msg.is-mine .quote { border-left-color: #fff; background: rgba(255,255,255,.18); }
.msg.is-mine .quote .qn, .msg.is-mine .quote .qt { color: #fff; }
.msg.is-mafia .quote { border-left-color: #f3a1ab; }
/* The flash when you jump to a quoted message. */
@keyframes msg-flash { 0%, 100% { box-shadow: none; } 30% { box-shadow: 0 0 0 3px rgba(79, 124, 255, .55); } }
.msg.is-flash .bubble { animation: msg-flash 1.4s ease; border-radius: 10px; }
/* The quote strip above the input while composing a reply. */
.chat-composer-sheet { flex-direction: column; align-items: stretch; gap: 6px; }
.composer-row { display: flex; gap: 8px; align-items: center; }
.reply-strip {
  display: flex; align-items: center; gap: 8px; padding: 6px 8px;
  background: var(--panel-3); border-radius: 10px; border-left: 3px solid var(--accent); color: var(--text-dim);
}
.reply-strip[hidden] { display: none !important; }
.reply-strip__txt { flex: 1; min-width: 0; }
.reply-strip .rn { display: block; font-size: 11px; color: var(--accent); font-weight: 800; }
.reply-strip .rq { display: block; font-size: 12px; color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.reply-strip__x { background: none; border: 0; color: var(--text-dim); padding: 2px; }

/* ---------- referrals ---------- */
.referral-card { display: flex; flex-direction: column; gap: 12px; }
.referral-lead { font-size: 13px; line-height: 1.45; color: var(--text-dim); }
.referral-lead b { color: var(--text); }
.referral-link {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  background: var(--panel-3); border: 1px dashed var(--border); border-radius: var(--radius-sm);
  padding: 10px 12px; color: var(--text); font-size: 12.5px; cursor: pointer;
}
.referral-link:active { transform: scale(.99); }
.referral-link .icon { color: var(--accent); flex-shrink: 0; }
.referral-link__url { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.referral-link__hint { flex-shrink: 0; font-size: 11px; font-weight: 700; color: var(--accent); }
.referral-tiles { padding: 0; }
.referral-progress { height: 8px; border-radius: 999px; background: var(--panel-3); overflow: hidden; }
.referral-progress span { display: block; height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, var(--accent), var(--accent-2)); transition: width .4s ease; }
.referral-next { font-size: 12px; color: var(--text-dim); }
.referral-next b { color: var(--text); }
/* On someone else's card, under their game stats. */
.profile-refs { display: flex; align-items: center; justify-content: center; gap: 6px;
  margin-top: 10px; font-size: 12.5px; color: var(--text-dim); }
.profile-refs .icon { color: var(--accent); }
.profile-refs b { color: var(--text); }
.stat-tiles.referral-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.referral-tiles .stat-tile { padding: 10px 6px; }
.referral-tiles .stat-tile .v { font-size: 20px; }
.referral-tiles .stat-tile .l { font-size: 10.5px; }

/* ---- the two online majority votes ---- */
/* Reuses the table-mode button, so a vote looks the same wherever it appears. */
.consensus.rush-vote, .consensus.rematch-vote { padding: 0 14px 10px; }
.consensus.rematch-vote { padding-top: 4px; }
.next-game-row { margin-bottom: 4px; }
.next-game-note { text-align: center; font-size: 12px; color: var(--text-dim); margin: 0 14px 10px; }
.next-game-note b { color: var(--text); }

/* ===================================================================== ongoing games
   The block under the open rooms on the main menu. A live row is taller than a room row
   on purpose: it carries a phase, a count and the faces, and squeezing that onto one
   line made all three unreadable at a glance. */
.section-title__count { margin-left: auto; font-weight: 700; color: var(--text-dim); text-transform: none; letter-spacing: 0; }
.live-list { display: flex; flex-direction: column; gap: 8px; padding: 0 14px; }
.live-row {
  display: flex; align-items: center; gap: 10px;
  background: linear-gradient(180deg, var(--panel-2), var(--panel));
  border: 1px solid var(--border-soft); border-radius: var(--radius-sm);
  padding: 11px 12px; font-size: 13px;
  box-shadow: 0 6px 16px -12px var(--shadow);
}
.live-row__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.live-row__title { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.live-row__title .name { font-weight: 800; font-family: var(--font-display); }
.live-row .dim { color: var(--text-dim); font-size: 12px; }
.live-row .avatar-stack { margin-top: 2px; }
/* The dead, greyed rather than hidden: "9/12 tirik" next to twelve bright faces reads
   as a bug, and who is already out is part of what the row is telling you. */
.live-row .avatar-stack .is-dead { filter: grayscale(1); opacity: .45; }
.live-row.is-locked { opacity: .82; }
.live-row__lock {
  width: 38px; height: 38px; border-radius: 11px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--panel-3, rgba(255,255,255,.05)); color: var(--text-dim);
}
.live-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 8px; border-radius: 999px; font-size: 11px; font-weight: 800;
  border: 1px solid transparent;
}
.live-chip.is-day { color: #e0a93a; background: rgba(224,169,58,.13); border-color: rgba(224,169,58,.3); }
.live-chip.is-night { color: #7aa2f7; background: rgba(122,162,247,.13); border-color: rgba(122,162,247,.3); }
.live-chip.is-vote { color: #e26d6d; background: rgba(226,109,109,.13); border-color: rgba(226,109,109,.3); }
.live-chip.is-closed { color: var(--text-dim); background: rgba(150,150,150,.12); border-color: var(--border-soft); }

/* ===================================================================== spectating */
.spec-banner {
  display: flex; align-items: center; gap: 9px; margin: 8px 14px 0;
  padding: 10px 12px; border-radius: var(--radius-sm); font-size: 12.5px; line-height: 1.35;
  color: #c9b8ff; background: rgba(124,92,255,.12); border: 1px solid rgba(124,92,255,.3);
}
.spec-banner .icon { flex-shrink: 0; }
.rchip.spec-count { color: var(--text-dim); }
/* The spectator screen is a flex column: everything above keeps its natural height and
   the chat absorbs the rest, instead of the chat being a fixed slice of the viewport
   with dead space underneath it. */
.spec-chat { flex: 1; min-height: 0; display: flex; flex-direction: column;
  margin: 6px 4px 0; padding: 0; }
/* The section title above the log is redundant on this screen now that the bar names it —
   and it cost another row of chat. */
.spec-chat-title { display: none; }
.spec-chat .chat-messages { flex: 1; min-height: 0; overflow-y: auto; }
/* Leave, label, sound — one row, the same height as the sound button alone. */
.spec-bar { display: flex; align-items: center; gap: 10px; padding: 8px 10px 2px; flex-shrink: 0; }
.spec-strip {
  flex: 1; min-width: 0; display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 7px 13px; border-radius: 999px; font-size: 12.5px; font-weight: 700;
  color: #c9b8ff; background: rgba(124,92,255,.12); border: 1px solid rgba(124,92,255,.3);
}
.spec-strip .icon { flex-shrink: 0; }
.spec-x {
  flex: none; width: 42px; height: 42px; border-radius: 50%; padding: 0; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  background: var(--panel-2); border: 1px solid var(--border); color: var(--text-dim);
  transition: transform .12s ease, color .2s ease, border-color .2s ease;
}
.spec-x:active { transform: scale(.94); }
/* The chat now runs to the bottom of the frame, so this is all that keeps its rounded
   corners off the edge and clear of Android's gesture bar. */
.spec-pad { flex-shrink: 0; height: calc(10px + var(--gap-bottom)); }

/* ===================================================================== dead exit */
.dead-actions { padding: 10px 14px 16px; display: flex; flex-direction: column; gap: 7px; }
.dead-actions__note { font-size: 11.5px; color: var(--text-dim); line-height: 1.4; text-align: center; }

/* ===================================================================== history */
.hist-tiles { display: flex; gap: 7px; padding: 6px 14px 2px; }
.hist-tile {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 10px 4px; border-radius: 12px;
  background: linear-gradient(180deg, var(--panel-2), var(--panel)); border: 1px solid var(--border-soft);
}
.hist-tile b { font-size: 19px; font-weight: 800; font-family: var(--font-display); }
.hist-tile span { font-size: 10px; color: var(--text-dim); text-align: center; }
.hist-tile.is-win b { color: #58c98a; }
.hist-tile.is-loss b { color: #e26d6d; }
.hist-tile.is-rate b { color: #e0a93a; }
.hist-filters { display: flex; gap: 7px; padding: 8px 14px; }
.hist-chip {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 5px;
  height: 40px; border-radius: 12px; cursor: pointer; font-size: 12.5px; font-weight: 800;
  background: var(--panel); border: 1px solid var(--border-soft); color: var(--text-dim);
}
.hist-chip__n:empty { display: none; }
.hist-chip.is-active { color: #fff; border-color: transparent; background: var(--accent); }
.hist-group {
  padding: 12px 16px 5px; font-size: 11px; font-weight: 800; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text-dim);
}
.hist-row {
  display: flex; align-items: center; gap: 10px; text-decoration: none; color: inherit;
  background: linear-gradient(180deg, var(--panel-2), var(--panel));
  border: 1px solid var(--border-soft); border-radius: var(--radius-sm);
  padding: 10px 11px; font-size: 13px; position: relative; overflow: hidden;
}
/* The outcome as a colour down the edge: readable while scrolling past, where a word
   in the corner is not. */
.hist-row::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; }
.hist-row.is-win::before { background: #58c98a; }
.hist-row.is-loss::before { background: #e26d6d; }
.hist-row.is-void::before { background: var(--border-soft); }
.hist-row:active { transform: scale(.98); }
.hist-role-tile {
  width: 44px; height: 44px; flex-shrink: 0; border-radius: 12px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(124,92,255,.12); border: 1px solid rgba(124,92,255,.25); color: var(--accent);
}
.hist-role-tile.is-mafia { background: rgba(226,109,109,.12); border-color: rgba(226,109,109,.3); color: #e26d6d; }
.hist-row__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.hist-row__title { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.hist-row__meta { font-size: 11.5px; }
.hist-row .dim { color: var(--text-dim); }
.hist-row__right { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; flex-shrink: 0; }
.hist-row__right b { font-size: 13px; font-weight: 800; font-variant-numeric: tabular-nums; }
.hist-row__right i { font-size: 10.5px; font-style: normal; color: var(--text-dim); }
.hist-share {
  margin-top: 3px; width: 30px; height: 30px; border-radius: 9px; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  background: transparent; border: 1px solid var(--border-soft); color: var(--text-dim);
}
.hist-share:active { transform: scale(.92); }
.hist-outcome { font-size: 12.5px; font-weight: 800; }
.hist-outcome.is-win { color: #58c98a; }
.hist-outcome.is-loss { color: #e26d6d; }
.hist-outcome.is-void { color: var(--text-dim); }
.hist-mvp {
  font-size: 10px; font-weight: 800; padding: 2px 7px; border-radius: 999px;
  color: #e0a93a; background: rgba(224,169,58,.14); border: 1px solid rgba(224,169,58,.3);
}
.hist-row__title .role-tag {
  font-size: 10.5px; font-weight: 800; padding: 2px 7px; border-radius: 7px;
  background: var(--panel-3, rgba(255,255,255,.06)); color: var(--text-dim);
}
.hist-row__title .role-tag.mafia { background: var(--mafia); color: #fff; }
.hist-more { display: flex; justify-content: center; padding: 14px 0 22px; }

/* The main menu's two lists share one scroller (open rooms, then ongoing games). The
   room list keeps its own scrolling everywhere else, hence the scoped override. */
.menu-lists { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; padding-bottom: 16px; }
.menu-lists .room-list { flex: none; overflow: visible; }
.menu-lists .menu-empty { padding: 26px 14px; }

/* A read-only chat offers no reply: the button did nothing there but take up the row. */
.chat-card.is-readonly .reply-btn { display: none; }
/* The share arrow's place, kept by a lock, on a game whose replay is not yours to pass on. */
.hist-share.is-locked { opacity: .4; cursor: default; }

/* A night role that has spent its one action: the chosen face stays lit, the rest go
   quiet. Not hidden — the player still wants to see who was in the room. */
.player-cell.is-chosen { border-color: var(--green); box-shadow: 0 0 0 2px rgba(34,197,94,.35) inset; }
.player-cell.is-locked-out { opacity: .38; pointer-events: none; }

/* ===================================================================== ban screen
   A countdown rather than a closed door: "bloklandingiz" with no end reads as permanent,
   and the players it is aimed at open a second account instead of waiting it out. */
.ban-screen { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 16px; padding: 30px 26px; text-align: center; }
.ban-icon { width: 92px; height: 92px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  color: #e26d6d; background: rgba(226,109,109,.12); border: 2px solid rgba(226,109,109,.35); }
.ban-title { font-family: var(--font-display); font-weight: 800; font-size: 21px; }
.ban-clock { width: 100%; max-width: 320px; padding: 14px 18px; border-radius: var(--radius-sm);
  background: rgba(226,109,109,.1); border: 1px solid rgba(226,109,109,.3); }
.ban-clock__label { font-size: 11.5px; color: var(--text-dim); text-transform: uppercase; letter-spacing: .06em; }
.ban-clock__time { margin-top: 6px; font-family: var(--font-display); font-weight: 800; font-size: 32px;
  font-variant-numeric: tabular-nums; color: #ff9d9d; }
.ban-text { font-size: 13.5px; line-height: 1.5; color: var(--text-dim); max-width: 330px; }


/* A mafioso's own team in the night grid: visible, labelled, and not a target. Hiding
   them meant nobody knew who their partners were until someone spoke up in the chat. */
.player-cell.is-team { position: relative; pointer-events: none; border-color: var(--mafia); background: rgba(226,109,109,.09); }
.player-cell.is-team .pname { color: #ff9d9d; }
.team-badge {
  position: absolute; top: 4px; left: 50%; transform: translateX(-50%);
  display: inline-flex; align-items: center; gap: 3px; white-space: nowrap;
  padding: 1px 7px; border-radius: 999px; font-size: 9px; font-weight: 800;
  background: var(--mafia); color: #fff; box-shadow: 0 2px 8px -2px rgba(0,0,0,.6);
}
.team-badge .icon { width: 10px; height: 10px; }

/* "The bot cannot message you" — shown only to players Telegram has actually refused
   delivery for. A bot may not open a conversation, so this is the only way out. */
.botfix {
  /* Wraps rather than squeezing: at 390px the button and two lines of explanation side
     by side left the text in a four-word column. */
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px 10px;
  margin: 10px 14px 16px; padding: 12px 13px;
  border-radius: var(--radius-sm); font-size: 12.5px;
  color: #ffd9a1; background: rgba(224,169,58,.11); border: 1px solid rgba(224,169,58,.34);
}
.botfix .btn { margin-left: auto; }
.botfix .icon { flex-shrink: 0; color: var(--amber); }
.botfix__t { flex: 1 1 200px; min-width: 0; font-weight: 700; line-height: 1.35; }
.botfix__t span { display: block; margin-top: 2px; font-weight: 500; color: var(--text-dim); font-size: 11.5px; }

/* "Nothing" in the badge and frame pickers — the subscription without the decoration.
   A red circle with a slash, the sign everyone already reads as "off", so it cannot be
   mistaken for one more ornament to wear. */
.picker-cell.is-none { border-color: rgba(226,109,109,.4); background: rgba(226,109,109,.07); }
.picker-cell.is-none .none-mark {
  width: 58%; aspect-ratio: 1 / 1; border-radius: 50%; position: relative;
  border: 3px solid #e26d6d;
}
.picker-cell.is-none .none-mark::after {
  content: ""; position: absolute; left: 50%; top: 8%; width: 3px; height: 84%;
  background: #e26d6d; border-radius: 2px; transform: translateX(-50%) rotate(45deg);
}
.picker-cell.is-none.is-on { border-color: var(--gold); box-shadow: 0 0 0 2px rgba(217,168,64,.3); }
/* The settings row when nothing is chosen: the word, in the dim colour the rest of the
   screen uses for "unset", rather than an empty space that reads as a loading bug. */
.prem-none-row { color: var(--text-dim); }

/* A chat avatar opens the player's card, so it has to look like it can be pressed —
   with a mouse this is the target people aim at, which is why the card looked missing
   on desktop when only the name carried the handler. */
.msg img.is-tappable { cursor: pointer; }
.msg img.is-tappable:active { transform: scale(.92); }

/* Maintenance mode (src/Maintenance.php) — the admin's "no new games" switch.
   Card: shown on the menu and in a held lobby while the switch is on.
   Sheet: opened by api() when a button is refused; above every other modal. */
.maint-card {
  display: flex; align-items: center; gap: 10px;
  margin: 0 14px 12px; padding: 11px 12px;
  border-radius: var(--radius-sm);
  background: rgba(224,169,58,.11); border: 1px solid rgba(224,169,58,.34);
}
.maint-card__icon { color: var(--amber); display: flex; flex-shrink: 0; }
.maint-card__t { flex: 1 1 auto; min-width: 0; font-size: 12.5px; line-height: 1.35; color: var(--text); }
.maint-card__t b { display: block; font-weight: 800; }
.maint-card__t span { display: block; margin-top: 2px; color: var(--text-dim); font-size: 11.5px; }
.maint-card .btn { flex-shrink: 0; }
.modal-overlay.maint-sheet { z-index: 95; }
.maint-sheet .modal-sheet__body { text-align: center; padding-top: 22px; }
.maint-sheet__icon {
  width: 64px; height: 64px; margin: 0 auto 12px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: var(--amber); background: rgba(224,169,58,.13); border: 1px solid rgba(224,169,58,.34);
}
.maint-sheet h3 { margin: 0 0 8px; font-size: 18px; }
.maint-sheet p { margin: 0 0 16px; font-size: 14px; line-height: 1.5; color: var(--text-dim); }

/* Channel membership gate */
.gate-screen { flex: 1; min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 14px; padding: 30px 24px; text-align: center; }
.gate-art { position: relative; width: 132px; height: 132px; margin-bottom: 6px; }
.gate-art img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; box-shadow: 0 10px 40px rgba(56,96,236,.35); }
.gate-art__lock { position: absolute; right: -2px; bottom: -2px; width: 42px; height: 42px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; color: #fff; background: var(--accent);
  border: 3px solid var(--bg); }
.gate-title { font-family: var(--font-display); font-weight: 800; font-size: 22px; }
.gate-text { margin: 0; font-size: 14.5px; line-height: 1.55; color: var(--text-dim); max-width: 330px; }
.gate-actions { width: 100%; max-width: 330px; display: flex; flex-direction: column; gap: 10px; margin-top: 10px; }
.gate-status { min-height: 18px; font-size: 13px; color: #e26d6d; }

/* Swear-filter warnings (showCurseWarning): amber for the first, red for the last one and the mute. */
.curse-sheet.is-final .maint-sheet__icon { color: #e26d6d; background: rgba(226,109,109,.12); border-color: rgba(226,109,109,.4); }

/* Profile: Saqlash appears in the header row (outside the scroller) once anything changed. */
.profile-save { margin: -5px 0; animation: profileSaveIn .22s cubic-bezier(.32,.72,0,1); box-shadow: 0 6px 18px rgba(56,96,236,.35); }
@keyframes profileSaveIn { from { opacity: 0; transform: translateY(-6px) scale(.94); } to { opacity: 1; transform: none; } }
.profile-save[hidden] { display: none; }

/* ------------------------------------------------------------------ leaderboard podium
   Top three as cards: 2nd | 1st (raised) | 3rd. Medal colours drive the ring, the place
   pill and a faint wash of the card; the viewer's own card gets the accent border. */
.lb-ends { display: flex; align-items: center; justify-content: center; gap: 6px; margin: 10px 16px 0;
  font-size: 12px; font-weight: 600; color: var(--text-dim); }
.lb-podium { display: grid; grid-template-columns: 1fr 1.08fr 1fr; gap: 8px; align-items: end; margin: 14px 12px 6px; }
.lb-pod {
  --medal: #cd8a4e; --medal-ink: #3a2210;
  position: relative; min-width: 0; display: flex; flex-direction: column; align-items: center; text-align: center;
  padding: 14px 6px 12px; border-radius: 16px; cursor: pointer;
  background: linear-gradient(180deg, color-mix(in srgb, var(--medal) 20%, var(--panel)), var(--panel) 75%);
  border: 1px solid color-mix(in srgb, var(--medal) 45%, transparent);
  transition: transform .12s;
}
.lb-pod:active { transform: scale(.97); }
.lb-pod--gold   { --medal: #e7b73c; --medal-ink: #3b2a05; padding-top: 18px; padding-bottom: 20px;
  box-shadow: 0 10px 30px color-mix(in srgb, #e7b73c 22%, transparent); }
.lb-pod--silver { --medal: #b9c2cf; --medal-ink: #1f2530; }
.lb-pod--bronze { --medal: #cd8a4e; --medal-ink: #3a2210; }
.lb-pod.is-me { border: 2px solid var(--accent); }
.lb-pod__place { padding: 2px 9px; border-radius: 99px; font-size: 10.5px; font-weight: 800; letter-spacing: .02em;
  background: var(--medal); color: var(--medal-ink); }
.lb-pod__ava { margin-top: 9px; padding: 3px; border-radius: 50%; background: var(--medal); display: inline-flex; }
.lb-pod__ava img, .lb-pod__ava .avf { width: 58px; height: 58px; border-radius: 50%; object-fit: cover; display: block; }
.lb-pod--gold .lb-pod__ava img, .lb-pod--gold .lb-pod__ava .avf { width: 70px; height: 70px; }
.lb-pod__name { margin-top: 8px; max-width: 100%; font-weight: 800; font-size: 13px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lb-pod__you { font-size: 10.5px; font-weight: 700; color: var(--accent); margin-top: 1px; }
.lb-pod__sub { margin-top: 2px; font-size: 10.5px; color: var(--text-dim); white-space: nowrap; }
.lb-pod__score { margin-top: 8px; font-family: var(--font-display); font-weight: 800; font-size: 20px;
  color: var(--medal); font-variant-numeric: tabular-nums; line-height: 1; }
.lb-pod--gold .lb-pod__score { font-size: 24px; }
.lb-pod__unit { font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--text-dim); margin-top: 3px; }
/* Silver on a light card is near-white: blend the score toward the text colour. */
.lb-pod--silver .lb-pod__score { color: color-mix(in srgb, var(--medal) 55%, var(--text)); }
/* "siz" sits as a corner tag so the viewer's own card is not taller than the others. */
.lb-pod__you { position: absolute; top: 6px; right: 6px; margin: 0; padding: 1px 6px; border-radius: 99px;
  background: var(--accent); color: #fff; font-size: 9.5px; }
/* The crown over 1st place: sits on the card's top edge, tilted like it was dropped on. */
.lb-podium { margin-top: 26px; }
.lb-pod__crown { position: absolute; top: -22px; left: 50%; transform: translateX(-50%) rotate(-8deg);
  color: #e7b73c; filter: drop-shadow(0 3px 8px rgba(231,183,60,.55)); line-height: 0; }
.lb-pod__crown .icon { width: 34px; height: 34px; fill: #e7b73c; stroke: #a87a14; stroke-width: 1.2; }
.lb-prize { display: flex; align-items: center; justify-content: center; gap: 7px; margin: 8px 16px 0; padding: 8px 12px;
  border-radius: var(--radius-sm); font-size: 12.5px; color: var(--text);
  background: rgba(231,183,60,.12); border: 1px solid rgba(231,183,60,.35); }
.lb-prize .icon { color: #e7b73c; flex-shrink: 0; }

/* ------------------------------------------------------------------ friends (src/Friends.php) */
/* Create-room: "Do'stlar uchun ochiq" switch, only under Yopiq. */
.switch-row { display: flex; align-items: center; gap: 12px; margin-top: 10px; padding: 11px 12px; border-radius: var(--radius-sm);
  background: var(--panel-2, rgba(255,255,255,.04)); border: 1px solid var(--border-soft); cursor: pointer; }
.switch-row[hidden] { display: none; }
.switch-row__text { flex: 1; min-width: 0; font-size: 13px; } .switch-row__text b { display: block; font-size: 14px; }
.switch-row__text span { display: block; margin-top: 2px; color: var(--text-dim); font-size: 11.5px; line-height: 1.35; }
.switch-row input { position: absolute; opacity: 0; pointer-events: none; }
.switch { position: relative; flex: none; width: 46px; height: 28px; border-radius: 14px; background: var(--border); transition: background .18s; }
.switch i { position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.3); transition: transform .18s; }
.switch-row input:checked + .switch { background: var(--green); }
.switch-row input:checked + .switch i { transform: translateX(18px); }
/* Main menu */
.friend-tag { display: inline-flex; align-items: center; gap: 3px; padding: 1px 7px; margin-right: 4px; border-radius: 99px; font-size: 10.5px; font-weight: 800;
  color: var(--green); background: rgba(34,197,94,.12); }
.friend-tag .icon { width: 11px; height: 11px; }
.header-share-btn { position: relative; }
.dot-badge { position: absolute; top: -4px; right: -4px; min-width: 17px; height: 17px; padding: 0 4px; border-radius: 9px; background: #ef4444; color: #fff;
  font-size: 10px; font-weight: 800; display: flex; align-items: center; justify-content: center; border: 2px solid var(--bg); }
.dot-badge.is-inline { position: static; display: inline-flex; border: 0; margin-left: 4px; }
/* Profile entry */
.friends-entry { display: flex; align-items: center; gap: 10px; width: calc(100% - 32px); margin: 0 16px; padding: 13px 14px; text-align: left; font: inherit; color: var(--text); cursor: pointer; }
.friends-entry > span:first-child { flex: 1; } .friends-entry b { margin-left: 4px; color: var(--accent); }
.friends-entry__req { font-size: 11.5px; font-weight: 800; color: #fff; background: #ef4444; padding: 2px 8px; border-radius: 99px; }
/* Friends screen */
.friend-row { display: flex; align-items: center; gap: 11px; margin: 8px 16px 0; padding: 10px 12px; border-radius: var(--radius-md);
  background: var(--panel); border: 1px solid var(--border-soft); cursor: pointer; }
.friend-row img, .friend-row .avf { width: 42px; height: 42px; border-radius: 50%; object-fit: cover; flex: none; }
.friend-row__main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.friend-row__name { font-weight: 700; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.friend-row__sub { display: flex; align-items: center; gap: 5px; font-size: 11.5px; color: var(--text-dim); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.st-dot { width: 8px; height: 8px; border-radius: 50%; background: #5b6474; flex: none; }
.st-dot.is-online { background: var(--green); } .st-dot.is-lobby { background: var(--accent); } .st-dot.is-game { background: var(--amber); }
.friend-row__acts { display: flex; gap: 8px; }
.icon-btn { width: 36px; height: 36px; border-radius: 50%; border: 1px solid var(--border); background: var(--panel-2, transparent); display: flex; align-items: center; justify-content: center; color: var(--text); }
.icon-btn.is-yes { background: var(--green); border-color: transparent; color: #fff; }
.icon-btn.is-no { color: #e26d6d; }
.friend-yes { color: var(--green); border-color: rgba(34,197,94,.45); }
.profile-friend-row { margin: 12px 0 4px; }
.block-link { color: var(--text-dim); }
.lb-tab { padding: 9px 4px; font-size: 11.5px; }

/* Play Mafia Pro gift link card (openGiftFromStartParam in app.js). */
.gift-card { display: flex; flex-direction: column; align-items: center; gap: 10px; min-width: 250px; }
.gift-card__ic { font-size: 44px; line-height: 1; }
.gift-card__code { font-family: ui-monospace, Menlo, monospace; letter-spacing: .08em; color: var(--text-dim);
  background: var(--panel-2); border-radius: 10px; padding: 6px 12px; margin-bottom: 6px; }
.gift-card__msg { margin: 0 0 6px; color: var(--text-dim); }
.gift-card .btn { width: 100%; }

/* "↓ Yangi xabarlar" — shown when others wrote while this player was scrolled up in the chat. */
.chat-new-pill { position: absolute; left: 50%; bottom: 12px; transform: translateX(-50%); z-index: 5;
  border: 0; border-radius: 999px; padding: 8px 14px; font: inherit; font-size: 13px; font-weight: 700;
  color: #fff; background: var(--accent); box-shadow: 0 8px 20px rgba(0,0,0,.35); cursor: pointer; }

/* ============================================================================
   In-app notifications (src/Notice.php, noticeCardHtml in app.js). Mirrored in
   cpanelmafia/assets/admin.css for the live preview — keep the two in step.
   ============================================================================ */
#noticeLayer:empty { display: none; }
.nt-ov { position: fixed; inset: 0; z-index: 120; display: flex; align-items: center; justify-content: center;
  padding: calc(var(--safe-top) + var(--pill-band) + 16px) 20px calc(var(--safe-bottom, 0px) + 20px);
  background: rgba(0,0,0,.74); backdrop-filter: blur(3px); animation: ntIn .25s ease; }
@keyframes ntIn { from { opacity: 0; } to { opacity: 1; } }
.nt { width: 100%; max-width: 340px; max-height: 100%; overflow-y: auto; color: #eef1f6;
  background: linear-gradient(180deg, #1f2530, #171c25); border: 1px solid #232936; border-radius: 22px;
  box-shadow: 0 24px 60px rgba(0,0,0,.6); display: flex; flex-direction: column; text-align: left; }
.nt__body { padding: 18px 20px 6px; }
.nt__kick { display: flex; justify-content: space-between; font-size: 10.5px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: #8b93a1; margin-bottom: 9px; }
.nt__t { font-family: var(--font-display, inherit); font-weight: 800; font-size: 19px; line-height: 1.22; margin: 0 0 7px; }
.nt__txt { font-size: 14px; line-height: 1.45; color: #aeb6c5; white-space: pre-line; overflow-wrap: anywhere; }
.nt__link { display: flex; align-items: center; justify-content: center; gap: 6px; width: 100%; margin-top: 14px; height: 42px;
  border-radius: 12px; border: 1px solid #2c3341; background: transparent; color: #7aa2ff; font: inherit; font-weight: 700; font-size: 14px; cursor: pointer; }
.nt__link.is-promo { border: 0; color: #2a1e05; background: linear-gradient(180deg, #f3d98b, #d9a840); }
.nt__foot { display: flex; align-items: center; gap: 10px; padding: 12px 16px 16px; }
.nt__dots { display: flex; gap: 5px; flex: 1; }
.nt__dots i { width: 7px; height: 7px; border-radius: 50%; background: #2c3341; }
.nt__dots i.on { background: #4f7cff; width: 18px; border-radius: 99px; }
.nt__btn { display: inline-flex; align-items: center; gap: 8px; height: 44px; padding: 0 20px; border-radius: 12px; border: 0;
  font: inherit; font-weight: 800; font-size: 15px; color: #fff; background: linear-gradient(90deg, #4f7cff, #7c5cff); cursor: pointer; }
.nt__btn:disabled { background: #262d3a; color: #8b93a1; cursor: default; }
.nt__ring { width: 20px; height: 20px; }
.tpl-album .nt__img { width: 100%; aspect-ratio: 16/9; object-fit: cover; display: block; }
.tpl-portrait .nt__row { display: flex; }
.tpl-portrait .nt__img { width: 40%; aspect-ratio: 2/3; object-fit: cover; flex: none; display: block; }
.tpl-portrait .nt__body { padding: 16px 16px 4px; flex: 1; min-width: 0; }
.tpl-portrait .nt__t { font-size: 17px; } .tpl-portrait .nt__txt { font-size: 13px; }
.tpl-cover { position: relative; }
.tpl-cover .nt__img { width: 100%; aspect-ratio: 4/5; object-fit: cover; display: block; }
.tpl-cover .nt__over { position: absolute; left: 0; right: 0; top: 0; aspect-ratio: 4/5; display: flex; flex-direction: column;
  justify-content: flex-end; background: linear-gradient(180deg, rgba(10,12,18,0) 35%, rgba(10,12,18,.92) 88%); }
.tpl-cover .nt__txt { color: #dfe5f2; }
.tpl-cover .nt__foot { background: #141922; }
.tpl-square .nt__sq { display: flex; justify-content: center; padding: 22px 0 4px; }
.tpl-square .nt__img { width: 62%; aspect-ratio: 1; object-fit: cover; border-radius: 20px; box-shadow: 0 14px 30px rgba(0,0,0,.5); }
.tpl-square .nt__body, .tpl-text .nt__body, .tpl-warn .nt__body { text-align: center; }
.tpl-text .nt__emoji { font-size: 46px; line-height: 1; text-align: center; padding: 22px 0 0; }
.nt.is-warn { border-color: rgba(234,179,8,.55); box-shadow: 0 0 0 1px rgba(234,179,8,.25), 0 24px 60px rgba(0,0,0,.6); }
.nt__warnic { display: flex; justify-content: center; margin: 6px 0 10px; }
.nt__warnic svg { width: 74px; height: 74px; filter: drop-shadow(0 6px 18px rgba(234,179,8,.45)); }
.is-warn .nt__t { color: #fcd34d; }
.is-warn .nt__txt { color: #eef1f6; }
.is-warn .nt__btn:not(:disabled) { background: linear-gradient(90deg, #d99a06, #eab308); color: #1c1402; }

/* Maintenance lockout screen (reuses the ban screen) — amber instead of red */
.ban-icon--maint { background: rgba(234, 179, 8, .14) !important; color: #eab308 !important; border-color: rgba(234, 179, 8, .45) !important; box-shadow: none !important; }
#maintLock .btn { flex: none; margin-top: 18px; min-width: 200px; height: 48px; }

/* ================================================================ menu ad carousel
   (src/MenuAds.php). Same box as the logo lockup, so nothing below moves. */
.adc { position: relative; margin: 0 auto; width: 100%; max-width: 360px; z-index: 1; }
.adc__vp { position: relative; overflow: hidden; border-radius: 18px; height: 103px; touch-action: pan-y; user-select: none; }
.adc__track { display: flex; height: 100%; transition: transform .6s cubic-bezier(.3,.9,.3,1); }
.adc__slide { flex: 0 0 100%; height: 100%; position: relative; display: flex; align-items: center; justify-content: center; }
.adc__slide .menu-hero__lockup { height: 100%; margin: 0; }
.adc__slide[data-ad] { cursor: pointer; }
.adc__img { width: 100%; height: 100%; object-fit: cover; border-radius: 18px; display: block; box-shadow: 0 10px 26px -12px rgba(0,0,0,.8); pointer-events: none; }
.adc__tag { position: absolute; left: 8px; top: 8px; font: 700 10px/1 Inter, sans-serif; letter-spacing: .06em; padding: 4px 7px;
  border-radius: 99px; background: rgba(0,0,0,.55); color: #e5e7eb; backdrop-filter: blur(4px); }
.adc__dots { display: flex; justify-content: center; gap: 6px; margin-top: 9px; }
.adc__dots i { position: relative; width: 16px; height: 5px; border-radius: 99px; background: rgba(127,127,127,.22); overflow: hidden; }
.adc__dots i b { position: absolute; left: 0; top: 0; bottom: 0; width: 0; background: linear-gradient(90deg, #c9a86a, #f3d98b); }
.adc__dots i.done b { width: 100% !important; }
.adc__dots i:not(.on):not(.done) b { width: 0 !important; }

/* ================================================================ night slideshow
   (src/NightSlides.php) — idle night screen, online mode only. */
.night-idle.has-slides { justify-content: flex-start; padding-top: 4px; padding-bottom: 16px; }
.night-idle.has-slides .night-scene { height: 150px; }
.night-idle.has-slides .night-moon { width: 92px; height: 92px; margin: -46px 0 0 -46px; }
.night-idle.has-slides .night-wait { padding: 0 24px 14px; }
.night-idle.has-slides .night-wait .big { font-size: 18px; }
.ns { margin: 0 16px; position: relative; }
.ns__vp { position: relative; overflow: hidden; border-radius: 22px; height: 300px; touch-action: pan-y; user-select: none;
  background: linear-gradient(180deg, rgba(40,48,78,.55), rgba(20,24,40,.75)); border: 1px solid rgba(160,176,230,.16);
  box-shadow: 0 18px 40px -20px rgba(0,0,0,.8); }
.ns__track { display: flex; height: 100%; transition: transform .6s cubic-bezier(.3,.9,.3,1); }
.ns__s { flex: 0 0 100%; height: 100%; position: relative; display: flex; align-items: stretch; overflow: hidden; }
.ns__art { flex: 0 0 42%; position: relative; }
.ns__art img { position: absolute; left: 50%; bottom: 4px; height: 96%; width: auto; max-width: none; transform: translateX(-50%);
  filter: drop-shadow(0 10px 18px rgba(0,0,0,.6)); pointer-events: none; }
.ns__art::before { content: ""; position: absolute; left: 8%; right: 8%; bottom: 6%; height: 60%; border-radius: 50%;
  background: radial-gradient(closest-side, var(--glow, rgba(122,162,247,.35)), transparent); filter: blur(4px); }
.ns__txt { flex: 1; position: relative; z-index: 1; padding: 22px 18px 22px 4px; display: flex; flex-direction: column; justify-content: center; gap: 8px; }
.ns__kick { font: 800 10.5px/1 Inter, system-ui, sans-serif; letter-spacing: .14em; text-transform: uppercase; color: #9aa6c8; }
.ns__t { font: 800 21px/1.15 Manrope, Inter, sans-serif; color: #fff; }
.ns__d { font-size: 13.5px; line-height: 1.38; color: #cfd6e8; }
.ns__tip { font-size: 12.5px; line-height: 1.35; color: #f3d98b; background: rgba(217,168,64,.1); border: 1px solid rgba(217,168,64,.25);
  border-radius: 12px; padding: 8px 10px; margin-top: 2px; }
.ns__side { display: inline-flex; align-self: flex-start; font: 800 10.5px/1 Inter, sans-serif; padding: 5px 9px; border-radius: 99px; }
.ns__side.town { color: #9ec5ff; background: rgba(79,124,255,.16); }
.ns__side.mafia { color: #ff9d9d; background: rgba(226,109,109,.16); }
.ns__btn { align-self: flex-start; margin-top: 4px; border: 0; font: 800 13px Manrope, Inter, sans-serif; padding: 9px 16px; border-radius: 12px;
  color: #2a1e08; background: linear-gradient(135deg, #f5d585, #d9a840); }
.ns__ad { flex-direction: column; justify-content: center; align-items: stretch; padding: 16px; gap: 12px; }
.ns__ad img { width: 100%; border-radius: 16px; display: block; box-shadow: 0 10px 24px -12px rgba(0,0,0,.9); pointer-events: none; }
.ns__adimg { position: relative; }
.ns__ad .adtag { position: absolute; left: 8px; top: 8px; font: 700 10px/1 Inter, sans-serif; letter-spacing: .06em; padding: 4px 7px;
  border-radius: 99px; background: rgba(0,0,0,.55); color: #e5e7eb; }
.ns__ad .adtxt { font-size: 13px; color: #b9c2d8; text-align: center; line-height: 1.35; }
.ns__ad .adbtn { align-self: center; border: 0; font: 800 14px Manrope, Inter, sans-serif; padding: 11px 22px; border-radius: 14px; color: #fff;
  background: linear-gradient(90deg, #4f7cff, #7c5cff); }
/* Progress: option C — a thin line along the bottom of the card, gold on banners. */
.ns__line { position: absolute; left: 0; right: 0; bottom: 0; height: 3px; z-index: 3; }
.ns__line i { display: block; height: 100%; width: 0; background: linear-gradient(90deg, #7aa2f7, #b6a6ff); }
.ns__line.is-ad i { background: linear-gradient(90deg, #c9a86a, #f3d98b); }

/* ---- New roles: Mirshab (labels, ammo, fired) and Xufya (results) — 2026-10-15 ---- */
.player-cell .vtag{display:block;margin:3px auto 0;font:800 8.5px/1.1 Inter,sans-serif;padding:3px 5px;border-radius:99px;max-width:100%;white-space:normal;text-align:center}
.verdict-mafia .vtag{background:rgba(220,38,38,.35);color:#ffc1c8}
.verdict-clean .vtag{background:rgba(34,197,94,.25);color:#b8f5cf}
.vtag--x{background:rgba(150,100,255,.2);color:#d9c4ff}
.ammo{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:10px 16px 0;padding:10px 14px;border-radius:14px;
  background:rgba(14,44,56,.55);border:1px solid rgba(94,190,210,.25);font:700 13px Inter,sans-serif;color:#cfe9ef}
.ammo .b{display:flex;gap:6px}
.ammo .b i{width:10px;height:22px;border-radius:5px 5px 3px 3px;background:linear-gradient(#f3d98b,#b8862a)}
.ammo .b i.used{background:rgba(255,255,255,.12)}
.role-mirshab h3{color:#8fdcec}
.role-xufya h3{color:#c9a6ff}
.btn-row--stack{flex-direction:column}
.xres .investigation-row .verdict{color:#c9a6ff;background:rgba(150,100,255,.15);border-radius:99px;padding:3px 9px;font-weight:800}
.fired-card{position:relative;z-index:1;margin:14px 16px 0;padding:14px 16px;border-radius:16px;background:rgba(255,255,255,.04);border:1px dashed rgba(255,255,255,.18);color:#c5cad6;font-size:13.5px;line-height:1.45}
.fired-card b{color:#fff;display:block;font:800 16px Manrope,Inter,sans-serif;margin-bottom:4px}

/* End screen: "+ Do'stlashish" under each player (2026-10-01). */
.sum-friend{display:block;margin:5px auto 0;max-width:100%;padding:4px 7px;border-radius:99px;border:1px solid rgba(79,124,255,.35);
  background:rgba(79,124,255,.10);color:var(--blue,#4f7cff);font:700 10px/1.15 Inter,sans-serif;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer}
.sum-friend:disabled{opacity:.5}
.sum-friend.is-done{border-color:transparent;background:none;color:var(--text-dim,#8b95a7);cursor:default}

/* ---- Play Mafia Pro purchase sheet (2026-10-16) ---- */
.popup-card.pro-buy{text-align:left}
.pro-buy__head{text-align:center}
.pro-buy__head p{margin:0}
.pro-buy__title{font-size:22px}
.pro-buy__close,.pro-buy__pay{margin-top:14px}
.pro-buy__fine{font-size:12px;color:var(--text-dim);margin:8px 0 0;text-align:center}
.pro-back{background:none;border:0;color:var(--blue,#4f7cff);font:700 14px Inter,sans-serif;padding:0;margin-bottom:6px;cursor:pointer}
.pay-opts{display:flex;flex-direction:column;gap:10px;margin-top:14px}
.pay-opt{display:flex;align-items:center;gap:12px;width:100%;padding:14px;border-radius:14px;border:1px solid var(--border,rgba(127,127,127,.25));background:rgba(127,127,127,.06);text-align:left;font:inherit;color:inherit;cursor:pointer}
.pay-opt b{display:block;font-size:15px}.pay-opt small{color:var(--text-dim);font-size:12.5px}
.pay-opt .ic{width:40px;height:40px;border-radius:12px;display:grid;place-items:center;font-size:21px;flex:none}
.pay-opt .ic.star{background:linear-gradient(135deg,#ffd76a,#f0a820)}.pay-opt .ic.ic-card{background:linear-gradient(135deg,#6f8cff,#3d5bd9)}
.plans{display:grid;grid-template-columns:1fr 1fr;gap:12px 10px;margin-top:16px}
.plan{position:relative;display:flex;flex-direction:column;align-items:center;padding:14px 8px;border-radius:14px;border:1.5px solid var(--border,rgba(127,127,127,.25));background:rgba(127,127,127,.05);font:inherit;color:inherit;cursor:pointer}
.plan.sel{border-color:#e0a82e;background:rgba(224,168,46,.12)}
.plan .m{font-weight:800;font-size:15px}.plan .p{margin-top:6px;font-weight:800;font-size:18px;color:#d99a1c}
.plan .s{font-size:11.5px;color:var(--text-dim);margin-top:2px}
.plan .tag{position:absolute;top:-9px;left:50%;transform:translateX(-50%);background:#22c55e;color:#fff;font:800 10px Inter,sans-serif;padding:3px 8px;border-radius:99px;white-space:nowrap}
.cprices{margin-top:14px;border-radius:14px;border:1px solid var(--border,rgba(127,127,127,.25));overflow:hidden}
.cprices div{display:flex;justify-content:space-between;padding:12px 14px;font-size:14.5px}
.cprices div+div{border-top:1px solid var(--border,rgba(127,127,127,.18))}
.cprices b{font-weight:800}
.cnote{margin:14px 0;font-size:13.5px;line-height:1.5}
.cnote b{color:var(--blue,#4f7cff)}
.pro-extend{margin-top:10px}
.pro-crown{font-size:54px;line-height:1}
.pro-wait{width:34px;height:34px;margin:6px auto 12px;border-radius:50%;border:3px solid rgba(224,168,46,.25);border-top-color:#e0a82e;animation:proSpin .8s linear infinite}
@keyframes proSpin{to{transform:rotate(360deg)}}

/* ---- Voice rooms (2026-10-17): floating mic, speaking rings, long-press sheet ---- */
.vbar{position:fixed;left:12px;bottom:calc(84px + env(safe-area-inset-bottom,0px));z-index:40;display:flex;align-items:center;gap:8px;pointer-events:none}
.vbar > *{pointer-events:auto}
.vbar__who{max-width:52vw;padding:5px 10px;border-radius:99px;background:rgba(10,14,22,.78);color:#b8f5cf;font:700 12px Inter,sans-serif;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;backdrop-filter:blur(6px)}
.vbar__who:empty{display:none}
.vbar__btn{display:grid;place-items:center;border-radius:50%;border:0;cursor:pointer;color:#fff;-webkit-tap-highlight-color:transparent}
.vbar__spk{width:40px;height:40px;background:rgba(30,36,50,.9);border:1px solid rgba(255,255,255,.12)}
.vbar__spk.is-off{color:#ff8a8a}
.vbar__mic{width:56px;height:56px;background:linear-gradient(180deg,#ef5b5b,#c62f2f);box-shadow:0 8px 22px rgba(239,68,68,.35)}
.vbar__mic.is-on{background:linear-gradient(180deg,#2fd46a,#16a34a);box-shadow:0 8px 22px rgba(34,197,94,.4)}
.vbar__mic.is-on.is-mafia{background:linear-gradient(180deg,#d94a4a,#9f1f1f)}
.vbar__mic.is-locked{background:#2a3140;color:#8b95a7;box-shadow:none}
.vbar__mic.is-wait{opacity:.6}
.vbar__mic.is-bad{outline:2px dashed #ef4444;outline-offset:2px}
.vbar .icon-md{width:24px;height:24px}
img[data-vu].is-vspeak{box-shadow:0 0 0 3px #22c55e,0 0 14px rgba(34,197,94,.55);animation:vspeak 1s ease-in-out infinite}
@keyframes vspeak{50%{box-shadow:0 0 0 4px #22c55e,0 0 20px rgba(34,197,94,.35)}}
img[data-vu].is-vlocalmute{filter:grayscale(.8);opacity:.7}
.voice-tag{display:inline-block;padding:1px 7px;border-radius:99px;background:rgba(34,197,94,.15);color:#22c55e;font-size:11px;font-weight:800;vertical-align:1px}
.pro-chip{display:inline-block;font-style:normal;padding:1px 6px;border-radius:6px;background:linear-gradient(135deg,#f3d98b,#c9932a);color:#2a1e08;font-size:10px;font-weight:900;vertical-align:1px}
.vsheet{text-align:left}
.vsheet__who{display:flex;align-items:center;gap:12px;margin-bottom:10px}
.vsheet__who img{width:52px;height:52px;border-radius:50%;object-fit:cover}
.vsheet__who b{font-size:17px}
.vsheet__opt{display:flex;align-items:center;gap:12px;width:100%;padding:13px 12px;margin-top:8px;border-radius:12px;border:1px solid var(--border,rgba(127,127,127,.25));background:rgba(127,127,127,.06);color:inherit;font:700 15px Inter,sans-serif;text-align:left;cursor:pointer}
.vsheet__opt small{display:block;font-weight:500;font-size:12px;color:var(--text-dim);margin-top:1px}
.vsheet__opt.is-red{color:#ef5b5b;border-color:rgba(226,109,109,.35);background:rgba(226,109,109,.07)}
.vsheet__meter{margin:10px 2px 4px;font-size:13px}
.vsheet__bar{display:block;height:6px;border-radius:3px;background:rgba(127,127,127,.2);margin-top:6px;overflow:hidden}
.vsheet__bar i{display:block;height:100%;background:#ef4444}
.vsheet .btn{margin-top:12px}

.vbar__who{order:3}
.vgrid{display:grid;grid-template-columns:repeat(5,1fr);gap:6px 4px;margin:0 12px 8px;padding:8px 6px;border-radius:14px;background:var(--panel,rgba(20,24,34,.8));border:1px solid var(--border-soft,rgba(255,255,255,.06))}
.vgrid.is-dense{grid-template-columns:repeat(6,1fr)}
.vgrid__p{display:flex;flex-direction:column;align-items:center;gap:3px;min-width:0}
.vgrid__p img{width:40px;height:40px;border-radius:50%;object-fit:cover}
.vgrid__p .avf{width:40px;height:40px}
.vgrid__p span{font-size:10.5px;font-weight:700;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.vgrid__p.is-me span{color:var(--accent)}
.vgrid__p.is-spot img{box-shadow:0 0 0 3px #e7b73c}

/* ==== Voice room screens (voice-mockup 01–14, built 2026-10-17) ==== */
.vr{position:relative;flex:1;min-height:0;display:flex;flex-direction:column;overflow-y:auto;overflow-x:hidden}
.vr.is-night{background:radial-gradient(120% 70% at 50% 0%,#1a2140 0%,#080a12 60%)}
.vr-top{display:flex;align-items:center;gap:7px;padding:12px 14px 6px}
.vr-phase{font-family:var(--font-display);font-weight:800;font-size:15px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;flex:0 1 auto}
.vr-top .vr-chip,.vr-top .vr-timer{flex:none}
@media (max-width:400px){.vr-top{gap:5px;padding:12px 10px 6px}.vr-chip{padding:3px 6px;font-size:10.5px}}
.vr-top .sp{flex:1}
.vr-timer{display:inline-flex;align-items:center;gap:5px;padding:3px 8px;border-radius:99px;background:var(--panel);border:1px solid var(--border-soft);font-weight:700;font-size:12px;font-variant-numeric:tabular-nums;white-space:nowrap}
.vr-timer.is-danger{color:#ff8a8a;border-color:rgba(226,109,109,.45)}
.vr-chip{display:inline-flex;align-items:center;gap:5px;padding:3px 8px;border-radius:99px;font-size:11px;font-weight:700;background:var(--panel);border:1px solid var(--border-soft);color:var(--text-dim);white-space:nowrap}
.vr-chip .icon{width:14px;height:14px}
.vr-chip.is-mafia{color:#ff9a9a;border-color:rgba(226,109,109,.45);background:rgba(226,109,109,.1)}
.vr-chip.is-doc{color:#7ee2a8;border-color:rgba(34,197,94,.45);background:rgba(34,197,94,.1)}
.vr-chip.is-det{color:#9db8ff;border-color:rgba(79,124,255,.45);background:rgba(79,124,255,.1)}
.vr-ann{margin:2px 14px 10px;padding:9px 11px;border-radius:12px;display:flex;gap:10px;align-items:flex-start;background:var(--panel);border:1px solid var(--border-soft);font-size:13px;line-height:1.4}
.vr-ann .icon{width:20px;height:20px;flex:none;margin-top:1px}
.vr-ann b{font-weight:800}
.vr-ann.is-death{border-color:rgba(226,109,109,.4);background:linear-gradient(180deg,rgba(226,109,109,.13),rgba(226,109,109,.04))}
.vr-ann.is-death .icon{color:#ff8a8a}
.vr-ann.is-vote{border-color:rgba(234,179,8,.4);background:rgba(234,179,8,.08)}.vr-ann.is-vote .icon{color:var(--amber)}
.vr-ann.is-night{border-color:rgba(120,140,255,.3);background:rgba(40,50,110,.35)}.vr-ann.is-night .icon{color:#aab8ff}
.vr-ann.is-mafia{border-color:rgba(226,109,109,.45);background:rgba(90,20,24,.45)}.vr-ann.is-mafia .icon{color:#ff8a8a}
.vr-ann.is-doc{border-color:rgba(34,197,94,.4);background:rgba(20,70,40,.35)}.vr-ann.is-doc .icon{color:#7ee2a8}
.vr-ann.is-det{border-color:rgba(79,124,255,.45);background:rgba(30,45,110,.4)}.vr-ann.is-det .icon{color:#9db8ff}
.vr-moon{position:absolute;top:120px;right:-30px;width:150px;height:150px;border-radius:50%;box-shadow:-26px 12px 0 0 #f6e7b4;opacity:.1;pointer-events:none}
.vr-grid{flex:1;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:9px;padding:2px 14px 8px;align-content:center}
.vr-grid.is-dense{grid-template-columns:repeat(4,minmax(0,1fr));gap:7px}
.vt{position:relative;display:flex;flex-direction:column;align-items:center;text-align:center;padding:8px 4px 7px;border-radius:16px;background:var(--panel);border:1px solid var(--border-soft);transition:.2s;-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
.vt[data-vvote],.vt[data-vpick]{cursor:pointer}
.vt__ava{position:relative;width:62px;height:62px;border-radius:50%}
.vr-grid.is-dense .vt__ava{width:52px;height:52px}
.vt__ava > img,.vt__ava > .avf,.vt__ava > .avf > img:first-child{width:100%;height:100%;border-radius:50%;object-fit:cover;display:block}
.vt__name{margin-top:6px;font-weight:800;font-size:13px;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.vt__mic{position:absolute;right:-2px;bottom:-2px;width:22px;height:22px;border-radius:50%;display:flex;align-items:center;justify-content:center;background:var(--panel-2,#222938);border:2px solid var(--panel);color:var(--text-dim);z-index:2}
.vt__mic .icon{width:12px;height:12px}
.vt.is-muted .vt__mic{color:#ff8a8a;background:#3a1719}
.vt__tag{position:absolute;top:5px;left:7px;font-size:9.5px;font-weight:800;letter-spacing:.02em}
.vt__tag.is-me{color:var(--accent)}
.vt__tag.is-maf{color:#ff9a9a}
.vt.is-me{border-color:var(--accent)}
.vt.is-speaking{border-color:rgba(34,197,94,.7);box-shadow:0 0 0 1px rgba(34,197,94,.35),0 8px 26px rgba(34,197,94,.22)}
.vt.is-speaking .vt__ava::before{content:'';position:absolute;inset:-5px;border-radius:50%;border:3px solid #22c55e;animation:vtRing 1s ease-in-out infinite;z-index:1}
@keyframes vtRing{0%,100%{transform:scale(1);opacity:1}50%{transform:scale(1.06);opacity:.7}}
.vt__bars{display:none;gap:2px;align-items:flex-end;height:12px;margin-top:3px}
.vt.is-speaking .vt__bars{display:flex}
.vt__bars i{width:3px;border-radius:2px;background:#22c55e;animation:vtBar .7s ease-in-out infinite alternate}
.vt__bars i:nth-child(1){height:5px}.vt__bars i:nth-child(2){height:11px;animation-delay:.1s}.vt__bars i:nth-child(3){height:7px;animation-delay:.2s}.vt__bars i:nth-child(4){height:12px;animation-delay:.3s}.vt__bars i:nth-child(5){height:4px;animation-delay:.15s}
@keyframes vtBar{to{transform:scaleY(.4)}}
.vt__sub{font-size:10.5px;color:var(--text-dim);margin-top:3px}
.vt__sub.is-red{color:#ff8a8a}
.vt.is-dead{opacity:.45;filter:grayscale(1)}
.vt.is-dead .vt__ava::after{content:'';position:absolute;inset:0;border-radius:50%;background:rgba(0,0,0,.35)}
.vt__skull{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);color:#fff;z-index:2}
.vt__skull .icon{width:30px;height:30px}
.vt__votes{display:flex;flex-wrap:wrap;justify-content:center;gap:2px;margin-top:5px;max-width:100%}
.vt__votes img{width:18px;height:18px;border-radius:50%;object-fit:cover;border:1.5px solid var(--panel)}
.vt__votes .avf{width:18px;height:18px}.vt__votes .avf__art{display:none}
.vt__votes .is-mine img{outline:2px solid var(--accent);outline-offset:-1px}
.vt__count{position:absolute;top:6px;right:7px;min-width:20px;height:20px;padding:0 5px;border-radius:10px;font-size:11px;font-weight:800;display:flex;align-items:center;justify-content:center;background:var(--amber);color:#2a1e08;z-index:3}
.vt.is-target{border-color:rgba(234,179,8,.8);background:linear-gradient(180deg,rgba(234,179,8,.13),var(--panel))}
.vt.is-myvote{box-shadow:0 0 0 2px var(--accent)}
.vr.is-night .vt{background:rgba(20,24,40,.8);border-color:rgba(255,255,255,.06)}
.vt.is-asleep{opacity:.38}
.vt.is-ally{border-color:rgba(226,109,109,.55);background:rgba(70,18,22,.55)!important}
.vt.is-kill{border-color:#ef4444!important;box-shadow:0 0 0 2px rgba(239,68,68,.5),0 8px 26px rgba(239,68,68,.25)}
.vt.is-kill .vt__ava::after{content:'';position:absolute;inset:-4px;border-radius:50%;border:2px dashed #ef4444}
.vt__aim{position:absolute;top:5px;right:6px;color:#ef4444;z-index:3}
.vt.is-heal{border-color:#22c55e!important;box-shadow:0 0 0 2px rgba(34,197,94,.45)}
.vt__plus{position:absolute;top:3px;right:7px;color:#22c55e;font-weight:900;font-size:18px;line-height:1}
.vt.is-checked{border-color:#4f7cff!important;box-shadow:0 0 0 2px rgba(79,124,255,.45)}
.vt__verdict{margin-top:4px;padding:2px 7px;border-radius:99px;font-size:10px;font-weight:800}
.vt__verdict.is-clean{background:rgba(34,197,94,.18);color:#7ee2a8}
.vt__verdict.is-bad{background:rgba(239,68,68,.2);color:#ff9a9a}
.vt__verdict.is-x{background:rgba(150,100,255,.2);color:#d9c4ff}
.vt.is-spotlight{border-color:#e7b73c;box-shadow:0 0 0 2px rgba(231,183,60,.5),0 10px 34px rgba(231,183,60,.25);opacity:1;filter:none}
.vt.is-dim{opacity:.4}
.vr-bar{position:relative;display:flex;align-items:center;justify-content:center;gap:14px;padding:8px 16px 26px}
.vr-btn{width:52px;height:52px;border-radius:50%;border:1px solid var(--border);background:var(--panel);color:var(--text);display:flex;align-items:center;justify-content:center;cursor:pointer;-webkit-tap-highlight-color:transparent}
.vr-btn .icon-md{width:24px;height:24px}
.vr-mic{width:64px;height:64px;border:0;color:#fff;background:linear-gradient(180deg,#ef5b5b,#c62f2f);box-shadow:0 10px 28px rgba(239,68,68,.35)}
.vr-mic.is-on{background:linear-gradient(180deg,#2fd46a,#16a34a);box-shadow:0 10px 28px rgba(34,197,94,.35)}
.vr-mic.is-on.is-mafia{background:linear-gradient(180deg,#d94a4a,#9f1f1f)}
.vr-mic.is-locked{background:#2a3140;color:#8b95a7;box-shadow:none}
.vr-mic.is-wait{opacity:.6}
.vr-mic.is-bad{outline:2px dashed #ef4444;outline-offset:2px}
.vr-mic .icon-lg{width:28px;height:28px}
.vr-lab{position:absolute;left:0;right:0;bottom:6px;text-align:center;font-size:11px;color:var(--text-dim)}
.vr-cta-wrap{padding:0 14px calc(14px + var(--safe-bottom,0px))}
.vr-cta{width:100%;padding:14px;border-radius:14px;border:0;font-weight:800;font-size:15px;color:#fff;display:flex;align-items:center;justify-content:center;gap:8px;cursor:pointer}
.vr-cta:disabled{opacity:.55}
.vr-cta.is-red{background:linear-gradient(180deg,#e25555,#b52a2a)}
.vr-cta.is-green{background:linear-gradient(180deg,#2fd46a,#16a34a)}
.vr-cta.is-blue{background:linear-gradient(180deg,#4f7cff,#3558d8)}
.vr-cta.is-violet{background:linear-gradient(180deg,#8b5cf6,#6d3fd6)}
/* floating variant (summary debrief / reveal): just mic + sound, bottom left */
.vbar.vr-bar{position:fixed;left:12px;right:auto;bottom:calc(84px + env(safe-area-inset-bottom,0px));z-index:40;padding:0;gap:8px}
.vbar.vr-bar #vbarLeave,.vbar.vr-bar .vr-lab{display:none}
.vbar.vr-bar .vr-btn{width:40px;height:40px}
.vbar.vr-bar .vr-mic{width:54px;height:54px}

/* ---- Create room: Chat / Ovozli / Stol, access switches, new roles (2026-10-01) ---- */
.mode-toggle .visibility-opt .pro-chip{margin-left:2px}
#accessRows[hidden]{display:none}
.switch-row--sub{margin-left:14px;border-left:2px solid var(--accent)}
.switch-row__text b .icon{width:14px;height:14px;vertical-align:-2px}
.new-roles{margin-top:10px;padding:10px 12px;border-radius:var(--radius-sm);border:1px solid rgba(224,168,46,.45);background:rgba(224,168,46,.08)}
.new-roles[hidden]{display:none}
.new-roles__head{display:flex;align-items:center;gap:6px;font-weight:800;font-size:13px;color:#d99a1c;margin-bottom:4px}
.new-roles__head span{margin-left:auto;font-size:10.5px;font-weight:800;padding:2px 7px;border-radius:99px;background:linear-gradient(135deg,#f3d98b,#c9932a);color:#2a1e08}
.new-roles__row{display:flex;align-items:center;gap:10px;padding:7px 0}
.new-roles__row + .new-roles__row{border-top:1px solid var(--border-soft)}
.new-roles__row b{display:block;font-size:14px}
.new-roles__row small{display:block;font-size:12px;color:var(--text-dim);line-height:1.35}
.new-roles__ic{width:36px;height:36px;border-radius:10px;display:grid;place-items:center;flex:none}
.new-roles__ic.is-mirshab{background:rgba(94,190,210,.18);color:#8fdcec}
.new-roles__ic.is-xufya{background:rgba(150,100,255,.18);color:#c9a6ff}

/* ---- Voice lobby: voice only, no chat (2026-10-01) ---- */
.vr.is-lobby .vr-top{padding-top:10px}
.vr.is-lobby .vr-top .header-icon-btn,.vr.is-lobby .vr-top .header-share-btn{flex:none}
.vr-chip.is-voice{color:#7ee2a8;border-color:rgba(34,197,94,.45);background:rgba(34,197,94,.1)}
.vt__tag.is-host{color:#e7b73c}
.vt__tag.is-host .icon{width:13px;height:13px}
.vt.is-empty{background:transparent;border-style:dashed;opacity:.55}
.vt.is-empty .vt__ava{display:flex;align-items:center;justify-content:center;border:1.5px dashed var(--border);color:var(--text-dim)}
.vt.is-empty .vt__name{font-weight:600;color:var(--text-dim);font-size:12px}
.vl-actions{display:flex;flex-direction:column;gap:8px}
.vl-actions .consensus{margin:0}
.vl-invites{display:flex;gap:8px}
.vl-invites .btn{flex:1;font-size:13px;padding:10px 8px}

/* ---- Voice screens: header clear of Telegram's fullscreen pills (2026-10-01) ----
   Same rule as .topbar: the title sits alone, centred, and in fullscreen it is centred
   INSIDE the pill band with room left and right for Telegram's Back / menu pills. The
   chips live on the row below, so nothing of ours is ever under those buttons. */
.vr-head{padding:calc(var(--safe-top) + 10px) 16px 0;text-align:center;flex:none}
.vr-head .vr-phase{display:block;font-size:17px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
:root.has-pill-band .vr-head{padding:var(--safe-top) 96px 0;min-height:calc(var(--safe-top) + var(--pill-band));display:flex;align-items:center;justify-content:center;box-sizing:border-box}
:root.has-pill-band .vr-top{padding-top:8px}
.vr-top{padding-top:6px}
.vr .vr-top .pro-chip,.vr-cta .pro-chip{font-style:normal}
/* "3 ta bepul" on the voice join button: free voice games left, green instead of gold */
.pro-chip.is-free{background:linear-gradient(135deg,#7ee2a8,#2fae68);color:#062312}

/* Pro rooms in the menu lists (new roles) */
.pro-chip.room-pro{margin-right:5px;font-size:10.5px;padding:1.5px 6px;vertical-align:1px}

/* Leaving a game / removing a player (Ali, 2026-10-01) */
.quit-x { order: -1; flex: none; }
.quit-q { font-size: 15px; font-weight: 700; color: var(--text); margin-bottom: 6px; }
.quit-sub { font-size: 12.5px; color: var(--text-dim); margin-bottom: 14px; line-height: 1.4; }
.kick-title { font-size: 21px; margin: 4px 0 6px; }
.kick-btn { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; margin: 10px 0 2px; padding: 11px 14px;
  border-radius: 14px; border: 1.5px solid rgba(239,68,68,.45); background: rgba(239,68,68,.1); color: #f87171; font: 700 14px/1 var(--font, inherit); cursor: pointer; }
.kick-btn .kc { margin-left: auto; padding: 3px 9px; border-radius: 999px; background: rgba(239,68,68,.2); font-size: 12.5px; font-weight: 800; }
.kick-btn:disabled { cursor: default; opacity: .85; }
.kick-btn.is-done { border-style: dashed; }
.kick-bar { height: 5px; border-radius: 9px; background: rgba(127,127,127,.18); overflow: hidden; margin: 6px 2px 4px; }
.kick-bar i { display: block; height: 100%; background: linear-gradient(90deg, #f97316, #ef4444); transition: width .4s; }
.kick-note { color: var(--text-dim); font-size: 11.5px; margin: 6px 2px 4px; line-height: 1.35; }
:root[data-theme="light"] .kick-btn { color: #d92d3a; }
.ban-card { display: flex; gap: 12px; align-items: flex-start; margin: 10px 0 4px; padding: 13px 14px; border-radius: 16px;
  background: rgba(239,68,68,.1); border: 1.5px solid rgba(239,68,68,.4); color: var(--text); font-size: 13.5px; line-height: 1.4; }
.ban-card .ban-left { font-weight: 800; font-variant-numeric: tabular-nums; }
.quickjoin.is-banned, .btn.is-banned { filter: grayscale(.7); opacity: .55; }

/* =====================================================================================
   Desktop ("Kompyuter rejimi"): body.desk is set by deskCheck() for windows ≥ 1100px.
   The phone screen stays as it is in the middle column; #deskLeft / #deskRight are the
   side panels (renderDesk). Nothing here applies below 1100px — phones are untouched.
   ===================================================================================== */
body.desk { --dk-l: 300px; --dk-r: 340px; --dk-gap: 18px; }
body.desk #app {
  max-width: none; height: 100dvh; display: grid; gap: var(--dk-gap); padding: var(--dk-gap);
  grid-template-rows: minmax(0, 1fr); box-sizing: border-box;
  grid-template-columns: var(--dk-l) minmax(0, 1fr) var(--dk-r);
  background: radial-gradient(1200px 700px at 50% -10%, rgba(79,124,255,.10), transparent 60%);
}
body.desk.desk-empty #app { grid-template-columns: minmax(0, 860px); justify-content: center; }
body.desk.desk-empty .desk-side { display: none; }
body.desk .phone-frame {
  height: 100% !important; border-radius: 20px; border: 1px solid var(--border-soft);
  box-shadow: 0 30px 60px -40px rgba(0,0,0,.8); overflow: hidden;
}
body.desk.desk-compose .phone-frame { height: calc(100% - 70px) !important; }
.desk-side { display: none; }
body.desk .desk-side { display: flex; flex-direction: column; gap: var(--dk-gap); min-height: 0; overflow-y: auto; }
.dk-card { background: linear-gradient(180deg, var(--panel), color-mix(in srgb, var(--panel) 85%, #000)); border: 1px solid var(--border-soft);
  border-radius: 18px; padding: 14px; }
.dk-ct { display: flex; align-items: center; gap: 8px; color: var(--text-dim); font-size: 11.5px; font-weight: 800; letter-spacing: .08em;
  text-transform: uppercase; margin-bottom: 10px; }
.dk-ct b { margin-left: auto; color: var(--text); letter-spacing: 0; text-transform: none; font-size: 12.5px; }
.dk-dim { color: var(--text-dim); font-size: 13px; line-height: 1.45; }
.dk-row, .dk-lb, .dk-live { display: flex; align-items: center; gap: 10px; padding: 7px 8px; border-radius: 12px; cursor: pointer; border: 1px solid transparent; }
.dk-row:hover, .dk-lb:hover { background: var(--panel-2); }
.dk-ava { width: 36px; height: 36px; border-radius: 50%; object-fit: cover; flex: none; display: block; }
.desk-side .avf { width: 36px; height: 36px; flex: none; position: relative; display: block; }
.desk-side .avf .dk-ava { width: 100%; height: 100%; }
.desk-side .avf .avf__art { position: absolute; inset: -18%; width: 136%; height: 136%; }
.dk-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.dk-n { font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dk-sub { color: var(--text-dim); font-size: 12px; display: flex; align-items: center; gap: 5px; }
.dk-typing { color: #93c5fd; }
.dk-row.is-me { background: rgba(79,124,255,.10); border-color: rgba(79,124,255,.35); }
.dk-row.is-dead { opacity: .42; }
.dk-row.is-dead .dk-ava { filter: grayscale(1); }
.dk-row.is-voted { background: rgba(234,179,8,.10); border-color: rgba(234,179,8,.45); }
.dk-vc { min-width: 26px; height: 26px; padding: 0 7px; border-radius: 999px; background: #c2410c; color: #fff; font-weight: 900; font-size: 12.5px;
  display: flex; align-items: center; justify-content: center; }
.dk-prof { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 20px 16px; }
.dk-av { width: 92px; height: 92px; border-radius: 50%; object-fit: cover; display: block; }
.dk-prof .avf { width: 92px; height: 92px; position: relative; display: block; }
.dk-prof .avf .dk-av { width: 100%; height: 100%; }
.dk-prof .avf .avf__art { position: absolute; inset: -18%; width: 136%; height: 136%; }
.dk-name { font-family: var(--font-display); font-size: 20px; font-weight: 800; margin-top: 10px; display: flex; align-items: center; gap: 6px; }
.dk-bio { color: var(--text-dim); font-size: 12.5px; margin-top: 4px; }
.dk-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; width: 100%; margin-top: 14px; }
.dk-stats div { background: var(--panel-2); border-radius: 12px; padding: 9px 4px; }
.dk-stats b { display: block; font-family: var(--font-display); font-size: 19px; }
.dk-stats b.is-good { color: var(--green); }
.dk-stats span { color: var(--text-dim); font-size: 11px; }
.dk-full { margin-top: 12px; }
.dk-live { background: var(--panel-2); margin-bottom: 8px; cursor: default; }
.dk-lb .dk-n { flex: 1; }
.dk-lb b { font-family: var(--font-display); }
.dk-lb.is-me { background: rgba(79,124,255,.10); }
.dk-rank { width: 20px; font-family: var(--font-display); font-weight: 800; color: var(--text-dim); }
.dk-rank.is-top { color: var(--gold); }
.dk-set { display: flex; justify-content: space-between; gap: 10px; padding: 9px 2px; border-bottom: 1px solid var(--border-soft); font-size: 13.5px; }
.dk-set:last-child { border: 0; }
.dk-set span { color: var(--text-dim); }
.dk-role { padding: 0; overflow: hidden; border-color: rgba(79,124,255,.35); }
.dk-role.is-mafia { border-color: rgba(239,68,68,.45); }
.dk-art { height: 230px; display: flex; justify-content: center; align-items: flex-end;
  background: radial-gradient(circle at 50% 75%, rgba(79,124,255,.32), transparent 65%); }
.dk-role.is-mafia .dk-art { background: radial-gradient(circle at 50% 75%, rgba(226,109,109,.32), transparent 65%); }
.dk-art img { height: 220px; filter: drop-shadow(0 16px 22px rgba(0,0,0,.55)); }
.dk-ri { padding: 12px 16px 16px; }
.dk-ri .dk-ct { margin-bottom: 2px; }
.dk-rn { font-family: var(--font-display); font-size: 22px; font-weight: 800; }
.dk-role.is-mafia .dk-rn { color: #fca5a5; }
.dk-rd { color: var(--text-dim); font-size: 12.5px; line-height: 1.45; margin-top: 4px; }
.dk-tl { display: flex; flex-direction: column; gap: 9px; }
.dk-ev { display: flex; gap: 9px; font-size: 12.5px; line-height: 1.4; }
.dk-ev i { width: 8px; height: 8px; border-radius: 50%; background: #7aa2f7; margin-top: 5px; flex: none; }
/* the menu's room list uses the width: two columns of cards */
body.desk .room-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-content: start; }
/* the composer docks under the middle column instead of floating over the screen */
body.desk .chat-composer-overlay {
  top: auto; bottom: var(--dk-gap); height: auto; background: none; padding: 0;
  left: calc(var(--dk-gap) * 2 + var(--dk-l)); right: calc(var(--dk-gap) * 2 + var(--dk-r));
}
body.desk.desk-empty .chat-composer-overlay { left: 50%; right: auto; width: min(860px, calc(100% - 36px)); transform: translateX(-50%); }
body.desk .chat-composer-sheet { max-width: none; box-shadow: 0 10px 30px -14px rgba(0,0,0,.7); }
body.desk .chat-fab { display: none !important; }
body.desk #timerBar { left: calc(var(--dk-gap) * 2 + var(--dk-l)); right: calc(var(--dk-gap) * 2 + var(--dk-r)); width: auto; }

/* desktop: ongoing games live in the right panel, so not twice */
body.desk:not(.desk-empty) .live-block { display: none; }

/* 1100–1399px (a half-screen or small laptop window): narrower side panels */
@media (max-width: 1399px) {
  body.desk { --dk-l: 250px; --dk-r: 280px; --dk-gap: 14px; }
  body.desk .dk-art { height: 180px; }
  body.desk .dk-art img { height: 172px; }
  body.desk .room-list { grid-template-columns: minmax(0, 1fr); }
}
body.desk .vr-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 12px; padding: 4px 20px 10px; }
@media (max-width: 1399px) { body.desk .vr-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* desktop top bar + medium-width tabs */
.desk-top { display: none; }
body.desk #app { grid-template-rows: auto minmax(0, 1fr); }
body.desk .desk-top { grid-column: 1 / -1; display: flex; align-items: center; gap: 12px; height: 52px; padding: 0 6px; }
body.desk.desk-empty #app { grid-template-columns: minmax(0, 860px); }
.dk-brand-em { height: 40px; } .dk-brand-wm { height: 28px; }
.dk-where { margin-left: 14px; font-family: var(--font-display); font-weight: 800; font-size: 18px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dk-sp { flex: 1; }
.dk-keys { color: var(--text-dim); font-size: 12px; white-space: nowrap; }
.dk-keys kbd { font-family: inherit; font-size: 11px; font-weight: 600; line-height: 1; padding: 2px 6px; border-radius: 6px; border: 1px solid var(--border); background: var(--panel); color: var(--text); }
.dk-topbtn { display: inline-flex; align-items: center; gap: 8px; height: 38px; padding: 0 14px; border-radius: 11px; border: 1px solid var(--border);
  background: var(--panel); color: var(--text); font-weight: 700; cursor: pointer; }
.dk-tabs { display: flex; gap: 4px; padding: 4px; border-radius: 13px; background: var(--panel-2); }
.dk-tab { flex: 1; position: relative; padding: 8px 6px; border: 0; border-radius: 10px; background: transparent; color: var(--text-dim); font-weight: 700; font-size: 13px; cursor: pointer; }
.dk-tab.is-on { background: var(--panel); color: var(--text); }
.dk-dot { position: absolute; top: 6px; right: 8px; width: 7px; height: 7px; border-radius: 50%; background: #f59e0b; }

/* ---- desktop main menu, to the approved concept ---- */
.dm { display: flex; flex-direction: column; gap: 16px; height: 100%; padding: 18px; overflow-y: auto; }
.dm-ads .adc { margin: 0; border-radius: 16px; overflow: hidden; max-height: 190px; }
.dm-ads__lock { display: flex; align-items: center; justify-content: center; gap: 12px; height: 150px; }
.dm-ads__lock img:first-child { height: 120px; } .dm-ads__lock img:last-child { height: 78px; }
.dm-hero { display: flex; gap: 14px; align-items: stretch; }
.dm-qj { flex: 3; height: 64px; font-size: 18px; margin: 0; white-space: nowrap; }
.dm-qj kbd { margin-left: 10px; font-family: inherit; font-size: 11px; font-weight: 600; line-height: 1; padding: 3px 7px; border-radius: 6px; border: 1px solid rgba(255,255,255,.4); color: #e6ecff; }
.dm-new { flex: 1; height: 64px; padding: 0 22px; font-size: 18px; border-radius: 16px; white-space: nowrap; }
.dm-rooms { flex: 1; display: flex; flex-direction: column; gap: 14px; min-height: 0; padding: 16px; border-radius: 18px;
  background: var(--panel); border: 1px solid var(--border-soft); }
.dm-head { display: flex; align-items: center; gap: 8px; color: var(--text-dim); font-size: 12px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }
.dm-head b { color: var(--text); letter-spacing: 0; }
.dm-f { display: inline-flex; align-items: center; gap: 6px; padding: 7px 13px; border-radius: 999px; border: 1px solid var(--border); background: var(--panel-2);
  color: var(--text-dim); font-family: inherit; font-size: 13px; font-weight: 700; line-height: 1; text-transform: none; letter-spacing: 0; cursor: pointer; }
.dm-f.is-on { background: rgba(79,124,255,.15); border-color: var(--accent); color: var(--text); }
.dm-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; align-content: start; }
.dm-grid .menu-empty { grid-column: 1 / -1; }
.dm-card { display: flex; flex-direction: column; gap: 10px; padding: 14px; border-radius: 16px; text-decoration: none; color: var(--text);
  background: linear-gradient(180deg, var(--panel-2), var(--panel)); border: 1px solid var(--border-soft); transition: border-color .2s, transform .15s; }
.dm-card:hover { border-color: var(--accent); transform: translateY(-1px); }
.dm-card__t { display: flex; align-items: center; gap: 7px; min-width: 0; }
.dm-card__n { font-family: var(--font-display); font-weight: 800; font-size: 16px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dm-card__m { display: flex; align-items: center; gap: 8px; color: var(--text-dim); font-size: 12.5px; }
.dm-card__who { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dm-card__c { color: var(--green); }
.dm-card__bar { height: 6px; border-radius: 9px; background: var(--panel-3); overflow: hidden; }
.dm-card__bar i { display: block; height: 100%; background: linear-gradient(90deg, var(--green), #4ade80); }
.dm-card__go { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 13.5px; padding: 9px; border-radius: 11px; text-align: center; font-weight: 800; background: rgba(79,124,255,.14); color: var(--text); border: 1px solid rgba(79,124,255,.35); }
@media (max-width: 1399px) { .dm-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* top bar: tabs, theme, profile chip */
.dk-nav { display: flex; gap: 4px; margin-left: 16px; }
.dk-navb { position: relative; display: inline-flex; align-items: center; gap: 8px; padding: 9px 14px; border-radius: 10px; border: 0; background: transparent;
  color: var(--text-dim); font-family: inherit; font-size: 14px; font-weight: 600; line-height: 1; cursor: pointer; }
.dk-navb.is-on { background: var(--panel-2); color: var(--text); }
.dk-navb .dot-badge { position: static; margin-left: 2px; }
.dk-iconb { width: 38px; height: 38px; }
.dk-me { display: inline-flex; align-items: center; gap: 9px; padding: 4px 12px 4px 4px; border-radius: 999px; border: 1px solid var(--border);
  background: var(--panel); color: var(--text); font-family: inherit; font-size: 14px; font-weight: 600; line-height: 1; cursor: pointer; }
.dk-me .dk-ava, .dk-me .avf { width: 32px; height: 32px; }
.dk-topbtn { width: 38px; padding: 0; justify-content: center; }
/* profile card Pro button + new-roles card + rank column */
.dk-pro { margin-top: 12px; border: 0; background: linear-gradient(135deg, #f3d98b, #c9932a); color: #2a1e08; font-weight: 800; }
.dk-pro.is-have { cursor: pointer; }
.dk-promo { position: relative; overflow: hidden; border-radius: 18px; padding: 16px; min-height: 150px;
  background: linear-gradient(120deg, #2b2333, var(--panel)); border: 1px solid rgba(217,168,64,.35); }
.dk-promo b { font-family: var(--font-display); font-size: 18px; }
.dk-promo p { color: #cfc6b0; font-size: 12.5px; max-width: 175px; margin: 6px 0 12px; line-height: 1.45; }
.dk-promo img { position: absolute; right: -6px; bottom: -14px; height: 168px; }
:root[data-theme="light"] .dk-promo { background: linear-gradient(120deg, #fbf3df, var(--panel)); } :root[data-theme="light"] .dk-promo p { color: #6b5a33; }
.dk-rank { width: auto; min-width: 30px; text-align: right; font-size: 13px; flex: none; }
/* Telegram's own ⋮ / ✕ sit over the top-right corner in fullscreen: keep it free */
body.desk.dk-fs .desk-top { padding-right: 112px; }
body.desk .desk-top { margin-top: var(--dk-safe-top, 0px); }

/* desktop chat games / lobbies: players 2 per row in the left panel as tall cards (big
   avatar + frame, name under it, the phone's own tags), chat fills the middle.
   --dk-ava is set by deskFitGrid() so every row fits the panel without scrolling. */
body.desk .dk-pgrid, body.desk .dk-gridcard .player-grid { display: grid !important; grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
  gap: 8px !important; }
body.desk .dk-gridcard, body.desk .dk-card:has(.dk-pgrid) { padding: 12px; }
body.desk .dk-gridcard .player-cell, body.desk .dk-pgrid .dk-row {
  display: flex !important; flex-direction: column !important; align-items: center; justify-content: center; gap: 4px;
  padding: 10px 6px 8px; min-height: 0; border-radius: 14px; position: relative; text-align: center;
  background: var(--panel-2); border: 1px solid var(--border-soft); }
body.desk .dk-gridcard .avatar-heat-wrap, body.desk .dk-gridcard .player-cell > img, body.desk .dk-gridcard .player-cell > .avf,
body.desk .dk-pgrid .dk-ava, body.desk .dk-pgrid .avf {
  width: var(--dk-ava, 96px) !important; height: var(--dk-ava, 96px) !important; flex: none; }
body.desk .dk-gridcard .avatar-heat-wrap > img:not([class*=voter]), body.desk .dk-gridcard .avatar-heat-wrap > .avf { width: 100% !important; height: 100% !important; }
body.desk .dk-gridcard .pname, body.desk .dk-pgrid .dk-n { font-size: 13px; font-weight: 700; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin: 0; }
body.desk .dk-pgrid .dk-main { align-items: center; width: 100%; }
body.desk .dk-pgrid .dk-sub { justify-content: center; font-size: 11px; }
body.desk .dk-pgrid .dk-vc { position: absolute; top: 6px; right: 6px; }
body.desk.desk-grid .phone-frame { display: flex; flex-direction: column; }
body.desk.desk-grid .phone-frame .chat { flex: 1 1 auto !important; height: auto !important; max-height: none !important; min-height: 0; }
/* big monitors: wider side panels */
@media (min-width: 1700px) { body.desk { --dk-l: 360px; --dk-r: 380px; } }
/* no box-in-a-box: the phone's own grid card loses its frame inside the panel card,
   and the phone's tall cell padding / minimum height gives way to tight cards */
body.desk .dk-gridcard .card--grid, body.desk .dk-gridcard #dkGridSlot > .player-grid { padding: 0 !important; margin: 0 !important; border: 0 !important;
  background: none !important; box-shadow: none !important; }
body.desk .dk-gridcard .player-cell, body.desk .dk-pgrid .dk-row { padding: 6px 4px 5px !important; min-height: 0 !important; height: auto !important; gap: 3px !important; }
body.desk .dk-gridcard { padding: 10px; }
body.desk .dk-gridcard .dk-ct { margin-bottom: 8px; }
/* the status line under a name only when it says something ("yozmoqda…"); dead players are greyed anyway */
body.desk .dk-pgrid .dk-sub:not(:has(.dk-typing)) { display: none; }

/* ================================================================ main menu buttons (2026-10-03)
   Round buttons centred at a fixed size; "Yangi xona" is a gold [ + ] square beside quick join. */
.menu-iconrow { justify-content: center; gap: 12px; padding-top: 12px; }
.menu-iconrow .header-share-btn { flex: 0 0 44px; width: 44px; height: 44px; }
.menu-iconrow .header-share-btn .icon { width: 20px; height: 20px; }
@media (max-width: 350px) { .menu-iconrow { gap: 8px; } .menu-iconrow .header-share-btn { flex-basis: 40px; width: 40px; height: 40px; } }
.new-room-btn {
  flex: 0 0 58px; display: grid; place-items: center; border-radius: var(--radius-md); cursor: pointer; padding: 0;
  border: 1px solid rgba(217,168,64,.6); color: var(--gold);
  background: linear-gradient(160deg, rgba(217,168,64,.16), rgba(217,168,64,.03));
}
.new-room-btn .icon { width: 30px; height: 30px; stroke-width: 2.4; }
.new-room-btn:active { transform: scale(.95); }
.new-room-btn.is-banned { filter: grayscale(.7); opacity: .55; }

/* Desktop fullscreen (2026-10-03): the top bar moves up INTO Telegram's own button band
   (← on the left, ⋮ ✕ on the right) instead of sitting below an empty strip. */
body.desk.dk-fs .desk-top {
  margin-top: max(0px, calc(var(--dk-sa, 0px) + (var(--dk-band, 0px) - 52px) / 2 - var(--dk-gap)));
  padding-left: 52px; padding-right: 112px;
}
.dk-me.is-on { border-color: var(--accent); }

body.desk .desk-side { overflow-x: hidden; }
/* the vote grid has moved to the left panel (which carries this title) */
body.desk.desk-grid .phone-frame .vote-grid-title { display: none; }
/* Desktop end screen (2026-10-03): the phone's 5-across "roles" grid stretched to the
   middle column gave giant avatars, 9px names and a cut-off second row. Fixed-size cards
   instead, as many per row as fit, room for frame art, readable names and roles. */
body.desk .summary-grid.is-compact { grid-template-columns: repeat(auto-fill, minmax(124px, 1fr)) !important; gap: 8px !important; padding: 6px 14px 12px; }
body.desk .summary-grid.is-compact .summary-card { padding: 8px 6px 8px; }
body.desk .summary-grid.is-compact .summary-card > img,
body.desk .summary-grid.is-compact .summary-card > .avf { width: 60px !important; height: 60px !important; margin: 12px auto 12px; }
body.desk .summary-grid.is-compact .summary-card .pname { font-size: 13px; margin-top: 4px; font-weight: 700; position: relative; z-index: 3; }
body.desk .summary-grid.is-compact .summary-card .role-tag { font-size: 11px; padding: 2px 7px; }
body.desk .postgame-roles { max-height: 46%; }
body.desk .dk-gridcard .player-cell .pname, body.desk .dk-gridcard .pname { font-size: 13px !important; line-height: 1.25; }

/* Desktop player grid — avatars (2026-10-03, v2). One square box per player (--dk-ava).
   A Pro frame fills that box exactly (nothing spills out of it) and the photo sits in
   the frame's hole: 56% of the box, centred (the artwork's hole/canvas ratio is
   1.06/1.9). Players without a frame get the same 56% face, so every face in the grid
   is the same size and the rows line up. */
body.desk #deskLeft .avf { --av: 56%; --art: 100%; }
body.desk #deskLeft .avf > img:first-child {
  position: absolute !important; width: 56% !important; height: 56% !important; left: 22% !important; top: 22% !important; margin: 0 !important; }
body.desk #deskLeft .avf > img.avf__art {
  position: absolute !important; width: 100% !important; height: 100% !important; left: 0 !important; top: 0 !important; }
body.desk #deskLeft .dk-pgrid > .dk-row > img.dk-ava,
body.desk #deskLeft .player-cell > img:not([class*=voter]):not(.prem-cell__art),
body.desk #deskLeft .avatar-heat-wrap > img:not([class*=voter]) {
  width: calc(var(--dk-ava, 96px) * .56) !important; height: calc(var(--dk-ava, 96px) * .56) !important;
  margin: calc(var(--dk-ava, 96px) * .22) auto !important; }
body.desk #deskLeft .avatar-heat-wrap:not(:has(.avf)) { height: auto !important; }
/* the small Pro crown sits in the card's corner instead of taking a row of its own */
body.desk #deskLeft .player-cell > .prem-cell { position: absolute !important; top: 5px; right: 5px; margin: 0 !important; }
body.desk #deskLeft .player-cell > .avf, body.desk #deskLeft .player-cell > .avatar-heat-wrap { margin: 0 auto !important; }
body.desk #deskLeft .player-cell .pname { margin: 0 !important; }

/* ================================================================ desktop grid v3 (2026-10-03)
   vote badge inside the card · eliminated players stay (grey, ✕, role, reason) ·
   end-screen roles in the left panel · wide profile card */
body.desk #deskLeft .player-cell .vote-count { top: 5px; right: 5px; min-width: 20px; height: 20px; font-size: 11px; }
body.desk #deskLeft .player-cell, body.desk #deskLeft .summary-card { position: relative; }
body.desk #deskLeft .dk-dead { cursor: pointer; }
body.desk #deskLeft .dk-dead > .avf, body.desk #deskLeft .dk-dead > img, body.desk #deskLeft .dk-dead .pname,
body.desk #deskLeft .dk-pgrid .dk-row.is-dead > .avf, body.desk #deskLeft .dk-pgrid .dk-row.is-dead > img { filter: grayscale(1); opacity: .5; }
body.desk #deskLeft .dk-dead::after, body.desk #deskLeft .dk-pgrid .dk-row.is-dead::after {
  content: ""; position: absolute; left: 50%; top: calc(6px + var(--dk-ava, 96px) * .22); width: calc(var(--dk-ava, 96px) * .56); height: calc(var(--dk-ava, 96px) * .56);
  transform: translateX(-50%); pointer-events: none; opacity: .85;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2.6' stroke-linecap='round'%3E%3Cpath d='M7 7l10 10M17 7L7 17'/%3E%3C/svg%3E") center / 55% no-repeat; }
body.desk .dk-rtag { display: inline-block; margin-top: 2px; font-size: 10.5px; font-weight: 700; padding: 1px 7px; border-radius: 6px; background: var(--panel-3); color: var(--text-dim); max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
body.desk .dk-rtag.is-mafia { background: var(--mafia); color: #fff; }
body.desk .dk-why { font-size: 10px; color: var(--text-dim); margin-top: 1px; }
body.desk .dk-pgrid .dk-row.is-dead .dk-sub { display: flex !important; }
body.desk .dk-pgrid .dk-row.is-dead { opacity: 1; }

/* end screen: the revealed roles live in the left panel, the chat gets the middle */
body.desk #deskLeft .summary-grid { display: grid !important; grid-template-columns: repeat(2, minmax(0, 1fr)) !important; gap: 8px !important; padding: 0 !important; }
body.desk #deskLeft .summary-card { padding: 6px 4px 7px !important; border-radius: 13px; background: var(--panel-2); cursor: pointer; }
body.desk #deskLeft .summary-card > .avf, body.desk #deskLeft .summary-card > img { width: var(--dk-ava, 96px) !important; height: var(--dk-ava, 96px) !important; margin: 0 auto !important; display: block; }
body.desk #deskLeft .summary-card > img:not(.prem-cell__art) { width: calc(var(--dk-ava, 96px) * .56) !important; height: calc(var(--dk-ava, 96px) * .56) !important; margin: calc(var(--dk-ava, 96px) * .22) auto !important; }
body.desk #deskLeft .summary-card .pname { font-size: 13px !important; font-weight: 700; margin: 0 !important; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
body.desk #deskLeft .summary-card .role-tag { font-size: 10.5px !important; padding: 1px 7px !important; }
body.desk #deskLeft .summary-card > .prem-cell { position: absolute !important; top: 5px; right: 5px; margin: 0 !important; }
body.desk #deskLeft .summary-card .sum-friend, body.desk #deskLeft .summary-card button { display: none; }
body.desk #deskLeft .summary-card.is-dead > .avf, body.desk #deskLeft .summary-card.is-dead > img { filter: grayscale(1); opacity: .5; }
body.desk #deskLeft .summary-card.is-dead .pname { opacity: .6; }
body.desk .phone-frame .postgame-roles { display: none; }

/* wide profile card */
body.desk .popup-card.profile-card.is-desk { width: 760px; max-width: calc(100vw - 80px); padding: 0; text-align: left; position: relative; overflow: hidden; }
body.desk .profile-card.is-desk .pcd { display: grid; grid-template-columns: 250px minmax(0, 1fr); min-height: 340px; }
body.desk .profile-card.is-desk .pcd-l { padding: 28px 20px; text-align: center; border-right: 1px solid var(--border-soft);
  background: radial-gradient(260px 220px at 50% 32%, rgba(217,168,64,.16), transparent 70%); }
body.desk .profile-card.is-desk .pcd-l .profile-head { flex-direction: column; gap: 6px; margin: 0; }
body.desk .profile-card.is-desk .pcd-l .avf, body.desk .profile-card.is-desk .pcd-l .profile-face { width: 150px !important; height: 150px !important; }
body.desk .profile-card.is-desk .pcd-l .profile-name { font-size: 21px; justify-content: center; }
body.desk .profile-card.is-desk .pcd-l .profile-bio { margin-top: 12px; }
body.desk .profile-card.is-desk .pcd-r { padding: 24px 26px 20px; display: flex; flex-direction: column; gap: 12px; min-width: 0; max-height: calc(100vh - 120px); overflow-y: auto; }
body.desk .profile-card.is-desk .stat-tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); padding: 0; }
body.desk .profile-card.is-desk .profile-detail .stat-tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); }
body.desk .profile-card.is-desk .pcd-acts { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin-top: auto; }
body.desk .profile-card.is-desk .pcd-acts .btn-row { margin: 0; flex: 1 1 220px; }
body.desk .profile-card.is-desk .pcd-acts .report-link { margin: 0; }
body.desk .profile-card.is-desk .pcd-x { position: absolute; top: 12px; right: 12px; width: 34px; height: 34px; border-radius: 10px; border: 1px solid var(--border);
  background: var(--panel-3); color: var(--text-dim); display: grid; place-items: center; cursor: pointer; z-index: 2; padding: 0; }
body.desk .profile-card.is-desk .pcd-l .avf { --av: 56%; --art: 100%; width: 190px !important; height: 190px !important; margin: -10px auto -14px; }
body.desk .profile-card.is-desk .pcd-l .avf > img:first-child { width: 56% !important; height: 56% !important; left: 22% !important; top: 22% !important; }
body.desk .profile-card.is-desk .pcd-l .avf > img.avf__art { width: 100% !important; height: 100% !important; left: 0 !important; top: 0 !important; }
body.desk .profile-card.is-desk .pcd-l > .profile-head > img.profile-face { width: 120px !important; height: 120px !important; }
body.desk .profile-card.is-desk { overflow: visible; }
body.desk #deskLeft .summary-card.is-dead { opacity: 1; }

/* ================================================================ rules gallery (2026-10-03) */
.rl-tut { display: flex; align-items: center; gap: 12px; width: 100%; text-align: left; padding: 12px 14px; border-radius: 16px; cursor: pointer;
  border: 1px solid rgba(79,124,255,.45); background: linear-gradient(90deg, rgba(79,124,255,.18), rgba(124,92,255,.08)); color: var(--text); font: inherit; }
.rl-tut__play { width: 42px; height: 42px; border-radius: 50%; display: grid; place-items: center; flex: none; background: linear-gradient(135deg, var(--accent), var(--accent-2)); color: #fff; font-size: 16px; }
.rl-tut b { display: block; font-size: 15px; } .rl-tut small { color: var(--text-dim); font-size: 12px; }
.rl-tut__go { margin-left: auto; font-size: 12.5px; font-weight: 800; padding: 6px 12px; border-radius: 999px; background: var(--panel-3); }
.rl-seg { display: flex; gap: 4px; margin: 12px 0 10px; padding: 3px; border-radius: 12px; background: var(--panel-2); }
.rl-seg button { flex: 1; border: 0; background: none; color: var(--text-dim); font: 700 12.5px var(--font-display, inherit); padding: 8px 0; border-radius: 9px; cursor: pointer; }
.rl-seg button.is-on { background: var(--panel-3); color: var(--text); }
.rl-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 9px; }
.rl-card { position: relative; border-radius: 15px; overflow: hidden; padding: 0 0 8px; cursor: pointer; text-align: left; font: inherit; color: var(--text);
  border: 1px solid #27304a; background: linear-gradient(180deg, #1b2440, #141a28); }
.rl-card.is-mafia { border-color: #5a2230; background: linear-gradient(180deg, #3a1520, #1a0f14); }
.rl-card img { display: block; width: 100%; height: 130px; object-fit: cover; object-position: top; }
.rl-card b { display: block; padding: 6px 10px 0; font-size: 14px; }
.rl-card__n { position: absolute; top: 7px; right: 7px; z-index: 1; font-size: 10px; font-weight: 800; padding: 2px 7px; border-radius: 6px; background: rgba(0,0,0,.6); color: #fff; }
.rl-card:active { transform: scale(.98); }
.rl-det { position: relative; height: 270px; margin: -4px -4px 0; border-radius: 16px; overflow: hidden; background: linear-gradient(180deg, #1b2440, var(--panel)); }
.rl-det.is-mafia { background: linear-gradient(180deg, #3a1520, var(--panel)); }
.rl-det img { position: absolute; left: 50%; bottom: 0; transform: translateX(-50%); height: 262px; }
.rl-pill { position: absolute; top: 10px; display: flex; align-items: center; gap: 6px; padding: 5px 11px; border-radius: 999px; border: 0;
  background: rgba(0,0,0,.55); color: #fff; font: 700 12.5px inherit; cursor: pointer; }
.rl-back { left: 10px; } .rl-nav { right: 10px; cursor: default; }
.rl-nav button { border: 0; background: none; color: #fff; font-size: 18px; line-height: 1; padding: 0 4px; cursor: pointer; }
.rl-name { font: 900 26px var(--font-display, inherit); margin-top: 10px; }
.rl-side { font-size: 12px; font-weight: 800; letter-spacing: .06em; color: #9fb4ff; } .rl-det.is-mafia ~ .rl-side { color: #fca5a5; }
.rl-desc { font-size: 14px; line-height: 1.5; color: var(--text); margin: 10px 0; }
.rl-facts { display: flex; flex-wrap: wrap; gap: 6px; }
.rl-facts span { font-size: 12px; padding: 5px 10px; border-radius: 999px; background: var(--panel-2); border: 1px solid var(--border); }
.rl-tip { margin-top: 12px; padding: 11px 13px; border-radius: 12px; font-size: 13px; line-height: 1.5;
  background: rgba(79,124,255,.1); border: 1px solid rgba(79,124,255,.32); }
#tutFrame { position: fixed; inset: 0; width: 100%; height: 100%; border: 0; z-index: 9999; background: #0b0d12; }
body.desk .rl-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
body.desk .rl-card img { height: 170px; }

/* ================================================================ desktop menu tabs (2026-10-03) */
.dm-tabbed { display: flex; flex-direction: column; padding: 0 !important; background: none !important; border: 0 !important; }
.dm-tabs { display: flex; align-items: flex-end; gap: 3px; padding: 0 12px; }
.dm-tab { display: flex; align-items: center; gap: 8px; padding: 11px 20px; border-radius: 13px 13px 0 0; cursor: pointer; font: 700 14px var(--font-display, inherit);
  color: var(--text-dim); background: color-mix(in srgb, var(--panel) 60%, transparent); border: 1px solid var(--border-soft); border-bottom: 0; }
.dm-tab b { font-size: 11.5px; padding: 1px 7px; border-radius: 8px; background: var(--panel-3); color: var(--text); }
.dm-tab.is-on { color: var(--text); background: var(--panel); position: relative; top: 1px; z-index: 1; }
.dm-tab.is-on b { background: var(--accent); color: #fff; }
.dm-live { width: 8px; height: 8px; border-radius: 50%; background: var(--red); box-shadow: 0 0 0 3px rgba(239,68,68,.22); }
.dm-tabkeys { margin-left: auto; padding-bottom: 8px; color: var(--text-dim); font-size: 11px; }
.dm-tabbody { flex: 1; min-height: 0; overflow-y: auto; background: var(--panel); border: 1px solid var(--border-soft); border-radius: 16px; padding: 14px; }
.dm-tabbody .dm-head { margin-bottom: 12px; gap: 6px; }
.dm-card { position: relative; }
.dm-flag { position: absolute; top: -9px; right: 12px; z-index: 1; font-size: 10.5px; font-weight: 800; padding: 2px 8px; border-radius: 6px; background: var(--accent); color: #fff; }
.dm-flag.is-hot { background: #f59e0b; color: #1a1000; }
.dm-alive { display: flex; gap: 3px; } .dm-alive i { flex: 1; height: 6px; border-radius: 3px; background: var(--panel-3); } .dm-alive i.on { background: var(--green); }
.dm-phase { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--text-dim); }
.dm-ph { font-size: 11px; font-weight: 800; padding: 2px 8px; border-radius: 6px; color: #fff; background: var(--panel-3); }
.dm-ph.is-night { background: #3b2a7a; } .dm-ph.is-day { background: #7c5a12; } .dm-ph.is-vote { background: var(--mafia); }
.dm-watch { border: 0; cursor: pointer; font: inherit; }

/* ================================================================ desktop "Yangi xona" (2026-10-03) */
.cm-comp, .cm-counts { display: none; }
body.desk #createModal .modal-sheet { width: 900px; max-width: calc(100vw - 80px); display: grid; grid-template-columns: minmax(0, 1fr) 330px;
  grid-template-rows: auto 1fr; padding: 0; overflow: hidden; }
body.desk #createModal .modal-sheet__head { grid-column: 1; padding: 18px 22px 0; }
body.desk #createModal .modal-sheet__body { grid-column: 1; padding: 6px 22px 20px; max-height: calc(100vh - 160px); overflow-y: auto; }
body.desk #createModal .cm-comp { display: flex; flex-direction: column; grid-column: 2; grid-row: 1 / span 2; padding: 22px 20px;
  border-left: 1px solid var(--border-soft); background: radial-gradient(300px 260px at 50% 20%, rgba(124,92,255,.18), transparent 70%), var(--bg-2); }
body.desk #createModal .stepper { display: none; }
body.desk #createModal .cm-counts { display: flex; gap: 5px; margin-top: 6px; }
.cm-counts button { flex: 1; height: 36px; border-radius: 9px; border: 1px solid var(--border); background: var(--panel-2); color: var(--text); font: 700 13px inherit; cursor: pointer; }
.cm-counts button.is-on { background: var(--accent); border-color: var(--accent); color: #fff; }
.cm-counts button.is-pro { border-color: #7a5a1a; color: #f3d98b; }
.cm-t { font-size: 11px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--text-dim); }
.cm-cards { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; margin-top: 10px; }
.cm-card { position: relative; border-radius: 10px; overflow: hidden; background: #1b2440; text-align: center; font-size: 10.5px; padding-bottom: 4px; animation: cmIn .3s both; }
.cm-card.is-mafia { background: #3a1520; } .cm-card.is-new { box-shadow: 0 0 0 2px var(--gold); }
.cm-card img { display: block; width: 100%; height: 66px; object-fit: cover; object-position: top; }
.cm-card b { position: absolute; top: 3px; right: 4px; font-size: 10.5px; padding: 0 5px; border-radius: 5px; background: rgba(0,0,0,.6); color: #fff; }
.cm-card span { display: block; padding: 2px 2px 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@keyframes cmIn { from { opacity: 0; transform: scale(.9); } }
.cm-bal { height: 10px; border-radius: 5px; margin-top: 14px; background: var(--accent); overflow: hidden; } .cm-bal i { display: block; height: 100%; background: var(--red); transition: width .3s; }
.cm-bal-l { display: flex; justify-content: space-between; font-size: 11.5px; margin-top: 4px; } .cm-bal-l span:first-child { color: #fca5a5; } .cm-bal-l span:last-child { color: #9fb4ff; }
.cm-note { margin-top: auto; padding: 11px; border-radius: 12px; font-size: 12px; line-height: 1.55; background: var(--panel-2); border: 1px solid var(--border); }
body.desk #createModal { position: fixed; inset: 0; z-index: 60; display: grid; place-items: center; }
body.desk #createModal:not(.is-open) { display: none; }

/* voice grid: every tile the same width, whole grid centred, nothing spills off the side */
.vr-grid { width: 100%; box-sizing: border-box; justify-content: center; }
.vt { min-width: 0; }
body.desk .vt__ava { width: 86px; height: 86px; }
body.desk .vr-grid.is-dense .vt__ava { width: 72px; height: 72px; }
body.desk .vt__name { font-size: 14px; }
/* voters under a voice tile: ONE overlapping row, so a voted tile never grows taller than its row */
.vt__votes { flex-wrap: nowrap !important; gap: 0 !important; }
.vt__votes > span + span { margin-left: -5px; }

/* Rules = a full page now, not a bottom sheet (Ali, 2026-10-03) */
#infoModal { align-items: stretch; background: var(--bg); backdrop-filter: none; }
#infoModal .modal-sheet { width: 100%; max-width: none; height: 100%; max-height: none; border-radius: 0; border: 0; margin: 0;
  transform: none !important; display: flex; flex-direction: column; box-shadow: none; background: var(--bg); }
#infoModal .modal-sheet__head { flex: none; display: flex; align-items: center; gap: 12px; padding: calc(var(--safe-top, 0px) + var(--pill-band, 0px) + 12px) 16px 10px; }
#infoModal .modal-sheet__head h3 { margin: 0; flex: 1; }
#infoModal .modal-sheet__body { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: 4px 16px 24px; }
#rulesBody { max-width: 100%; overflow-x: hidden; }
.rl-facts span { max-width: 100%; white-space: normal; }
body.desk #infoModal .modal-sheet { border-radius: 20px; }
body.desk #infoModal .modal-sheet__body { padding: 4px 22px 24px; }
body.desk .rl-det { height: 360px; } body.desk .rl-det img { height: 350px; }
body.desk #infoModal .modal-sheet__head { padding: 14px 22px 10px; }
.voice-tag .icon{width:11px;height:11px;vertical-align:-1px}
/* tabs attached to the block (2026-10-03 v2): no gap, active tab merges into the panel,
   inactive ones sit darker behind it */
.dm-tabbed { gap: 0 !important; }
.dm-tabs { padding: 0 14px; margin: 0 0 -1px; position: relative; z-index: 2; gap: 4px; }
.dm-tab { background: color-mix(in srgb, var(--bg) 70%, var(--panel)); color: var(--text-dim); opacity: .8; border-color: var(--border-soft); top: 0 !important; }
.dm-tab:hover { opacity: 1; color: var(--text); }
.dm-tab.is-on { opacity: 1; background: var(--panel); color: var(--text); border-color: var(--border-soft); box-shadow: inset 0 3px 0 var(--accent);
  border-bottom: 1px solid var(--panel); padding-bottom: 12px; }
.dm-tabbody { border-top-left-radius: 0; position: relative; z-index: 1; }
.dm-live { background: var(--green); box-shadow: 0 0 0 3px rgba(34,197,94,.22); animation: dmPulse 2s ease-in-out infinite; }
@keyframes dmPulse { 50% { box-shadow: 0 0 0 5px rgba(34,197,94,.08); } }

/* Voice tiles never change size (Ali, 2026-10-03): the speaking ring is drawn inside the
   avatar box, the level bars replace the mic badge, and voters / verdicts live in a
   fixed one-line footer that every tile reserves. */
.vt { justify-content: flex-start; }
.vt__foot { height: 20px; margin-top: 4px; width: 100%; display: flex; justify-content: center; align-items: center; overflow: hidden; }
.vt__foot .vt__votes { margin-top: 0; }
.vt__foot .vt__verdict { margin-top: 0 !important; white-space: nowrap; }
.vt.is-speaking .vt__ava::before { inset: -3px !important; }
.vt__bars { position: absolute; display: flex !important; visibility: hidden; height: 14px; margin: 0; padding: 3px 4px; border-radius: 9px;
  background: var(--panel); border: 2px solid var(--panel); z-index: 3; }
.vt.is-speaking .vt__bars { visibility: visible; }
.vt.is-speaking .vt__mic { visibility: hidden; }
.vt__ava > .vt__bars { right: -6px; bottom: -4px; }
/* Pro frames stay INSIDE the voice tile (2026-10-03): the frame art fills the avatar box
   exactly, the photo sits in its hole; plain avatars get the same face size. */
.vt__ava { width: 76px; height: 76px; }
.vr-grid.is-dense .vt__ava { width: 64px; height: 64px; }
body.desk .vt__ava { width: 104px; height: 104px; }
body.desk .vr-grid.is-dense .vt__ava { width: 90px; height: 90px; }
.vt__ava > .avf { --av: 60%; --art: 100%; width: 100% !important; height: 100% !important; border-radius: 0 !important; }
.vt__ava > .avf > img:first-child { position: absolute !important; left: 20% !important; top: 20% !important; width: 60% !important; height: 60% !important; }
.vt__ava > .avf > img.avf__art { position: absolute !important; left: 0 !important; top: 0 !important; width: 100% !important; height: 100% !important; }
.vt__ava > img { position: absolute; left: 20%; top: 20%; width: 60% !important; height: 60% !important; }
.vt.is-speaking .vt__ava::before { inset: 17% !important; }
.vt__ava > .vt__mic { right: 12%; bottom: 12%; }
.vt__ava > .vt__bars { right: 4%; bottom: 8%; }
.vt { overflow: hidden; }
/* speaking bars: top-left corner of the tile (vote count is top-right) */
.vt > .vt__bars { top: 7px; left: 7px; right: auto !important; bottom: auto !important; padding: 2px 3px; height: 16px; background: rgba(34,197,94,.14); border-color: transparent; }
.vt.is-speaking .vt__mic { visibility: visible; }
.vt.is-speaking .vt__tag { left: 40px; }

/* voice screen never scrolls: the grid takes the remaining height, vtFit() sizes tiles */
.vr { overflow: hidden !important; }
.vr-grid { flex: 1 1 auto !important; min-height: 0; align-content: center; overflow: hidden; }
.vr-grid .vt__ava, .vr-grid.is-dense .vt__ava, body.desk .vr-grid .vt__ava { width: var(--vt-a, 76px) !important; height: var(--vt-a, 76px) !important; }
.vr-grid .vt { padding: 6px 4px 4px; min-height: 0; }
.vr-grid .vt__name { margin-top: 3px; line-height: 19px; }
.vr-grid { align-content: start !important; }
.vr-grid.is-compact .vt { padding: 3px 3px 2px; }
.vr-grid.is-compact .vt__name { font-size: 12px; line-height: 16px; margin-top: 2px; }
.vr-grid.is-compact .vt__foot { height: 18px; margin-top: 1px; }
.vr-grid.is-compact .vt__votes img, .vr-grid.is-compact .vt__votes .avf { width: 15px !important; height: 15px !important; }
.vt, .vt img { -webkit-touch-callout: none; -webkit-user-drag: none; touch-action: manipulation; }
.vt img { pointer-events: none; }
.vt.is-lmuted .vt__mic { color: #ff8a8a; background: #3a1719; }
.vt.is-lmuted .vt__ava { opacity: .55; }
.vt.is-lmuted::after { content: "🔇"; position: absolute; top: 6px; left: 8px; font-size: 13px; }
.vmenu { position: fixed; z-index: 10000; min-width: 220px; padding: 6px; border-radius: 14px; background: var(--panel-2); border: 1px solid var(--border);
  box-shadow: 0 18px 40px rgba(0,0,0,.55); animation: vmIn .14s ease-out; }
@keyframes vmIn { from { opacity: 0; transform: scale(.94); } }
.vmenu__who { font-size: 11.5px; font-weight: 800; color: var(--text-dim); padding: 4px 10px 6px; }
.vmenu button { display: flex; align-items: center; gap: 9px; width: 100%; border: 0; background: none; color: var(--text); font: 600 14px inherit;
  padding: 10px; border-radius: 10px; cursor: pointer; text-align: left; }
.vmenu button:hover, .vmenu button:active { background: var(--panel-3); }
.vmenu button.is-red { color: #ff8a8a; }

/* ---- profile card actions (2026-10-03) ---- */
.profile-card .pc-acts{margin-top:10px;display:flex;flex-direction:column;gap:8px}
.profile-card .pc-acts__row{display:flex;gap:8px}
.profile-card .pc-acts__row>.btn{flex:1;min-width:0;margin:0;padding:10px 8px;font-size:14px;white-space:nowrap;justify-content:center}
.profile-card .pc-acts .kick-btn{margin:0}
.profile-card .pc-acts .kick-bar{margin-top:-2px}
.pc-blk{background:rgba(229,72,77,.14)!important;color:#ff7b7f!important;border:1px solid rgba(229,72,77,.45)!important}
.pc-rep{background:rgba(255,255,255,.06)!important;color:inherit!important;border:1px solid rgba(255,255,255,.12)!important}
.pc-rep:disabled{opacity:.55}
.profile-card .profile-head{position:relative}
.pc-sq{margin-left:auto;flex:none;width:46px;height:46px;border-radius:13px;border:0;display:grid;place-items:center;
  background:var(--accent,#3a6df0);color:#fff;cursor:pointer;align-self:center}
.pc-sq.is-pend{background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.14);color:#c6cad8}
.pc-sq.is-ok{background:rgba(34,197,94,.15);border:1px solid rgba(34,197,94,.5);color:#4ade80}
.pc-sq.is-inc{background:#22c55e;animation:pcSqPulse 1.4s ease-in-out infinite}
@keyframes pcSqPulse{0%,100%{box-shadow:0 0 0 0 rgba(34,197,94,.55)}50%{box-shadow:0 0 0 7px rgba(34,197,94,0)}}
.profile-card.is-desk .pcd-l .profile-friend-row{margin-top:10px;width:100%}
.profile-card.is-desk .pcd-l .pc-acts{width:100%}
.profile-card.is-desk .pcd-l .profile-friend-row .btn{width:100%;white-space:nowrap;font-size:14px}
.profile-card .pc-acts .kick-btn{font-size:14px;font-weight:600;padding:10px 12px;white-space:nowrap;justify-content:center;gap:8px}
.profile-card .pc-acts .kick-btn .kc{margin-left:auto}
.profile-card .pc-acts .kick-bar{margin:0}
.profile-card.is-desk .pcd-l .profile-friend-row{display:flex;width:100%;align-self:stretch}
.profile-card.is-desk .pcd-l .profile-friend-row .btn{flex:1;max-width:none}
.profile-card.is-desk .pcd-l .profile-friend-row{padding:0;margin:10px 0 0}
/* 2026-10-03: names are never cut — they wrap (max 2 lines) and long ones get smaller. */
.profile-card .profile-id{flex:1 1 auto;min-width:0}
.profile-card .profile-name{white-space:normal;overflow:visible;text-overflow:clip;overflow-wrap:anywhere;word-break:break-word;line-height:1.2;align-items:flex-start;display:block}
.profile-card .profile-name .prem-badge,.profile-card .profile-name>svg,.profile-card .profile-name>span:first-child{vertical-align:-2px}
.profile-card .profile-name.is-long{font-size:16px}
.profile-card .profile-name.is-xlong{font-size:14px}

/* ---- voice-game announcements (2026-10-04) ---- */
#annLayer { position: fixed; inset: 0; z-index: 9000; pointer-events: none; }
.ann-ov { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; padding: 24px;
  background: rgba(3,4,10,.7); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  opacity: 0; transition: opacity .25s; pointer-events: auto; }
.ann-ov.is-open { opacity: 1; }
.ann-card { width: 100%; max-width: 300px; perspective: 1000px; transform: scale(.85); transition: transform .3s cubic-bezier(.2,.9,.3,1.2); }
.ann-ov.is-open .ann-card { transform: scale(1); }
.ann-inner { position: relative; display: grid; transform-style: preserve-3d; transition: transform .7s cubic-bezier(.4,.1,.2,1); }
.ann-card.is-turned .ann-inner { transform: rotateY(180deg); }
.ann-side { grid-area: 1 / 1; backface-visibility: hidden; -webkit-backface-visibility: hidden;
  border-radius: 22px; padding: 26px 18px 24px; text-align: center; display: flex; flex-direction: column; align-items: center;
  box-shadow: 0 24px 60px rgba(0,0,0,.6); }
.ann-front { background: linear-gradient(180deg,#2a1219,#150b10); border: 1px solid rgba(239,68,68,.55); }
.ann-back { transform: rotateY(180deg); background: linear-gradient(180deg,#121a30,#0c1222); border: 1px solid rgba(99,140,255,.5); }
.ann-facewrap { position: relative; width: 112px; height: 112px; margin-bottom: 16px; }
.ann-facewrap > img, .ann-facewrap > .avf { width: 112px; height: 112px; border-radius: 50%; object-fit: cover; display: block; }
.ann-front .ann-facewrap > img, .ann-front .ann-facewrap > .avf > img:first-child { filter: grayscale(.7) brightness(.8); }
.ann-facewrap img[data-vu].is-vspeak { box-shadow: none; animation: none; }
.ann-slash { position: absolute; left: -12%; width: 124%; top: calc(50% - 3px); height: 6px; border-radius: 3px; z-index: 3;
  background: linear-gradient(90deg,transparent,#ff3b3b 18%,#ff5a5a 82%,transparent); box-shadow: 0 0 14px #ff3b3b;
  transform: rotate(-38deg) scaleX(0); transform-origin: center; }
.ann-slash.is-b { transform: rotate(38deg) scaleX(0); transform-origin: center; }
.ann-ov.is-open .ann-slash { animation: annSlash .28s .35s ease-out forwards; }
.ann-ov.is-open .ann-slash.is-b { animation: annSlashB .28s .55s ease-out forwards; }
@keyframes annSlash { to { transform: rotate(-38deg) scaleX(1); } }
@keyframes annSlashB { to { transform: rotate(38deg) scaleX(1); } }
.ann-text { font-size: 17px; line-height: 1.4; color: #e8eaf2; }
.ann-text b { font-weight: 800; color: #fff; }
.ann-front .ann-text b { color: #ff8a8a; }
.ann-back .ann-text b { color: #9db8ff; }
.ann-mic { position: absolute; margin-top: 84px; margin-left: 84px; width: 34px; height: 34px; border-radius: 50%; background: #3a6df0;
  display: grid; place-items: center; font-size: 17px; box-shadow: 0 0 0 4px #0f1628; }
.ann-ban { position: absolute; left: 12px; right: 12px; max-width: 420px; margin: 0 auto;
  top: calc(var(--safe-top, 0px) + var(--pill-band, 0px) + 10px + var(--i, 0) * 58px);
  display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-radius: 14px;
  background: rgba(30,36,58,.97); border: 1px solid #39426a; box-shadow: 0 10px 30px rgba(0,0,0,.45);
  font-size: 14px; color: #dfe2ee; pointer-events: auto;
  transform: translateY(-140%); opacity: 0; transition: transform .3s ease, opacity .3s ease, top .3s ease; }
.ann-ban.is-open { transform: none; opacity: 1; }
.ann-ban b { color: #fff; }
.ann-ban > img, .ann-ban > .avf { width: 34px; height: 34px; border-radius: 50%; object-fit: cover; flex: none; }
.ann-ban { z-index: 2; }
body.desk .ann-card { max-width: 380px; }
body.desk .ann-facewrap, body.desk .ann-facewrap > img, body.desk .ann-facewrap > .avf { width: 140px; height: 140px; }
body.desk .ann-text { font-size: 20px; }
body.desk .ann-mic { margin-top: 106px; margin-left: 106px; }

/* ---- voice: Tun bo'ldi / Tong otdi cards, night countdown (2026-10-04) ---- */
.ann-phase { border: 1px solid rgba(255,255,255,.12); padding: 30px 18px 28px; }
.is-night .ann-phase { background: radial-gradient(120% 90% at 50% 0%, #2b2f6b 0%, #121534 55%, #0a0c1f 100%); border-color: rgba(129,140,248,.45); }
.is-day .ann-phase { background: radial-gradient(120% 90% at 50% 0%, #6b4a17 0%, #2b1f10 55%, #140f08 100%); border-color: rgba(251,191,36,.5); }
.ann-sun { font-size: 64px; line-height: 1; margin-bottom: 12px; animation: annRise .6s ease-out both; }
@keyframes annRise { from { transform: translateY(18px) scale(.8); opacity: 0; } to { transform: none; opacity: 1; } }
.ann-ptitle { font-family: var(--font-display, inherit); font-size: 30px; font-weight: 800; color: #fff; margin-bottom: 6px; }
.is-phase .ann-text { font-size: 15px; color: #c9cde0; }
body.desk .ann-ptitle { font-size: 36px; }

.vr.is-nightidle { display: flex; flex-direction: column; }
.vr-nightbig { text-align: center; margin: 18px 0 14px; position: relative; z-index: 1; }
.vr-nightbig .vr-bigtime { display: inline-flex; align-items: center; gap: 10px; font-size: 64px; font-weight: 800; line-height: 1;
  font-variant-numeric: tabular-nums; color: #e7e9ff; background: none; border: 0; padding: 0; text-shadow: 0 0 30px rgba(129,140,248,.45); }
.vr-nightbig .vr-bigtime .icon-sm { width: 26px; height: 26px; opacity: .6; }
.vr-bigsub { margin-top: 8px; font-size: 13px; color: #9aa0c8; letter-spacing: .02em; }
.vr.is-nightidle .ns { margin: 0 12px; position: relative; z-index: 1; }
body.desk .vr-nightbig .vr-bigtime { font-size: 88px; }
.ann-role { background: linear-gradient(180deg,#0f2219,#0b1611); border-color: rgba(34,197,94,.55); padding-top: 34px; padding-bottom: 32px; }
.ann-role.is-mafia { background: linear-gradient(180deg,#2a1219,#150b10); border-color: rgba(239,68,68,.6); }
.ann-role .popup-icon { width: 46px; height: 46px; color: #4ade80; margin-bottom: 14px; }
.ann-role.is-mafia .popup-icon { color: #ff6b6b; }
.ann-role .ann-text { font-size: 14px; color: #b9bdcc; letter-spacing: .08em; text-transform: uppercase; }
.ann-role .ann-text b { color: inherit; }
.ann-rolename { font-family: var(--font-display, inherit); font-size: 30px; font-weight: 800; margin-top: 6px; color: #4ade80; }
.ann-role.is-mafia .ann-rolename { color: #ff6b6b; }
.vr.is-nightidle .vr-bar { margin-top: auto; } /* same spot as during the day: the grid (flex:1) is what pushed it down there */

/* ---- weak-connection badge on voice tiles (2026-10-04) ---- */
.vt.is-weak::before {
  content: ""; position: absolute; top: 6px; right: 6px; width: 20px; height: 20px; border-radius: 6px; z-index: 4;
  background: #ef4444 url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2.6' stroke-linecap='round'%3E%3Cpath d='M4 20v-2M9 20v-5M14 20v-8M19 20V7' /%3E%3Cpath d='M3 3l18 18' stroke-width='2.2'/%3E%3C/svg%3E") center / 14px no-repeat;
  box-shadow: 0 0 0 2px rgba(10,12,20,.9); animation: vtWeak 1.6s ease-in-out infinite;
}
@keyframes vtWeak { 50% { opacity: .55; } }

/* fullscreen switch in the compact desktop layout (2026-10-04) */
.fs-float { position: fixed; top: 8px; right: 8px; z-index: 50; width: 32px; height: 32px; border-radius: 10px;
  display: grid; place-items: center; color: var(--text); background: rgba(30,36,58,.85); border: 1px solid var(--border-soft, rgba(255,255,255,.1));
  cursor: pointer; opacity: .75; transition: opacity .15s; }
.fs-float:hover { opacity: 1; }
/* PC grid: 4 per row (Ali, 2026-10-04) — 16 players = 4×4 */
body.desk .vr-grid { grid-template-columns: repeat(4, minmax(0, 1fr)) !important; }

/* ---------------------------------------------------------------- daily missions
   Kunlik vazifalar (src/Missions.php). Players without Pro only. Colours come from the
   theme variables so light and dark both work; orange = streak, violet = the chest. */
.ms-card{display:block;width:calc(100% - 24px);text-align:left;margin:12px 12px 4px;padding:12px 14px;border-radius:var(--radius-md);cursor:pointer;font:inherit;color:inherit;
  background:linear-gradient(135deg,color-mix(in srgb,#f59e0b 16%,var(--panel)),color-mix(in srgb,var(--accent-2) 10%,var(--panel)));
  border:1px solid color-mix(in srgb,#f59e0b 45%,var(--border-soft))}
.ms-card__top{display:flex;align-items:center;gap:8px;font:800 14.5px var(--font-display);color:var(--text)}
.ms-card__top .dot-badge{position:static;margin-left:2px}
.ms-card__top i{margin-left:auto;font-style:normal;font-size:12px;color:#c2620a}
.ms-bars{display:flex;gap:6px;margin-top:9px}
.ms-bars span{flex:1;height:7px;border-radius:9px;background:color-mix(in srgb,var(--text) 10%,transparent);overflow:hidden}
.ms-bars b{display:block;height:100%;border-radius:9px;background:linear-gradient(90deg,#f59e0b,#f97316)}
.ms-page{padding:14px 16px 0}
.ms-fire{color:#f97316}
.ms-streak__t .icon{align-self:center}
.ms-card__top .icon{flex:none}
.ms-day .r .icon{width:17px;height:17px;vertical-align:-3px}
.ms-day .r em{font-style:normal;font-size:11px;font-weight:800;margin-left:1px}
.ms-row__ic .icon{width:22px;height:22px}
.ms-row__ic.is-e{color:var(--green);background:color-mix(in srgb,var(--green) 13%,var(--panel-3))}
.ms-row__ic.is-m{color:var(--accent);background:color-mix(in srgb,var(--accent) 13%,var(--panel-3))}
.ms-row__ic.is-h{color:var(--red);background:color-mix(in srgb,var(--red) 12%,var(--panel-3))}
.ms-row.locked .ms-row__ic{color:var(--text-dim)}
.icon-xs{width:13px;height:13px;vertical-align:-2px}
.ms-row__m i{display:inline-flex;align-items:center;gap:3px}
.ms-swap{display:inline-flex;align-items:center;gap:4px}
.ms-daygift .icon,.ms-reroll .icon,.ms-passes .icon,.ms-reset .icon{color:var(--text-dim)}
.ms-chest .bx{color:var(--accent-2);width:46px;height:46px;border-radius:14px;display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,var(--accent-2) 14%,transparent);flex:none}
.ms-chest.is-open .bx{color:#b8862a;background:color-mix(in srgb,var(--gold) 22%,transparent)}
.ms-chest.is-sm .bx{width:34px;height:34px;border-radius:11px}
.ms-chest .k{display:inline-flex;align-items:center;gap:4px}
.ms-pop__c .big{color:var(--accent-2)} .ms-pop__c .big .icon{width:64px;height:64px}
.ms-prize b{color:var(--accent)} .ms-prize b .icon{width:42px;height:42px}
.ms-prize.is-pro b{color:#b8862a}
.ms-toast .e{color:#f97316;display:flex}
.ms-endstrip b{display:flex;align-items:center;justify-content:center;gap:4px}
.dk-ms .ic.is-e{color:var(--green)} .dk-ms .ic.is-m{color:var(--accent)} .dk-ms .ic.is-h{color:var(--red)}
.dk-ms.is-locked .ic{color:var(--text-dim)}
.dk-ms-card .dk-ct b{display:inline-flex;align-items:center;gap:3px}
.ms-streak{padding:13px;border-radius:var(--radius-md);margin-bottom:10px;
  background:linear-gradient(160deg,color-mix(in srgb,#f59e0b 14%,var(--panel)),var(--panel));border:1px solid color-mix(in srgb,#f59e0b 40%,var(--border-soft))}
.ms-streak__t{display:flex;align-items:baseline;gap:8px;font:800 15px var(--font-display);color:var(--text)}
.ms-streak__t b{font-size:24px;color:#ea7a0c}
.ms-streak__t small{margin-left:auto;color:var(--text-dim);font-size:12px;font-weight:600}
.ms-days{display:grid;grid-template-columns:repeat(7,1fr);gap:6px;margin-top:10px}
.ms-day{border-radius:12px;padding:6px 0 5px;text-align:center;background:color-mix(in srgb,var(--text) 6%,transparent);border:1.5px solid transparent;font-size:10.5px;color:var(--text-dim)}
.ms-day .r{display:block;font-size:15px;line-height:1.5;white-space:nowrap}
.ms-day b{display:block;font:800 10.5px var(--font-display)}
.ms-day.done{background:color-mix(in srgb,#f59e0b 16%,transparent);border-color:color-mix(in srgb,#f59e0b 40%,transparent);color:#b45309}
.ms-day.now{border-color:#f59e0b;box-shadow:0 0 0 3px color-mix(in srgb,#f59e0b 22%,transparent)}
.ms-day.big{background:linear-gradient(160deg,color-mix(in srgb,var(--gold) 30%,transparent),color-mix(in srgb,var(--accent-2) 18%,transparent));border-color:color-mix(in srgb,var(--gold) 55%,transparent)}
.ms-daygift{margin:0 0 12px;font-size:12.5px;color:var(--text-dim);text-align:center}
.ms-daygift b{color:var(--text)} .ms-daygift .is-good{color:var(--green)}
.ms-page .section-title{white-space:nowrap}
.ms-reset{margin-left:auto;display:inline-flex;align-items:center;gap:4px;text-transform:none;letter-spacing:0;font-weight:700}
.ms-row{display:flex;align-items:center;gap:12px;padding:12px 13px;margin-bottom:9px;border-radius:var(--radius-sm);
  background:linear-gradient(180deg,var(--panel-2),var(--panel));border:1px solid var(--border-soft)}
.ms-row__ic{width:44px;height:44px;border-radius:14px;flex:none;display:flex;align-items:center;justify-content:center;background:var(--panel-3)}
.ms-row__b{flex:1;min-width:0}
.ms-row__t{display:flex;align-items:center;flex-wrap:wrap;gap:7px;font:800 14.5px var(--font-display);color:var(--text)}
.ms-row__h{font-size:11.5px;color:var(--text-dim);margin-top:3px;line-height:1.35}
.ms-lvl{font:800 9.5px var(--font-display);padding:2px 7px;border-radius:99px;letter-spacing:.04em}
.ms-lvl.e{background:color-mix(in srgb,var(--green) 18%,transparent);color:var(--green)}
.ms-lvl.m{background:color-mix(in srgb,var(--accent) 16%,transparent);color:var(--accent)}
.ms-lvl.h{background:color-mix(in srgb,var(--red) 15%,transparent);color:var(--red)}
.ms-pb{height:7px;border-radius:9px;background:color-mix(in srgb,var(--text) 9%,transparent);margin-top:8px;overflow:hidden}
.ms-pb b{display:block;height:100%;border-radius:9px;background:linear-gradient(90deg,var(--accent),var(--accent-2))}
.ms-row__m{display:flex;justify-content:space-between;align-items:center;font-size:12px;color:var(--text-dim);margin-top:5px}
.ms-row__m i{font-style:normal;font-weight:800;color:#c2620a;white-space:nowrap}
.ms-swap{background:none;border:0;padding:0;color:var(--accent);font:700 12px inherit;cursor:pointer}
.ms-row.ok{border-color:color-mix(in srgb,var(--green) 50%,transparent)}
.ms-row.ok .ms-pb b{background:var(--green)}
.ms-row.got{opacity:.6}
.ms-row.locked{opacity:.6;border-style:dashed}
.ms-claim{flex:none;padding:10px 14px;border-radius:13px;background:var(--green);color:#fff;font:800 13.5px var(--font-display);border:0;cursor:pointer}
.ms-claim.is-sm{padding:6px 10px;font-size:12px}
.ms-claim:disabled{opacity:.5}
.ms-chk{flex:none;width:30px;height:30px;border-radius:50%;display:flex;align-items:center;justify-content:center;color:var(--green);background:color-mix(in srgb,var(--green) 15%,transparent)}
.ms-reroll{display:flex;align-items:center;justify-content:center;gap:6px;margin:6px 0 14px;color:var(--text-dim);font-size:12.5px}
.ms-reroll b{color:var(--accent)}
.ms-chest{display:flex;align-items:center;gap:12px;padding:13px;border-radius:var(--radius-md);cursor:default;
  background:linear-gradient(135deg,color-mix(in srgb,var(--accent-2) 18%,var(--panel)),var(--panel));border:1px solid color-mix(in srgb,var(--accent-2) 40%,var(--border-soft))}
.ms-chest.is-open{border-color:var(--gold);box-shadow:0 0 0 3px color-mix(in srgb,var(--gold) 20%,transparent)}

.ms-chest__b{flex:1;min-width:0}
.ms-chest b{font:800 14.5px var(--font-display);color:var(--text)} .ms-chest p{margin:2px 0 0;font-size:12.5px;color:var(--text-dim)}
.ms-chest .k{margin-left:auto;font:800 15px var(--font-display);color:var(--accent-2);white-space:nowrap}
.ms-chest.is-sm{margin-top:10px;padding:10px;cursor:pointer}
.ms-chest.is-sm b{font-size:13px} .ms-chest.is-sm .k{font-size:13px}
.ms-keybar{height:7px;border-radius:9px;background:color-mix(in srgb,var(--text) 9%,transparent);margin-top:7px;overflow:hidden}
.ms-keybar b{display:block;height:100%;background:linear-gradient(90deg,var(--accent),var(--accent-2))}
.ms-passes{margin-top:12px;text-align:center;font-size:12.5px;color:var(--text-dim)} .ms-passes b{color:var(--text)}
.ms-endstrip{display:flex;gap:8px;margin:10px 0 2px}
.ms-endstrip div{flex:1;padding:8px 6px;border-radius:14px;text-align:center;background:var(--panel);border:1px solid var(--border-soft);font-size:11.5px;color:var(--text-dim)}
.ms-endstrip b{display:block;font:800 17px var(--font-display);color:var(--text)}
.ms-toast{position:fixed;left:50%;top:calc(var(--safe-top, 0px) + 14px);transform:translateX(-50%);z-index:120;width:min(360px,calc(100% - 24px));display:flex;gap:12px;align-items:center;cursor:pointer;
  padding:12px 14px;border-radius:18px;background:var(--panel);border:1.5px solid #f59e0b;box-shadow:var(--shadow);animation:msDrop .45s cubic-bezier(.2,.9,.3,1.2) both;transition:opacity .4s,transform .4s}
.ms-toast.is-out{opacity:0;transform:translate(-50%,-30px)}
@keyframes msDrop{from{opacity:0;transform:translate(-50%,-40px)}to{opacity:1;transform:translate(-50%,0)}}
.ms-toast b{display:block;font:800 14.5px var(--font-display);color:var(--text)} .ms-toast span{font-size:12.5px;color:var(--text-dim)}
.ms-pop{position:fixed;inset:0;z-index:130;display:flex;align-items:center;justify-content:center;background:rgba(10,12,20,.55);backdrop-filter:blur(4px)}
.ms-pop__c{width:min(320px,88vw);border-radius:26px;padding:24px 18px 18px;text-align:center;background:var(--panel);border:1.5px solid color-mix(in srgb,var(--gold) 60%,transparent);box-shadow:var(--shadow);animation:msPop .6s cubic-bezier(.2,.9,.3,1.4) both}
@keyframes msPop{from{opacity:0;transform:scale(.6)}to{opacity:1;transform:none}}
.ms-pop__c .big{line-height:1}
.ms-pop__c h3{font:800 21px var(--font-display);margin:10px 0 4px;color:var(--text)}
.ms-pop__c p{margin:0;color:var(--text-dim);font-size:13.5px}
.ms-prize{margin:16px 0;padding:16px;border-radius:16px;background:var(--panel-2)}
.ms-prize b{display:block;line-height:1.2}
.ms-prize span{font:800 18px var(--font-display);color:var(--text)}
.ms-ok{width:100%;height:48px;border:0;border-radius:15px;background:linear-gradient(135deg,#f5d585,#e0a63e 55%,#b8862a);color:#2a1e08;font:800 15.5px var(--font-display);cursor:pointer}
.dk-ms{display:flex;align-items:center;gap:10px;padding:7px 6px;border-radius:12px}
.dk-ms .ic{width:32px;height:32px;border-radius:10px;background:var(--panel-3);display:flex;align-items:center;justify-content:center;flex:none}
.dk-ms .b{flex:1;min-width:0;font-size:13px;color:var(--text);font-weight:700}
.dk-ms .ms-pb{margin-top:5px;height:5px}
.dk-ms .n{font-size:12px;color:var(--text-dim);font-weight:700}
.dk-ms.is-locked{opacity:.6}
.dk-ms__h{font-size:11.5px;color:var(--text-dim);font-weight:600}

/* ★ 2026-10-05 Roster grid (chat mode, phone) */
.roster-bar.is-tap { cursor: pointer; -webkit-tap-highlight-color: transparent; }
.rb-chev { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; width: 24px; height: 24px; border-radius: 50%;
  background: rgba(79, 108, 240, .12); color: var(--accent, #4f6cf0); transition: transform .2s; }
.rb-chev .icon { width: 14px; height: 14px; color: inherit !important; }
.roster-bar.is-open .rb-chev { transform: rotate(180deg); }
.pgrid-wrap { margin: 6px 0 10px; background: var(--panel); border: 1px solid var(--border, rgba(120,130,170,.18)); border-radius: 18px;
  padding: 10px 10px 8px; box-shadow: 0 10px 30px rgba(40, 50, 90, .10); animation: pgIn .18s ease-out; }
.pgrid-wrap[hidden] { display: none; }
@keyframes pgIn { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
.pgrid-head { display: flex; justify-content: space-between; align-items: center; padding: 2px 4px 8px; font-size: 11px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; color: var(--text-dim); }
.pgrid-head span:last-child { letter-spacing: 0; text-transform: none; font-weight: 600; }
.pgrid { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 5px; max-height: 300px; overflow-y: auto; }
.pg { position: relative; display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 7px 2px 6px; border-radius: 12px; background: rgba(120, 130, 170, .07); min-width: 0; }
.pg .pg-ava, .pg .avatar { width: 36px !important; height: 36px !important; }
.pg b { font-size: 11.5px; font-weight: 600; line-height: 1.15; max-width: 100%; padding: 0 3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pg i { font-style: normal; font-size: 10px; font-weight: 600; line-height: 1; padding: 3px 6px; border-radius: 7px; background: rgba(120, 130, 170, .14);
  color: var(--text-dim); max-width: 94%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pg.is-me { outline: 2px solid var(--accent, #4f6cf0); outline-offset: -2px; }
.pg.is-me i { background: var(--accent, #4f6cf0); color: #fff; }
.pg.is-dead { background: rgba(20, 24, 40, .07); }
.pg.is-dead .pg-ava, .pg.is-dead .avatar, .pg.is-dead b { opacity: .45; filter: grayscale(1); }
.pg.is-dead i.is-maf { background: #d63a3a; color: #fff; }
.pg-x { position: absolute; top: 4px; right: 5px; color: #d63a3a; opacity: .75; line-height: 0; }
.pg-x .icon { width: 14px; height: 14px; }

/* ★ 2026-10-05 Voice: role counters on the top row + system-message log */
.vr-roster { display: flex; gap: 5px; flex: 0 1 auto; min-width: 0; overflow-x: auto; scrollbar-width: none; }
.vr-roster::-webkit-scrollbar { display: none; }
.vr-roster .rchip { display: inline-flex; align-items: center; gap: 3px; flex-shrink: 0; height: 28px; padding: 0 7px; border-radius: 999px;
  background: var(--panel-2); border: 1px solid var(--border-soft); font-size: 12.5px; font-weight: 800; color: var(--text); }
.vr-roster .rchip .icon { width: 13px; height: 13px; color: var(--text-dim); }
.vr-roster .rchip.is-mafia { background: rgba(214, 58, 58, .12); border-color: rgba(214, 58, 58, .4); color: #d63a3a; }
.vr-roster .rchip.is-mafia .icon { color: #e05555; }
.vr-roster .rchip.is-out { opacity: .35; }
.vr-top .sp { flex: 1 1 0; min-width: 0; }
.vr-top { gap: 5px; flex-wrap: nowrap; }
@media (max-width: 400px) {
  .vr-top .vr-chip, .vr-top .vr-timer { height: 28px; padding: 0 8px; font-size: 13px; }
}
@media (max-width: 420px) { .vr-rolechip > span { display: none; } .vr-rolechip { padding: 0 8px !important; } }
.vr-ann.has-log { position: relative; padding-right: 58px; }
.vr-log { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); width: 40px; height: 40px; border: 0; border-radius: 12px;
  background: rgba(79, 108, 240, .12); color: var(--accent, #4f6cf0); display: grid; place-items: center; cursor: pointer; }
.vr-log .icon { width: 20px; height: 20px; }
.vr-log em { position: absolute; top: -5px; right: -5px; min-width: 18px; height: 18px; padding: 0 4px; border-radius: 9px; background: var(--accent, #4f6cf0);
  color: #fff; font: 700 10px/18px inherit; font-style: normal; text-align: center; }
.vlog-bg { position: fixed; inset: 0; z-index: 900; background: rgba(15, 18, 32, .55); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  display: flex; align-items: center; justify-content: center; padding: 18px; animation: pgIn .16s ease-out; }
.vlog { width: 100%; max-width: 460px; max-height: 74vh; display: flex; flex-direction: column; overflow: hidden; border-radius: 22px;
  background: var(--panel); color: var(--text); box-shadow: 0 24px 60px rgba(0, 0, 0, .35); }
.vlog-h { display: flex; align-items: center; gap: 10px; padding: 16px 14px 12px 18px; border-bottom: 1px solid var(--border, rgba(120,130,170,.15)); }
.vlog-h b { font-size: 17px; font-weight: 800; } .vlog-h small { display: block; margin-top: 2px; font-size: 12px; color: var(--text-dim); }
.vlog-x { margin-left: auto; flex-shrink: 0; display: inline-flex; align-items: center; gap: 6px; height: 34px; padding: 0 14px; border: 0; border-radius: 17px;
  background: rgba(120, 130, 170, .14); color: var(--text); font: 600 13.5px inherit; cursor: pointer; }
.vlog-x .icon { width: 14px; height: 14px; }
.vlog-b { overflow-y: auto; padding: 4px 14px 16px; overscroll-behavior: contain; }
.vlog-d { position: sticky; top: 0; z-index: 1; background: var(--panel); padding: 12px 4px 6px; font-size: 11px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; color: var(--text-dim); }
.vlog-m { display: flex; gap: 10px; padding: 9px 10px; border-radius: 12px; font-size: 14px; line-height: 1.35; }
.vlog-m:nth-of-type(even) { background: rgba(120, 130, 170, .06); }
.vlog-m time { flex: none; width: 38px; font-size: 11.5px; line-height: 1.7; color: var(--text-dim); }
.vlog-m.is-new { background: rgba(79, 108, 240, .09) !important; box-shadow: inset 3px 0 0 var(--accent, #4f6cf0); }
@media (max-width: 440px) {
  .roster-bar.is-tap { gap: 4px; }
  .roster-bar.is-tap .rchip { padding-left: 7px; padding-right: 7px; gap: 3px; }
  .roster-bar.is-tap .rb-chev { width: 22px; height: 22px; }
}
.rb-chips { display: flex; gap: inherit; align-items: center; flex: 1 1 auto; min-width: 0; overflow-x: auto; scrollbar-width: none; }
.rb-chips::-webkit-scrollbar { display: none; }
.roster-bar .rb-chips + .sound-toggle, .roster-bar .rb-chev + .sound-toggle { margin-left: 0; }
.setting-select + .setting-row { margin-top: 12px; padding-top: 14px; border-top: 1px solid var(--border-soft); }

/* ★ 2026-10-05 Browser version: Pro by card transfer */
.cardnets { display: flex; gap: 8px; justify-content: center; margin: 14px 0 6px; }
.cardnets span { display: inline-flex; align-items: center; gap: 6px; padding: 7px 12px; border-radius: 10px; border: 1px solid var(--border-soft);
  background: var(--panel-2); font-size: 12.5px; font-weight: 800; letter-spacing: .06em; }
.cardnets span i { width: 8px; height: 8px; border-radius: 50%; background: #1aa0e0; }
.cardnets span.is-humo i { background: #f5a623; }
.webnote { display: flex; gap: 10px; margin: 14px 0 12px; padding: 12px 13px; border-radius: 14px; text-align: left;
  background: rgba(232, 185, 90, .10); border: 1px solid rgba(232, 185, 90, .32); font-size: 13.5px; line-height: 1.45; color: var(--text); }
.webnote .icon { flex: none; width: 18px; height: 18px; color: #d9a440; margin-top: 1px; }
.webnote b { white-space: nowrap; }
.pro-buy .pro-buy__close { margin-top: 8px; }
.web-logout { margin-top: 12px; justify-content: center; color: #d63a3a; }
.web-logout span { display: inline-flex; align-items: center; gap: 8px; }
.popup-card.pro-buy { max-width: 460px; }

/* ★ 2026-10-05 Voice post-game talk: roles under the faces */
.vt__role { display: inline-block; max-width: 100%; margin-top: 2px; padding: 2px 7px; border-radius: 7px; font-size: 10.5px; font-weight: 700;
  background: var(--panel-2); color: var(--text-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vt__role.is-maf { background: #d63a3a; color: #fff; }
.vr.is-postgame .vt.is-pgdead .vt__ava img, .vr.is-postgame .vt.is-pgdead .vt__ava .avatar { filter: grayscale(.85); opacity: .7; }
.vr.is-postgame .vt.is-pgdead { opacity: 1; }
.vr.is-postgame .vt.is-pgdead .vt__name { opacity: .7; }
.vr.is-postgame .ms-end, .vr.is-postgame .ms-strip { margin: 0 0 8px; }

/* ✎ 2026-10-07 Auto-name notice: the given name stands out on its own line (gold),
   two buttons below — "Tushunarli!" and "Sozlamalarga o'tish". */
.name-notice__text { margin: 0; text-align: center; font-size: 14.5px; line-height: 1.5; color: var(--text-dim); }
.name-notice__name { display: block; margin: 12px 0 10px; text-align: center; font-family: var(--font-display);
  font-weight: 800; font-size: 26px; line-height: 1.2; color: #f5b42a; text-shadow: 0 0 18px rgba(245, 180, 42, .35);
  overflow-wrap: anywhere; }
:root[data-theme="light"] .name-notice__name { color: #b7800c; text-shadow: none; }
.name-notice__btns { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 16px; }
.name-notice__btns .btn { white-space: nowrap; padding-left: 8px; padding-right: 8px; }

/* ================================================= ★ 2026-10-29 Qassob · Rais · counters */
.rchip.rc-sum { cursor: pointer; gap: 5px; }
.rchip.rc-sum b { font-weight: 800; }
.rchip.rc-sum b i { font-style: normal; opacity: .5; margin: 0 1px; }
.rchip.rc-sum b em { font-style: normal; color: #ff7b7b; }
.rchip.is-maf { color: #ff8a8a; }
.role-emoji { display: inline-block; vertical-align: middle; }
/* Rais */
.rais-fab { position: absolute; left: 16px; bottom: calc(16px + var(--gap-bottom)); width: 50px; height: 50px; border-radius: 50%;
  border: none; background: linear-gradient(180deg,#f2c14e,#d99a1c); color: #2a1c02; display: flex; align-items: center;
  justify-content: center; box-shadow: 0 6px 18px rgba(0,0,0,.35), 0 0 0 3px rgba(242,193,78,.18); z-index: 60; cursor: pointer; }
.rais-fab[hidden] { display: none !important; }
.rais-fab .icon { width: 24px; height: 24px; }
#app.has-bottom-actions .rais-fab { bottom: calc(74px + var(--gap-bottom)); }
.vr-btn.vr-rais { background: linear-gradient(180deg,#f2c14e,#d99a1c); color: #2a1c02; border-color: transparent; }
.rais-tag { display: inline-flex; align-items: center; gap: 2px; margin: 2px auto 0; padding: 1px 5px; border-radius: 99px;
  font: 800 8.5px/1.3 Inter,sans-serif; letter-spacing: .03em; color: #2a1c02; background: #f2c14e; }
.rais-tag .icon { width: 10px; height: 10px; }
.player-cell.is-rais { border-color: rgba(242,193,78,.6); }
.vt__tag.is-rais { color: #f2c14e; }
.vt__x2 { font-style: normal; font: 800 10px/1 Inter,sans-serif; color: #f2c14e; margin: 0 2px 0 -2px; align-self: center; }
.vr-rolechip.is-rais { color: #f2c14e; }
.rais-card { text-align: center; }
.rais-card__ic { width: 64px; height: 64px; margin: 4px auto 12px; border-radius: 50%; display: grid; place-items: center;
  background: rgba(242,193,78,.15); color: #f2c14e; }
.rais-card__btns { display: flex; gap: 10px; margin-top: 16px; }
.rais-card__btns .btn { flex: 1; }
.rais-yes { background: linear-gradient(180deg,#f2c14e,#d99a1c) !important; color: #2a1c02 !important; border: 0 !important; font-weight: 800; }
/* Qassob */
.vt.is-stab { outline: 2px dashed #ef4444; outline-offset: -2px; cursor: pointer; }
.vt.is-stab-on { outline-style: solid; box-shadow: 0 0 0 4px rgba(239,68,68,.3); }
.vt__aim.is-stab { color: #ff6b6b; }
.vr-cta-note { text-align: center; font-size: 11.5px; color: var(--text-dim); margin-top: 6px; }
.qassob-sheet { margin: 8px 14px; padding: 14px; border-radius: var(--radius-md); background: linear-gradient(180deg,#2a1219,#170c11);
  border: 1px solid rgba(239,68,68,.45); }
.qassob-sheet__h { display: flex; align-items: center; gap: 8px; font-weight: 800; font-size: 16px; color: #ff8a8a; }
.qassob-sheet p { margin: 6px 0 10px; font-size: 13px; line-height: 1.4; color: #e3c9cd; }
.qassob-grid { display: grid; grid-template-columns: repeat(auto-fill,minmax(76px,1fr)); gap: 8px; margin-bottom: 12px; }
.qassob-pick { display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 8px 4px; border-radius: 12px;
  border: 2px dashed rgba(239,68,68,.55); background: rgba(0,0,0,.2); color: var(--text); cursor: pointer; }
.qassob-pick img, .qassob-pick .avf { width: 46px; height: 46px; border-radius: 50%; object-fit: cover; }
.qassob-pick b { font-size: 12px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qassob-pick small { font-size: 10px; color: #ff9a9a; }
.qassob-pick.is-on { border-style: solid; border-color: #ef4444; background: rgba(239,68,68,.18); }
.qassob-go { background: #c0262d !important; color: #fff !important; border: 0 !important; font-weight: 800; display: flex; gap: 6px; justify-content: center; align-items: center; }
.qassob-go:disabled { opacity: .5; }
.qassob-wait { display: flex; align-items: center; gap: 8px; margin: 8px 14px; padding: 10px 12px; border-radius: var(--radius-sm);
  font-size: 13px; font-weight: 700; color: #ff9a9a; background: rgba(239,68,68,.1); border: 1px solid rgba(239,68,68,.3); }
.cut-banner { color: var(--text) !important; background: rgba(239,68,68,.12) !important; border: 1px solid rgba(239,68,68,.45) !important; opacity: 1 !important; }
.cut-banner b { color: #e23c3c; }
.vr-ann.is-cut { color: #ffd6d6; }
.vr-ann.is-cut b { color: #ff8a8a; }
.rb-chips:has(.rc-host) { min-width: 0; flex-wrap: nowrap; }
.rc-host { display: inline-flex; gap: 6px; flex-wrap: nowrap; min-width: 0; max-width: 100%; overflow-x: auto; scrollbar-width: none; }
.vr-roster.rc-host { flex: 1 1 auto; }
.rc-host::-webkit-scrollbar { display: none; }
.rc-host .rchip { flex: none; }
.cut-banner .icon { color: #ef4444; flex-shrink: 0; }
.player-cell.is-viewonly { cursor: default; pointer-events: none; }
.player-cell.is-viewonly:active { transform: none; }
/* custom announcement cards */
.ann-ov.is-custom .ann-front { background: linear-gradient(180deg,#2a1219,#150b10); }
.ann-ov.is-custom.is-rais .ann-front { background: linear-gradient(180deg,#16314a,#0d1d2e); border-color: rgba(125,200,255,.6); }
.ann-ov.is-custom.is-rais .ann-text b { color: #9fdcff; }
.ann-ov.is-custom.is-rais .ann-facewrap img, .ann-ov.is-custom.is-rais .ann-facewrap .avf > img:first-child { filter: none; }
.ann-ov.is-custom.is-qassob .ann-front { border-color: rgba(239,68,68,.65); }
.ann-emoji { position: absolute; right: -6px; bottom: -6px; width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center;
  background: #0f1420; box-shadow: 0 0 0 3px rgba(255,255,255,.08); }
.ann-emoji-big { margin: 6px 0 16px; }
/* friend icon buttons in the post-game summary */
.sum-friend.is-ico { display: grid; place-items: center; width: 28px; height: 28px; padding: 0; margin: 5px auto 0; border-radius: 50%;
  background: rgba(79,124,255,.14); color: var(--accent); }
.sum-friend.is-ico.is-accept { background: rgba(34,197,94,.15); border-color: rgba(34,197,94,.4); color: var(--green); }
.sum-friend.is-ico.is-done { background: none; }
.sum-friend.is-ico .icon { width: 15px; height: 15px; }
.rl-credit { margin: 18px 0 6px; text-align: center; font-size: 11px; color: var(--text-dim); }
.qassob-sheet, .qassob-pick, .qassob-pick b { color: #fff; }
.qassob-sheet p { color: #e3c9cd; }

/* ================================================= ★ 2026-10-30 Ovul (approved v3 mockups) */
.ovl-tile{border-radius:16px;display:grid;place-items:center;flex:none;box-shadow:inset 0 0 0 1px rgba(255,255,255,.12)}
.ovl-tile img{width:78%;height:78%;object-fit:contain;filter:drop-shadow(0 3px 6px rgba(0,0,0,.45))}
.ovl-head{display:flex;gap:12px;align-items:center;margin:4px 16px 10px;padding:12px 14px;border-radius:18px;background:var(--panel);border:1px solid rgba(255,255,255,.07)}
.ovl-name{font-family:var(--font-display);font-weight:800;font-size:17px;display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.ovl-sub{font-size:12.5px;color:var(--text-dim);margin-top:4px;display:flex;gap:10px;flex-wrap:wrap}
.ovl-sub b{color:var(--text)}
.ovl-lvl{margin-top:8px;display:flex;align-items:center;gap:8px;font-size:11.5px;color:var(--text-dim)}
.ovl-lvl__bar{flex:1;height:6px;border-radius:4px;background:rgba(255,255,255,.08);overflow:hidden}.ovl-lvl__bar i{display:block;height:100%;width:24%;background:#2f6fe4}
.ov-tag{font-style:normal;display:inline-block;font-size:10.5px;font-weight:800;letter-spacing:.06em;padding:2px 6px;border-radius:6px;color:#fff;line-height:1.35;vertical-align:1px;margin-right:4px}
.ov-tag.l1{background:#6b7486}.ov-tag.l2{background:#16a364}.ov-tag.l3{background:#2f6fe4}.ov-tag.l4{background:#7c4ff0}.ov-tag.l5{background:#e23b3b}
.ov-tag.l6{background:linear-gradient(135deg,#f5b428,#ffe08a,#e09b12);color:#3a2600;box-shadow:0 0 10px rgba(245,180,40,.45)}
.ov-tag.big{font-size:13px;padding:3px 8px;border-radius:8px}
.ovl-role{font-size:10px;font-weight:800;padding:2px 6px;border-radius:6px;margin-left:5px;vertical-align:1px;font-style:normal}
.ovl-role.o{background:#f5b428;color:#3a2600}.ovl-role.m{background:rgba(96,140,255,.18);color:#8fb0ff}
.ovl-pin{margin:0 16px 8px;padding:9px 12px;border-radius:14px;background:rgba(245,180,40,.10);border:1px solid rgba(245,180,40,.35);font-size:13px;display:flex;gap:8px;align-items:flex-start}
.ovl-pin b{display:block;font-size:11px;letter-spacing:.06em;color:#f0b43a;text-transform:uppercase}
.ovl-pin .dim{color:var(--text-dim);font-size:11.5px;margin-top:3px}
.ovl-chat{margin:0 12px;padding:2px 4px 80px}
.ovl-keep{text-align:center;font-size:11.5px;color:var(--text-dim);margin:2px 0 6px;display:flex;gap:5px;justify-content:center;align-items:center}
.ovl-inv{margin:8px 6px;padding:11px 12px;border-radius:16px;background:linear-gradient(135deg,rgba(59,99,240,.16),rgba(138,92,246,.18));border:1px solid rgba(124,92,246,.4);display:flex;gap:10px;align-items:center}
.ovl-inv__ic{width:38px;height:38px;border-radius:12px;background:#3b63f0;color:#fff;display:grid;place-items:center;flex:none}
.ovl-inv__t{flex:1;font-size:13px;line-height:1.3}.ovl-inv__t b{display:block;font-size:14px}
.ovl-inv__t span{color:var(--text-dim);font-size:12px;display:block}
.ovl-inv__t .free{color:#5fd39a;font-weight:700}
.ovl-elon{margin:8px 6px;padding:11px 12px;border-radius:16px;background:rgba(245,180,40,.08);border:1px solid rgba(245,180,40,.35);font-size:13.5px}
.ovl-elon b{display:flex;gap:6px;align-items:center;font-size:11px;letter-spacing:.06em;color:#f0b43a;text-transform:uppercase;margin-bottom:4px}
.ovl-elon .meta{font-size:11.5px;color:var(--text-dim);margin-top:6px}
.ovl-steps{display:flex;gap:6px;justify-content:center;margin:2px 0 12px}.ovl-steps i{width:26px;height:5px;border-radius:3px;background:rgba(255,255,255,.12)}.ovl-steps i.on{background:#4c6ef5}
.ovl-hint{font-size:12px;color:var(--text-dim);margin:5px 2px 0}
.ovl-ok{color:#51cf66;font-weight:700}.ovl-bad{color:#ff6b6b;font-weight:700}
.ovl-tagin{display:flex;gap:8px;align-items:center}.ovl-tagin input{text-transform:uppercase;letter-spacing:.12em;font-weight:800}
.ovl-chips{display:flex;gap:6px;overflow:hidden;margin:0 0 10px;flex-wrap:nowrap}
.ovl-chip{flex:none;padding:6px 11px;border-radius:999px;font-size:12.5px;font-weight:700;background:rgba(255,255,255,.06);color:var(--text-dim);border:1px solid rgba(255,255,255,.08)}
.ovl-chip.on{background:#3b5bdb;color:#fff;border-color:#3b5bdb}
.ovl-egrid{display:grid;grid-template-columns:repeat(5,1fr);gap:8px}
.ovl-ecell{aspect-ratio:1;border-radius:14px;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.07);display:grid;place-items:center}
.ovl-ecell img{width:82%;height:82%;object-fit:contain}
.ovl-ecell.on{border:2px solid #4c6ef5;background:rgba(76,110,245,.14)}
.ovl-bgrid{display:grid;grid-template-columns:repeat(6,1fr);gap:8px}
.ovl-bcell{aspect-ratio:1;border-radius:12px;box-shadow:inset 0 0 0 1px rgba(255,255,255,.12)}
.ovl-bcell.on{outline:3px solid #fff;outline-offset:2px}
.ovl-prev{display:flex;flex-direction:column;align-items:center;gap:8px;padding:6px 0 14px}
.ovl-seg{display:grid;grid-template-columns:repeat(3,1fr);gap:6px}
.ovl-seg button{padding:10px 6px;border-radius:12px;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.08);color:var(--text);font-weight:700;font-size:12.5px;display:flex;flex-direction:column;align-items:center;gap:4px}
.ovl-seg button.on{background:rgba(76,110,245,.18);border-color:#4c6ef5;color:#fff}
.ovl-seg small{font-weight:500;color:var(--text-dim);font-size:10.5px;line-height:1.2;text-align:center}
.ovl-radio{display:flex;gap:10px;align-items:flex-start;padding:10px 12px;border-radius:12px;background:rgba(255,255,255,.04);margin-top:6px;font-size:13px}
.ovl-radio i{width:18px;height:18px;border-radius:50%;border:2px solid rgba(255,255,255,.3);flex:none;margin-top:1px}
.ovl-radio.on i{border:5px solid #4c6ef5}
.ovl-radio span{color:var(--text-dim);font-size:11.5px;display:block;margin-top:2px}
.ovl-row{display:flex;align-items:center;gap:10px;padding:12px 14px;border-bottom:1px solid rgba(255,255,255,.06);font-size:14px}
.ovl-row:last-child{border-bottom:0}
.ovl-row__v{margin-left:auto;color:var(--text-dim);font-size:13px;display:flex;gap:6px;align-items:center}
.ovl-row .icon{color:var(--text-dim)}
.ovl-row.danger{color:#ff6b6b}.ovl-row.danger .icon{color:#ff6b6b}
.ovl-row.lock{opacity:.55}
.ovl-card{background:var(--panel);border:1px solid rgba(255,255,255,.07);border-radius:16px;margin:0 16px 12px;overflow:hidden}
.ovl-acts{display:flex;flex-direction:column;gap:2px}
.ovl-act{display:flex;gap:12px;align-items:center;padding:13px 12px;border-radius:12px;font-size:14.5px;font-weight:600}
.ovl-act:active{background:rgba(255,255,255,.05)}
.ovl-act small{display:block;font-weight:500;color:var(--text-dim);font-size:12px;margin-top:2px}
.ovl-act.danger{color:#ff6b6b}
.ovl-act .ic{width:36px;height:36px;border-radius:10px;background:rgba(255,255,255,.06);display:grid;place-items:center;flex:none}
.ovl-act.danger .ic{background:rgba(255,107,107,.12)}
.ovl-act.gold .ic{background:rgba(245,180,40,.15);color:#f0b43a}
.ovl-whohead{display:flex;gap:10px;align-items:center;padding:4px 4px 12px;border-bottom:1px solid rgba(255,255,255,.07);margin-bottom:6px}
.ovl-whohead img{width:44px;height:44px;border-radius:50%}
.ovl-sel{display:flex;gap:6px;margin:4px 0 0 48px}
.ovl-sel span{padding:5px 10px;border-radius:999px;background:rgba(255,255,255,.07);font-size:12px;font-weight:700}
.ovl-sel span.on{background:#3b5bdb;color:#fff}
.ovl-bot{margin-top:10px;border-radius:14px;background:#17212b;padding:10px;border:1px solid rgba(255,255,255,.06)}
.ovl-bot__h{display:flex;gap:8px;align-items:center;font-size:12.5px;font-weight:700;margin-bottom:6px}
.ovl-bot__h img{width:26px;height:26px;border-radius:50%}
.ovl-bot__m{background:#182533;border-radius:12px 12px 12px 4px;padding:9px 11px;font-size:13px;line-height:1.45;color:#e9eef5}
.ovl-bot__btn{margin-top:6px;text-align:center;padding:8px;border-radius:10px;background:#2b5278;color:#fff;font-size:13px;font-weight:600}
.ovl-rules{font-size:13.5px;line-height:1.55;padding:10px 12px;border-radius:12px;background:rgba(255,255,255,.04);margin:0 0 10px}
.ovl-rules ol{margin:0;padding-left:18px}.ovl-rules li{margin:3px 0}
.ovl-agree{display:flex;gap:10px;align-items:center;padding:12px;border-radius:12px;background:rgba(76,110,245,.12);border:1px solid rgba(76,110,245,.4);font-size:13.5px;font-weight:600;margin-bottom:10px}
.ovl-agree i{width:22px;height:22px;border-radius:6px;background:#4c6ef5;display:grid;place-items:center;color:#fff;flex:none}
.ovl-req{display:flex;gap:8px;align-items:center;font-size:13px;padding:9px 12px;border-radius:12px;background:rgba(81,207,102,.1);border:1px solid rgba(81,207,102,.35);color:#8ce99a;margin:0 0 10px}
.ovl-banner{margin:0 16px 12px;padding:12px 14px;border-radius:16px;background:rgba(76,110,245,.12);border:1px solid rgba(76,110,245,.4);display:flex;gap:10px;align-items:center;font-size:13px}
.ovl-banner b{display:block;font-size:14px}
.ovl-card2{display:flex;gap:10px;align-items:center;margin:0 16px 8px;padding:10px 12px;border-radius:16px;background:var(--panel);border:1px solid rgba(255,255,255,.06)}
.ovl-card2__m{flex:1;min-width:0}.ovl-card2__n{font-weight:800;font-size:14.5px;display:flex;gap:6px;align-items:center}
.ovl-card2__s{font-size:12px;color:var(--text-dim);margin-top:2px}
.ovl-search{margin:4px 16px 10px;display:flex;gap:8px;align-items:center;padding:11px 14px;border-radius:14px;background:var(--panel);border:1px solid rgba(255,255,255,.08);color:var(--text-dim);font-size:14px}
.ovl-cta{margin:4px 16px 12px;padding:16px;border-radius:18px;background:linear-gradient(135deg,#232a6b,#6b4ce6);color:#fff}
.ovl-cta h3{margin:0 0 4px;font-family:var(--font-display);font-size:17px;display:flex;gap:7px;align-items:center}
.ovl-cta p{margin:0 0 12px;font-size:13px;opacity:.85}
.ovl-cta .btn{background:#fff;color:#3b2fb0}
.ovl-perks{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin:0 0 12px;font-size:12px}
.ovl-perks span{display:flex;gap:6px;align-items:center;background:rgba(255,255,255,.12);padding:6px 8px;border-radius:10px}
.ovl-menu{position:absolute;z-index:40;width:230px;background:#232b3b;border:1px solid rgba(255,255,255,.1);border-radius:14px;box-shadow:0 12px 32px rgba(0,0,0,.5);padding:6px}
.ovl-menu div{display:flex;gap:10px;align-items:center;padding:10px 10px;border-radius:9px;font-size:14px}
.ovl-menu div.danger{color:#ff6b6b}
.ovl-log{display:flex;gap:10px;padding:10px 14px;border-bottom:1px solid rgba(255,255,255,.06);font-size:13px;align-items:flex-start}
.ovl-log .ic{width:30px;height:30px;border-radius:9px;display:grid;place-items:center;flex:none;background:rgba(255,255,255,.06)}
.ovl-log time{display:block;font-size:11.5px;color:var(--text-dim);margin-top:2px}
.ovl-note{font-size:12.5px;color:var(--text-dim);line-height:1.45;margin:8px 2px 0}
.ovl-warn{display:flex;gap:8px;padding:10px 12px;border-radius:12px;background:rgba(255,107,107,.1);border:1px solid rgba(255,107,107,.35);color:#ffa8a8;font-size:12.5px;line-height:1.4;margin:8px 0 10px}
.ovl-success{text-align:center;padding:6px 0 4px}
.ovl-success h2{font-family:var(--font-display);margin:10px 0 4px;font-size:21px}
.ovl-link{display:flex;gap:8px;align-items:center;padding:10px 12px;border-radius:12px;background:rgba(255,255,255,.05);font-size:12.5px;color:var(--text-dim);margin:12px 0 8px;word-break:break-all;text-align:left}
.ovl-2btn{display:grid;grid-template-columns:1fr 1fr;gap:8px}
/* menu button: three o'tovs at 1.7x, thin strokes */
.ovul-btn .ovul-ic{width:34px;height:34px;stroke-width:1.15}
.ovul-btn{position:relative}
.ovl-tile{display:grid;place-items:center;flex:none;box-shadow:inset 0 0 0 1px rgba(255,255,255,.12)}
.ovl-tile img{width:78%;height:78%;object-fit:contain;filter:drop-shadow(0 3px 6px rgba(0,0,0,.45))}
.ovl-tile.is-inline{display:inline-grid;vertical-align:-4px;margin:0 2px}
.ovl-page{padding-top:4px}
.ovl-body{padding-bottom:84px}
.ovl-tabs{margin:0 16px 10px}
.ovl-search input{flex:1;min-width:0;background:none;border:0;outline:0;color:var(--text);font:inherit;font-size:14px}
.ovl-card2{cursor:pointer}
.ovl-banner{cursor:pointer}
.ovl-desc{font-size:13.5px;text-align:center;color:var(--text-dim);max-width:300px}
.ovl-lbl{font-size:12px;font-weight:700;color:var(--text-dim);text-transform:uppercase;letter-spacing:.06em}
.ovl-ecell,.ovl-bcell{border:0;padding:0;cursor:pointer}
.ovl-ecell{border:1px solid rgba(255,255,255,.07)}
.ovl-chip{cursor:pointer}
.ovl-chips{overflow-x:auto;scrollbar-width:none}
.ovl-chips::-webkit-scrollbar{display:none}
.ovl-seg button{cursor:pointer}
.ovl-radio{cursor:pointer}
.ovl-agree{cursor:pointer;background:rgba(255,255,255,.04);border-color:rgba(255,255,255,.12)}
.ovl-agree input{display:none}
.ovl-agree i{background:transparent;border:2px solid rgba(255,255,255,.35)}
.ovl-agree i .icon{opacity:0}
.ovl-agree.is-on{background:rgba(76,110,245,.12);border-color:rgba(76,110,245,.4)}
.ovl-agree.is-on i{background:#4c6ef5;border-color:#4c6ef5}.ovl-agree.is-on i .icon{opacity:1}
.ovl-row{width:100%;background:none;border:0;border-bottom:1px solid rgba(255,255,255,.06);color:var(--text);font:inherit;text-align:left;cursor:pointer}
.ovl-act{width:100%;background:none;border:0;color:var(--text);font:inherit;text-align:left;cursor:pointer}
.ovl-sel button{padding:5px 10px;border-radius:999px;background:rgba(255,255,255,.07);font-size:12px;font-weight:700;border:0;color:var(--text);cursor:pointer}
.ovl-sel button.on{background:#3b5bdb;color:#fff}
.ovl-danger{background:#c92a2a!important;color:#fff!important;border:0!important}
.ovl-danger:disabled{opacity:.45}
.ovl-quote{font-size:13px;color:var(--text-dim);padding:8px 12px;border-left:3px solid #4c6ef5;background:rgba(255,255,255,.04);border-radius:8px;margin-bottom:10px}
.ovl-time{display:block;text-align:right;font-size:10.5px;color:var(--text-dim);margin-top:2px}
.ovl-chat .msg{user-select:none;-webkit-user-select:none}
.ovl-compose{position:fixed;left:0;right:0;bottom:0;z-index:30;display:flex;gap:8px;align-items:center;max-width:480px;margin:0 auto;
  padding:10px 12px calc(10px + var(--safe-bottom,0px));background:var(--bg);border-top:1px solid var(--border-soft)}
.ovl-compose input{flex:1;min-width:0;height:42px;border-radius:21px;border:1px solid var(--border);background:var(--panel);color:var(--text);padding:0 16px;font:inherit;font-size:14.5px;outline:0}
.ovl-compose input:focus{border-color:var(--accent)}
.ovl-send{width:42px;height:42px;border-radius:50%;border:0;background:var(--accent);color:#fff;display:grid;place-items:center;flex:none;cursor:pointer}
.ovl-elonbtn{width:42px;height:42px;border-radius:50%;border:0;background:#f0b429;color:#3a2600;display:grid;place-items:center;flex:none;cursor:pointer;box-shadow:0 4px 14px rgba(240,180,41,.3)}
.ovl-elonbtn.is-used{background:var(--panel-3);color:var(--text-dim);box-shadow:none}
.ovl-roombox{margin:0 0 6px;padding:0 2px;border-radius:14px;border:1px solid rgba(76,110,245,.45);background:rgba(76,110,245,.06)}
.ovl-roomtag{color:#9fb3ff;background:rgba(76,110,245,.14);border-color:rgba(76,110,245,.35)}
.ovl-badgepick{grid-template-columns:repeat(3,1fr)}
.ovl-badgepick .picker-cell{display:grid;place-items:center}
/* Ovul badge in place of the Pro icon (premiumBadge in icons.js) */
.prem-badge.prem-ovtag{width:auto;height:auto;margin-right:5px;vertical-align:1px}
.prem-badge.prem-ovtag.is-big{font-size:12px;padding:2px 7px}
.prem-badge.prem-ovemb{display:inline-grid;place-items:center;width:16px;height:16px;margin-right:5px;border-radius:5px;vertical-align:-3px;box-shadow:inset 0 0 0 1px rgba(255,255,255,.15);overflow:hidden;flex:none}
.prem-badge.prem-ovemb.is-big{width:22px;height:22px;border-radius:6px;vertical-align:-4px}
.prem-badge.prem-ovemb.is-xl{width:34px;height:34px;border-radius:9px;margin:0}
.prem-badge.prem-ovemb img{width:86%!important;height:86%!important;object-fit:contain;margin:0!important;border-radius:0!important}
.prem-cell.is-ovemb{border-radius:7px;display:grid;place-items:center}
.prem-cell.is-ovemb img{width:84%!important;height:84%!important}
.prem-cell.is-ovtag{background:none;box-shadow:none;width:auto}
.prem-cell.is-ovtag .ov-tag{font-size:8.5px;padding:1px 4px;margin:0;border:1.5px solid var(--panel)}
/* profile card: Pro chip in the corner, Ovul block as one link */
.profile-card{position:relative}
.pc-corner{position:absolute;top:8px;left:8px;z-index:3;font-size:11.5px!important;padding:2px 8px!important;border-radius:7px}
.pc-ovul{display:flex;align-items:center;gap:12px;width:100%;margin:12px 0 4px;padding:11px 12px;border-radius:16px;overflow:hidden;cursor:pointer;
  background:linear-gradient(135deg,rgba(76,110,245,.22),rgba(20,26,58,.6));border:1px solid rgba(110,140,255,.35);color:var(--text);font:inherit;text-align:left;
  transition:transform .15s}
.pc-ovul:active{transform:scale(.98)}
.pc-ovul__main{flex:1;min-width:0;display:flex;flex-direction:column}
.pc-ovul__k{font-size:10.5px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:#9fb3ff;display:flex;align-items:center;gap:5px}
.pc-ovul__k .ov-tag{margin:0 0 0 2px;vertical-align:0}
.pc-ovul__n{font-family:var(--font-display);font-weight:800;font-size:16px;margin-top:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pc-ovul__s{font-size:11.5px;color:var(--text-dim);margin-top:4px;display:flex;gap:6px;align-items:center;white-space:nowrap}
.pc-role{font-style:normal;font-size:10px;font-weight:800;padding:2px 6px;border-radius:6px;background:rgba(96,140,255,.2);color:#9fb8ff}
.pc-role.is-o{background:#f5b428;color:#3a2600}
.pcd-r .pc-ovul{margin:0 0 14px}
:root[data-theme="light"] .pc-ovul{background:linear-gradient(135deg,rgba(76,110,245,.14),rgba(76,110,245,.04));border-color:rgba(76,110,245,.35)}
:root[data-theme="light"] .pc-ovul__k{color:#3b5bdb}
/* light theme: the mockup surfaces were dark-only */
:root[data-theme="light"] .ovl-head,:root[data-theme="light"] .ovl-card,:root[data-theme="light"] .ovl-card2,:root[data-theme="light"] .ovl-search{border-color:var(--border)}
:root[data-theme="light"] .ovl-row{border-bottom-color:var(--border-soft)}
:root[data-theme="light"] .ovl-chip,:root[data-theme="light"] .ovl-seg button,:root[data-theme="light"] .ovl-radio,:root[data-theme="light"] .ovl-rules,:root[data-theme="light"] .ovl-ecell,:root[data-theme="light"] .ovl-sel button{background:var(--panel-2);border-color:var(--border)}
:root[data-theme="light"] .ovl-lvl__bar{background:var(--panel-3)}
:root[data-theme="light"] .ovl-pin,:root[data-theme="light"] .ovl-elon{color:var(--text)}
@media (min-width:900px){ body.desk .ovl-compose{max-width:none;left:auto;right:auto;position:sticky} }

.ovl-body .scroll-page{overflow:visible;flex:none;min-height:auto}
.menu-iconrow .header-share-btn .icon.ovul-ic{width:34px;height:34px;stroke-width:1.15}
.ovl-sheet .profile-field textarea{width:100%;box-sizing:border-box;background:var(--panel-2);border:1px solid var(--border);border-radius:var(--radius-sm);
  padding:12px 14px;color:var(--text);font:500 14px/1.45 var(--font-display);resize:none;outline:0}
.ovl-sheet .profile-field textarea:focus,.ovl-sheet .profile-field input:focus{border-color:var(--accent)}
.ovl-sheet .modal-sheet{max-height:calc(100vh - 40px);overflow-y:auto}
.profile-card.is-premium:not(.is-desk) .profile-head{margin-top:12px}
/* ★ 2026-10-31 Ovul windows: phone-sized on every screen. Without a cap the desktop dialog
   stretched to the full width and the emblem / background grids grew with it. */
.ovl-sheet .modal-sheet{width:100%;max-width:440px;margin:0 auto}
.ovl-egrid{grid-template-columns:repeat(5,minmax(0,76px));justify-content:center}
.ovl-bgrid{grid-template-columns:repeat(6,minmax(0,56px));justify-content:center}
body.desk .ovl-sheet .modal-sheet{max-width:460px;max-height:calc(100vh - 80px)}
/* ★ 2026-10-31 one scrolling emblem grid (no category chips) */
.ovl-escroll{max-height:min(46vh,340px);overflow-y:auto;overscroll-behavior:contain;margin:0 -4px;padding:4px;border-radius:14px}
.ovl-escroll .ovl-egrid{grid-template-columns:repeat(5,minmax(0,1fr));justify-content:stretch}
.ovl-escroll .ovl-ecell{max-width:none}
.ovl-escroll{position:relative}
/* ★ 2026-10-31 Ovul tag / emblem in the Pro badge picker */
.picker-cell.is-ovul{display:grid;place-items:center}
.picker-cell.is-ovul .prem-ovemb.is-xl{width:34px;height:34px;border-radius:9px}
.picker-cell.is-ovul .prem-ovtag.is-xl{font-size:11px}
/* ★ 2026-10-31 staff Ovul tag (ADMIN): red-black, a thin red edge and a soft red glow */
.ov-tag.staff{background:linear-gradient(135deg,#d42a35 0%,#5a0d16 55%,#0b0b0e 100%);color:#fff;
  box-shadow:inset 0 0 0 1px rgba(255,90,100,.55),0 0 10px rgba(226,40,50,.45);text-shadow:0 1px 2px rgba(0,0,0,.6)}
/* ★ 2026-10-31 One scrollbar for the whole app: thin, rounded, no arrow buttons, transparent
   track, a soft thumb that brightens on hover. Chrome 121+ ignores ::-webkit-scrollbar on any
   element that sets scrollbar-width / scrollbar-color, so the standard properties are only
   given to browsers without the webkit selector (Firefox). Places that hide their bar
   (scrollbar-width:none + display:none) keep doing so — those rules are more specific. */
*::-webkit-scrollbar{width:6px;height:6px;background:transparent}
*::-webkit-scrollbar-track{background:transparent}
*::-webkit-scrollbar-thumb{background:rgba(140,152,175,.28);border-radius:99px}
*::-webkit-scrollbar-thumb:hover{background:rgba(140,152,175,.5)}
*::-webkit-scrollbar-thumb:active{background:var(--accent)}
*::-webkit-scrollbar-button{display:none;width:0;height:0}
*::-webkit-scrollbar-corner{background:transparent}
@supports not selector(::-webkit-scrollbar){*{scrollbar-width:thin;scrollbar-color:rgba(140,152,175,.35) transparent}}
/* ★ 2026-10-31 The Ovul tag sat on the text baseline, so next to a bigger name it read low.
   Centre it on the name's letters instead, everywhere it is used as a badge. */
.prem-badge.prem-ovtag,.profile-card .profile-name .prem-badge.prem-ovtag{vertical-align:middle;position:relative;top:-.08em}
.prem-badge.prem-ovemb,.profile-card .profile-name .prem-badge.prem-ovemb{vertical-align:middle;position:relative;top:-.08em}
/* ★ 2026-10-31 Rais reveal: the elimination flip card, in green (front and role side). */
.ann-ov.is-rais .ann-front{background:linear-gradient(180deg,#123222,#0a1a12);border-color:rgba(34,197,94,.6);box-shadow:0 24px 60px rgba(0,0,0,.6),0 0 40px rgba(34,197,94,.18)}
.ann-ov.is-rais .ann-front .ann-facewrap>img,.ann-ov.is-rais .ann-front .ann-facewrap>.avf>img:first-child{filter:none}
.ann-ov.is-rais .ann-front .ann-text b{color:#7ee2a8}
.ann-ov.is-rais .ann-back,.ann-ov.is-rais .ann-back.ann-role{background:linear-gradient(180deg,#14402a,#0b1f15);border-color:rgba(34,197,94,.65)}
.ann-ov.is-rais .ann-back .ann-text b{color:#9ff0c0}
.ann-ov.is-rais .ann-rolename{color:#7ee2a8}
/* ★ 2026-10-31 Reyting: Top O'yinchilar / Top Ovullar, Ovul blocks, Top 10 badge, Blok foni */
.lbx-seg{display:grid;grid-template-columns:1fr 1fr;gap:4px;margin:4px 16px 10px;padding:4px;border-radius:14px;background:var(--panel);border:1px solid var(--border-soft)}
.lbx-seg button{height:40px;border:0;border-radius:11px;background:none;color:var(--text-dim);font:inherit;font-weight:800;font-size:14px;display:flex;align-items:center;justify-content:center;gap:7px;cursor:pointer}
.lbx-seg button .icon{width:17px;height:17px}
.lbx-seg button.on{background:linear-gradient(135deg,#4f7cff,#7c5cff);color:#fff;box-shadow:0 6px 16px -8px rgba(79,124,255,.8)}
.tov-note{display:flex;align-items:center;gap:7px;margin:2px 4px 12px;font-size:12px;color:var(--text-dim)}
.tov-hint{font-size:12px;color:var(--text-dim);margin:-2px 4px 10px}
.tov-legend{margin:14px 2px 6px;padding:11px 12px;border-radius:14px;background:var(--panel);border:1px solid var(--border-soft);font-size:12px;line-height:1.45;color:var(--text-dim)}
.tov-legend b{color:var(--text)} .tov-legend b.g{color:#4ade80}
.tov-legend .lg{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}
.tov-legend .icon{width:14px;height:14px;vertical-align:-2px}
.ovb{position:relative;display:flex;align-items:center;gap:12px;width:100%;margin:0 0 8px;padding:11px 12px;border-radius:16px;overflow:hidden;
  border:1px solid;color:var(--text);font:inherit;text-align:left;cursor:pointer;transition:transform .15s}
.ovb:active{transform:scale(.98)}
.ovb.is-me{box-shadow:0 0 0 2px rgba(79,124,255,.6)}
.ovb__rk{width:24px;flex:none;text-align:center;font-family:var(--font-display);font-weight:800;font-size:14px;color:var(--text-dim)}
.ovb .ovl-tile{flex:none}
.ovb__m{flex:1;min-width:0;display:flex;flex-direction:column}
.ovb__k{font-size:10.5px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:rgba(255,255,255,.72);display:flex;align-items:center;gap:5px}
.ovb__k .icon{width:14px;height:14px}
.ovb__k .ov-tag{margin:0 0 0 2px;vertical-align:0}
.ovb__n{font-family:var(--font-display);font-weight:800;font-size:16px;margin-top:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ovb__s{font-size:11.5px;color:rgba(255,255,255,.62);margin-top:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ovb__p{flex:none;text-align:right;padding-top:16px}
.ovb__p b{display:block;font-family:var(--font-display);font-size:18px}
.ovb__p span{font-size:10.5px;color:rgba(255,255,255,.6)}
.ov-top{display:inline-flex;align-items:center;gap:3px;padding:2px 8px;border-radius:99px;font-size:11px;font-weight:800;letter-spacing:.02em;text-transform:none;
  background:linear-gradient(135deg,#f5b428,#ffe08a,#e09b12);color:#3a2600;box-shadow:0 0 10px rgba(245,180,40,.35);white-space:nowrap;font-style:normal}
.ov-top .icon{width:12px;height:12px}
.ovb>.ov-top{position:absolute;top:8px;right:9px}
.ov-top.is-inline{margin-left:auto}
.pc-ovul__k{width:100%}
.ovl-rank{display:inline-grid;place-items:center;min-width:24px;height:20px;padding:0 5px;margin-right:5px;border-radius:7px;background:rgba(255,255,255,.07);font-size:11px;font-weight:800;color:var(--text-dim);vertical-align:1px}
.ovl-rank.is-top{background:rgba(245,180,40,.18);color:#f5b428}
.ovl-card2__s b{color:var(--text)}
.ovl-pts{display:flex;align-items:center;gap:6px;margin-top:7px;font-size:12px}
.ovl-pts .icon{width:13px;height:13px;vertical-align:-2px;color:#f6c453}
.ovl-pts b{color:var(--text)}
.ovl-bbsw{display:inline-block;width:20px;height:20px;border-radius:6px;border:1px solid}
.ovl-bbgrid{display:grid;grid-template-columns:repeat(5,1fr);gap:8px;margin-top:12px}
.ovl-bbcell{height:44px;border-radius:12px;border:1px solid;cursor:pointer;padding:0}
.ovl-bbcell.on{outline:2px solid #fff;outline-offset:2px}
.hist-ovb{display:inline-flex;align-items:center;gap:3px;font-size:10.5px;font-weight:800;padding:1px 7px;border-radius:99px;background:rgba(34,197,94,.14);color:#4ade80;border:1px solid rgba(34,197,94,.35)}
.hist-ovb .icon{width:12px;height:12px}
.ovb,.ovl-bbcell,.ovl-bbsw{background-color:#141a26}
:root[data-theme="light"] .ovb,:root[data-theme="light"] .pc-ovul{color:#fff;background-color:#1b2233}
/* ★ 2026-11-01 Desktop sidebar news slides (replaces .dk-promo) */
.dk-news{position:relative;overflow:hidden;border-radius:18px;border:1px solid var(--border-soft);background:var(--panel)}
.dk-news__track{display:flex;transition:transform .55s cubic-bezier(.4,.1,.2,1)}
.dk-news__s{position:relative;flex:0 0 100%;min-height:176px;padding:16px 16px 34px;box-sizing:border-box;overflow:hidden}
.dk-news__s.c-gold{background:linear-gradient(120deg,#2a2210,var(--panel) 75%)}
.dk-news__s.c-red{background:linear-gradient(120deg,#2c1216,var(--panel) 75%)}
.dk-news__s.c-blue{background:linear-gradient(120deg,#13203d,var(--panel) 75%)}
.dk-news__s.c-green{background:linear-gradient(120deg,#10291c,var(--panel) 75%)}
.dk-news__s.c-purple{background:linear-gradient(120deg,#24173d,var(--panel) 75%)}
.dk-news__k{display:inline-block;font-size:10px;font-weight:800;letter-spacing:.1em;padding:2px 8px;border-radius:99px;background:rgba(255,255,255,.1);color:#ffd77a;margin-bottom:6px;position:relative;z-index:1}
.dk-news__s.c-red .dk-news__k{color:#ff9a9a}.dk-news__s.c-blue .dk-news__k{color:#9db8ff}.dk-news__s.c-green .dk-news__k{color:#7ee2a8}.dk-news__s.c-purple .dk-news__k{color:#c4b0ff}
.dk-news__s b{display:block;font-family:var(--font-display);font-size:18px;position:relative;z-index:1;max-width:190px}
.dk-news__s p{color:#cfd3dd;font-size:12.5px;max-width:178px;margin:6px 0 12px;line-height:1.45;position:relative;z-index:1}
.dk-news__s .btn{position:relative;z-index:1}
.dk-news__s img.pose{position:absolute;right:-26px;bottom:-30px;height:230px}
.dk-news__s img.emb{position:absolute;right:12px;top:50%;transform:translateY(-50%);width:104px;filter:drop-shadow(0 10px 20px rgba(0,0,0,.5))}
.dk-news__s img.img{position:absolute;right:10px;top:50%;transform:translateY(-50%);width:110px;max-height:150px;object-fit:contain}
.dk-news__dots{position:absolute;left:16px;bottom:12px;display:flex;gap:5px;z-index:2}
.dk-news__dots i{width:16px;height:4px;border-radius:3px;background:rgba(255,255,255,.22);cursor:pointer;transition:width .3s,background .3s}
.dk-news__dots i.on{width:26px;background:#fff}
.dk-news__nav{position:absolute;right:10px;top:10px;display:flex;gap:6px;z-index:2;opacity:.75;transition:opacity .2s}
.dk-news:hover .dk-news__nav{opacity:1}
.dk-news__nav button{width:24px;height:24px;border-radius:50%;border:1px solid rgba(255,255,255,.18);background:rgba(0,0,0,.35);color:#fff;display:grid;place-items:center;padding:0;cursor:pointer}
.dk-news__nav button.is-prev{transform:scaleX(-1)}
.dk-news__nav .icon{width:13px;height:13px}
.dk-news__bar{position:absolute;left:0;top:0;height:2px;width:0;background:rgba(255,255,255,.45);z-index:2;transition:width .25s linear}
:root[data-theme="light"] .dk-news__s p{color:#4a5160}
:root[data-theme="light"] .dk-news__s.c-gold{background:linear-gradient(120deg,#fbf0d6,var(--panel) 75%)}
:root[data-theme="light"] .dk-news__s.c-red{background:linear-gradient(120deg,#fbe0e2,var(--panel) 75%)}
:root[data-theme="light"] .dk-news__s.c-blue{background:linear-gradient(120deg,#e0e8fb,var(--panel) 75%)}
:root[data-theme="light"] .dk-news__s.c-green{background:linear-gradient(120deg,#dcf3e5,var(--panel) 75%)}
:root[data-theme="light"] .dk-news__s.c-purple{background:linear-gradient(120deg,#ebe2fb,var(--panel) 75%)}
:root[data-theme="light"] .dk-news__k{background:rgba(0,0,0,.06);color:#8a6510}
:root[data-theme="light"] .dk-news__dots i{background:rgba(0,0,0,.15)} :root[data-theme="light"] .dk-news__dots i.on{background:#333}

/* ★ 2026-11-02 Profil page: the player's own card (same pieces as the popup card),
   a gear instead of the friend button; settings live behind it. */
.profile-card.pv-card{position:relative;max-width:none;margin:6px 16px 6px;padding:26px 18px 18px;border-radius:22px;
  background:linear-gradient(180deg,var(--panel-2),var(--panel));border:1px solid var(--border-soft);box-shadow:0 20px 44px -26px var(--shadow)}
.profile-card.pv-card.is-premium{border-color:rgba(217,168,64,.45)}
.pv-card .profile-scroll{max-height:none;overflow:visible}
.pv-card .profile-head{margin-top:6px}
.pc-sq.is-gear{background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.16);color:var(--text)}
.pc-sq.is-gear:active{transform:scale(.94)}
[data-theme="light"] .pc-sq.is-gear{background:rgba(0,0,0,.04);border-color:rgba(0,0,0,.12)}
.pv-pill{display:flex;justify-content:center;margin:12px 0 4px}
.pv-card .profile-points{display:none}

/* ★ 2026-11-02 Aged-gold picture icons (uiIcon / roleIcon in icons.js). */
.ui-ic{display:inline-block;flex:none;width:24px;height:24px;object-fit:contain;vertical-align:middle;pointer-events:none;user-select:none;
  filter:drop-shadow(0 1.5px 2px rgba(0,0,0,.45))}
:root[data-theme="light"] .ui-ic{filter:drop-shadow(0 1.5px 2px rgba(90,60,0,.25))}
.header-share-btn .ui-ic{width:31px;height:31px}
.theme-toggle img.icon-moon{display:none}
:root[data-theme="light"] .theme-toggle img.icon-sun{display:none}
:root[data-theme="light"] .theme-toggle img.icon-moon{display:inline-block}
.new-room-btn .ui-ic{width:34px;height:34px}
.scan-btn .ui-ic{width:34px;height:34px}
.quickjoin .ui-ic{width:30px;height:30px;margin:-4px 0}
.dm-new .ui-ic{width:26px;height:26px;margin:-3px 0}
.dk-navb .ui-ic{width:22px;height:22px}
.dk-iconb .ui-ic{width:26px;height:26px}
.pc-sq.is-gear .ui-ic{width:30px;height:30px}
.header-icon-btn .ui-ic{width:22px;height:22px}
.rchip .ui-ic{width:19px;height:19px;filter:drop-shadow(0 1px 1px rgba(0,0,0,.45))}
.rchip.rc-sum .ui-ic{width:20px;height:20px}
body.desk .rchip .ui-ic{width:23px;height:23px}
/* ★ 2026-11-02 Watchers get the role-count pills in the spectate bar. */
.spec-roster{flex:1 1 auto;min-width:0;display:flex;align-items:center;overflow-x:auto;scrollbar-width:none}
.spec-roster::-webkit-scrollbar{display:none}
.spec-roster .rb-chips{display:flex;gap:6px;align-items:center}
/* ★ 2026-11-02 Gold role icons on the cards, role header, stats, history, "Yangi rollar". */
.ui-ic.ri-card{width:100px;height:100px;filter:drop-shadow(0 6px 14px rgba(0,0,0,.5))}
.ui-ic.ri-xl{width:92px;height:92px;margin:0 auto 6px;display:block;filter:drop-shadow(0 8px 18px rgba(0,0,0,.5))}
.ui-ic.ri-face{width:34px;height:34px}
.ui-ic.ri-md{width:26px;height:26px}
.ui-ic.ri-sm{width:22px;height:22px}
/* ★ 2026-11-02 uiIcon() in place of the old line icons: the old size classes still size it. */
.ui-ic.icon-xs{width:15px;height:15px}
.ui-ic.icon-sm{width:19px;height:19px}
.ui-ic.icon-md{width:24px;height:24px}
.ui-ic.icon-lg{width:44px;height:44px}
.ui-ic.icon-xl{width:56px;height:56px}
.ui-ic.popup-icon{width:76px;height:76px;margin:0 auto 10px;display:block}
.section-title .ui-ic{width:20px;height:20px;margin:-2px 0}
.lbx-seg button .ui-ic{width:22px;height:22px}
.pgrid .pg[data-profile]{cursor:pointer}.pgrid .pg[data-profile]:active{transform:scale(.96)}
.profile-card .stat-streak{display:block;text-align:center;font-size:13.5px;line-height:1.4;margin:10px 16px 0;padding:9px 12px}.profile-card .stat-streak b{display:inline}
/* ★ 2026-11-02 Desktop night: where to pick, and who is picked */
.dk-pick-hint{display:flex;align-items:center;justify-content:center;gap:8px;margin:14px 16px 4px;padding:11px 14px;border-radius:14px;
  border:1px dashed rgba(124,140,255,.45);background:rgba(79,124,255,.08);color:#c9d3ff;font-weight:700;font-size:14px}
.dk-pick-hint .icon{transform:scaleX(-1);animation:dkNudge 1.4s ease-in-out infinite}
@keyframes dkNudge{50%{transform:scaleX(-1) translateX(5px)}}
.dk-pick-hint.is-picked{border-style:solid;border-color:rgba(34,197,94,.5);background:rgba(34,197,94,.1);color:#bdf5d3}
.dk-pick-hint.is-picked .icon{transform:none;animation:none}
:root[data-theme="light"] .dk-pick-hint{color:#3446a8}:root[data-theme="light"] .dk-pick-hint.is-picked{color:#11743c}
.dk-pick-hint .dk-arr{font-style:normal;font-size:18px;line-height:1;animation:dkNudge2 1.4s ease-in-out infinite}
@keyframes dkNudge2{50%{transform:translateX(-5px)}}
/* ★ 2026-11-02 the admin's message on the ban screen */
.ban-note{margin:14px auto 0;width:100%;max-width:320px;box-sizing:border-box;text-align:left;padding:12px 14px;border-radius:14px;background:rgba(229,72,77,.08);border:1px solid rgba(229,72,77,.32)}
.ban-note__k{display:flex;align-items:center;gap:6px;font-size:11.5px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:#ff9a9d;margin-bottom:6px}
.ban-note__t{font-size:14.5px;line-height:1.45;white-space:pre-wrap;word-break:break-word}
:root[data-theme="light"] .ban-note__k{color:#c22a30}
/* ★ 2026-11-02 Ovul members: points brought in the last 7 days */
.ovm-pts{margin-left:auto;display:inline-flex;align-items:center;gap:4px;flex:none;font:800 13px var(--font-display,inherit);padding:4px 9px;border-radius:99px;
  background:rgba(34,197,94,.12);border:1px solid rgba(34,197,94,.35);color:#4ade80;margin-right:6px}
.ovm-pts.is-zero{background:rgba(255,255,255,.04);border-color:var(--border-soft);color:var(--text-dim)}
.ovm-pts .ui-ic{width:15px;height:15px}
:root[data-theme="light"] .ovm-pts{color:#15803d}
.chat.is-under-qassob{min-height:110px}
/* ★ 2026-11-02 Desktop night (approved): the centre split in two — actions | chat or night sky */
body.desk .dk-split{flex:1;min-height:0;display:grid;grid-template-columns:minmax(0,38fr) minmax(0,62fr);gap:14px;margin:6px 16px 12px}
body.desk .scroll-page > .dk-split{min-height:calc(100% - 12px)}
body.desk .dk-split__l{display:flex;flex-direction:column;gap:10px;min-height:0;overflow-y:auto}
body.desk .dk-split__l > *{margin:0!important}
body.desk .dk-split__l > .action-panel{padding:12px 14px}
body.desk .dk-split__l > .action-panel h3{font-size:15px}
body.desk .dk-split__l > .action-panel p{font-size:12.5px;line-height:1.45;margin-top:6px}
body.desk .dk-split.has-chat .dk-split__l > .action-panel p{display:none}
body.desk .dk-split__l .dk-pick-hint{padding:12px}
body.desk .dk-split__l > .btn-row,body.desk .dk-split__l > .confirm-row{display:flex;gap:8px;padding:0}
body.desk .dk-split__l > .btn-row .btn,body.desk .dk-split__l > .confirm-row .btn.block{min-height:48px;flex:1}
body.desk .dk-split__l > .btn-row--stack{flex-direction:column}
body.desk .dk-split__l > .investigations{padding:12px 14px}
body.desk .dk-split__l > .investigations h3{font-size:14px;margin:0 0 6px}
body.desk .dk-split > .mafia-chat-panel{margin:0!important;min-height:0;display:flex;flex-direction:column}
body.desk .dk-split > .mafia-chat-panel .chat-messages{flex:1;min-height:0}
body.desk .dk-split__r{position:relative;margin:0;border-radius:18px;overflow:hidden;border:1px solid rgba(255,255,255,.06);background:linear-gradient(180deg,#0b1430,#060a18);min-height:480px}
/* ★ 2026-11-02 final words: the mic opened by itself */
.fw-micnote{display:flex;align-items:center;justify-content:center;gap:7px;margin:10px 0;padding:9px 12px;border-radius:12px;background:rgba(34,197,94,.12);border:1px solid rgba(34,197,94,.45);color:#86efac;font-weight:800;font-size:13.5px;line-height:1.3}
.fw-micnote.is-bar{margin:8px 12px}
:root[data-theme="light"] .fw-micnote{color:#15803d}
.vr-mic.is-fw{background:#22c55e!important;color:#06210f!important;animation:fwPulse 1.3s infinite}
@keyframes fwPulse{0%{box-shadow:0 0 0 0 rgba(34,197,94,.6)}70%{box-shadow:0 0 0 16px rgba(34,197,94,0)}100%{box-shadow:0 0 0 0 rgba(34,197,94,0)}}
/* ★ 2026-11-02 Voice emotes */
.vr-btn.vr-emo{position:relative;padding:7px}
.vr-btn.vr-emo img{width:100%;height:100%;object-fit:contain;display:block}
.vr-btn.vr-emo.on{background:rgba(232,185,90,.18);border-color:rgba(232,185,90,.6)}
.vr-btn.vr-emo .cd{position:absolute;inset:0;border-radius:50%;background:conic-gradient(rgba(0,0,0,.6) var(--a,0deg),transparent 0);pointer-events:none}
.emo-pick{position:fixed;right:12px;bottom:118px;width:min(300px,calc(100vw - 24px));padding:12px;border-radius:20px;background:var(--panel-2);border:1px solid var(--border-soft);
  box-shadow:0 20px 50px -10px rgba(0,0,0,.6);transform-origin:90% 100%;transform:scale(.6);opacity:0;pointer-events:none;transition:transform .22s cubic-bezier(.2,.9,.3,1.3),opacity .18s;z-index:80}
.emo-pick.open{transform:none;opacity:1;pointer-events:auto}
.emo-pick__h{display:flex;align-items:center;gap:6px;font-size:11px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;color:var(--text-dim);margin:10px 2px 6px}
.emo-pick__h:first-child{margin-top:0}
.emo-pick__row{display:grid;grid-template-columns:repeat(4,1fr);gap:6px}
.emo-pick button{background:none;border:0;padding:6px;border-radius:12px;cursor:pointer;transition:transform .12s,background .12s}
.emo-pick button:hover{background:rgba(255,255,255,.07)}.emo-pick button:active{transform:scale(.88)}
.emo-pick button img{width:100%;display:block}
.emo-pick.is-free .is-pro button{opacity:.35;filter:grayscale(.6)}
body.desk .emo-pick{right:auto;left:50%;bottom:110px;transform-origin:50% 100%;margin-left:40px}
.vt-emo{position:fixed;z-index:70;pointer-events:none;filter:drop-shadow(0 6px 14px rgba(0,0,0,.55));animation:vtEmo 1.9s cubic-bezier(.2,.9,.3,1.2) forwards}
@keyframes vtEmo{0%{transform:scale(.2) rotate(-12deg);opacity:0}14%{transform:scale(1.18) rotate(4deg);opacity:1}26%{transform:scale(1) rotate(0)}78%{transform:scale(1);opacity:1}100%{transform:scale(1.1) translateY(-14px);opacity:0}}
/* ★ 2026-11-02 the 1 / 2 tab keys as real key boxes */
.dm-tabkeys{display:inline-flex;align-items:center;gap:5px}
.dm-tabkeys kbd{font-family:inherit;font-size:11px;font-weight:700;line-height:1;min-width:20px;text-align:center;padding:4px 6px;border-radius:6px;border:1px solid var(--border);border-bottom-width:2px;background:var(--panel);color:var(--text)}
/* ★ 2026-11-02 spectator: the headphone count in green, on the right */
.vr-chip.is-me-watch{background:rgba(34,197,94,.14);border-color:rgba(34,197,94,.5);color:#4ade80}
.vr-chip.is-me-watch .icon{color:#4ade80}
:root[data-theme="light"] .vr-chip.is-me-watch{color:#15803d}:root[data-theme="light"] .vr-chip.is-me-watch .icon{color:#15803d}
body.desk .vr-roster,body.desk .rb-chips,body.desk .spec-roster{cursor:grab}
/* ★ 2026-10-10 profile: free voice games left (non-Pro only) */
.vpass { display: flex; align-items: center; gap: 10px; width: calc(100% - 32px); margin: 14px 16px 0; padding: 9px 14px; text-align: left; font: inherit; font-weight: 600; color: var(--text); cursor: default; }
.vpass__t { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vpass__ic { width: 30px; height: 30px; flex: none; border-radius: 9px; display: grid; place-items: center; background: rgba(47,168,102,.14); }
.vpass__ic img, .vpass__ic svg { width: 20px; height: 20px; }
.vpass__n { flex: none; white-space: nowrap; padding: 4px 10px; border-radius: 99px; font-weight: 800; font-size: 14px; color: #1f8f52; background: rgba(47,168,102,.13); }
.vpass.is-out { cursor: pointer; }
.vpass.is-out .vpass__ic { background: rgba(224,106,106,.14); }
.vpass.is-out .vpass__n { color: #c93d3d; background: rgba(224,106,106,.13); }
.vpass__chev { flex: none; display: flex; opacity: .55; }

/* ★ 2026-10-10 Lobby: Start + Taklif yuborish side by side (Ali) */
.lobby-actions.is-split { display: flex; gap: 8px; }
.lobby-actions.is-split > * { flex: 1 1 0; min-width: 0; padding-left: 8px; padding-right: 8px; white-space: nowrap; }
.lobby-actions.is-split .locked-note { white-space: normal; font-size: 12px; display: flex; align-items: center; justify-content: center; text-align: center; }
/* ★ 2026-10-10 The quit ✕ always sits on the LEFT end of its row (Ali) */
.quit-x { margin-right: auto; }

/* ★ 2026-10-10 Post-game debrief (Ali): "Chiqish" in the header, roles folded into a pill */
.pg-sub { position: relative; }
.pg-exit { position: absolute; left: 0; top: 50%; transform: translateY(-50%); display: inline-flex; align-items: center; gap: 4px;
  height: 28px; padding: 0 11px 0 8px; border-radius: 999px; border: 1px solid var(--border-soft); background: var(--panel-2);
  color: var(--text); font: inherit; font-size: 12.5px; font-weight: 700; cursor: pointer; }
.pg-exit .icon { width: 13px; height: 13px; color: var(--text-dim); }
.postgame-roles .pr-bar { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: 10px 14px 0; }
.pr-pill { display: inline-flex; align-items: center; gap: 6px; height: 34px; padding: 0 12px; border-radius: 999px;
  border: 1px solid var(--border-soft); background: var(--panel-2); color: var(--text); font: inherit; font-size: 13px; font-weight: 800;
  letter-spacing: .02em; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.pr-pill .icon { width: 14px; height: 14px; color: var(--text-dim); }
.pr-pill .pr-chev { transition: transform .2s; }
.postgame-roles.is-open .pr-pill .pr-chev { transform: rotate(90deg); }
.postgame-roles .pr-grid { animation: pgIn .18s ease-out; }
.postgame-roles .pr-grid[hidden] { display: none; }
/* ★ 2026-10-10 Kuzatuvchi pill + slimmer "Yangi o'yinga o'tish" strip (Ali) */
.rchip.spec-me { background: rgba(214, 58, 58, .12); border-color: rgba(214, 58, 58, .45); color: #ff8a8a; }
.rchip.spec-me .icon { color: #ff8a8a; }
.banner-row > .rchip.spec-me { display: inline-flex; align-items: center; gap: 4px; height: 30px; padding: 0 10px; border-radius: 999px; border: 1px solid rgba(214,58,58,.45); font-size: 12.5px; margin-right: auto; }
.dead-actions { padding: 8px 14px calc(10px + var(--safe-bottom, 0px)); }
.dead-actions .btn { min-height: 44px; }
.postgame-roles .pr-grid { margin-top: 8px; }
/* ★ 2026-10-10 Roster grid: a framed avatar had no size here, so .avf (whose children are all
   absolutely positioned) collapsed to 0×0 and the photo AND frame vanished (Ali's bug report). */
.pg .avf { width: 36px; height: 36px; display: block; margin: 0 auto; }
.pg.is-dead .avf { opacity: .45; filter: grayscale(1); }
/* ★ 2026-10-10 Qassob: pick confirmed → locked */
.qassob-grid.is-locked .qassob-pick:not(.is-on) { opacity: .35; }
.qassob-done { display: flex; align-items: center; justify-content: center; gap: 6px; height: 44px; border-radius: 12px;
  background: rgba(192, 38, 45, .16); border: 1px solid rgba(192, 38, 45, .5); color: #ff9a9a; font-weight: 800; }

/* ★ 2026-10-10 Announcement cards in chat rooms too + result cards (approved mockup) */
.ann-back.is-doc { background: linear-gradient(180deg,#10283a,#0b1824); border-color: rgba(56,189,248,.55); }
.ann-back.is-doc .ann-text b { color: #7dd3fc; }
.ann-back.is-doc .ann-facewrap > img, .ann-back.is-doc .ann-facewrap > .avf > img:first-child { filter: grayscale(.7) brightness(.8); }
.ann-front.is-mic { background: linear-gradient(180deg,#121a30,#0c1222); border-color: rgba(99,140,255,.5); }
.ann-front.is-mic .ann-text b { color: #9db8ff; }
.ann-front.is-mic .ann-facewrap > img, .ann-front.is-mic .ann-facewrap > .avf > img:first-child { filter: none; }
.ann-ov.is-result .ann-front { padding-top: 30px; }
.ann-ov.is-result.is-heal .ann-front { background: linear-gradient(180deg,#0f2219,#0b1611); border-color: rgba(34,197,94,.55); }
.ann-ov.is-result.is-calm .ann-front { background: radial-gradient(120% 90% at 50% 0%,#2b2f6b 0%,#121534 55%,#0a0c1f 100%); border-color: rgba(129,140,248,.45); }
.ann-rtitle { font-size: 26px; }

/* ★ 2026-11-03 Kirish talabi (approved mockup) */
.mg-box { margin-top: 10px; border-radius: 14px; background: var(--panel-2); border: 1px solid var(--border-soft); }
.mg-box[hidden] { display: none; }
.mg-box > .switch-row { margin: 0; border: 0; background: none; }
.mg-sub { padding: 0 12px 12px; }
.mg-sub[hidden] { display: none; }
.mg-chips { display: flex; gap: 6px; }
.mg-chips button { flex: 1 1 0; min-width: 0; height: 36px; border-radius: 10px; border: 1px solid var(--border-soft); background: var(--panel);
  color: var(--text); font: inherit; font-weight: 700; font-size: 13.5px; cursor: pointer; }
.mg-chips button.is-on { background: var(--accent, #4f6cf0); border-color: transparent; color: #fff; }
.mg-sub .visibility-hint { margin: 8px 2px 0; }
.mg-chip { display: inline-flex; align-items: center; gap: 3px; height: 20px; padding: 0 7px; border-radius: 999px; margin-right: 4px; vertical-align: middle;
  background: rgba(217,168,64,.16); border: 1px solid rgba(217,168,64,.5); color: #c99a2e; font-size: 11px; font-weight: 800; }
:root[data-theme="dark"] .mg-chip { color: #f0c86a; }
.mg-chip.is-no { background: rgba(214,58,58,.14); border-color: rgba(214,58,58,.5); color: #d63a3a; }
:root[data-theme="dark"] .mg-chip.is-no { color: #ff8a8a; }
.mg-need { margin: 0 16px; padding: 10px 12px; border-radius: 12px; background: rgba(214,58,58,.12); border: 1px solid rgba(214,58,58,.45);
  color: #c0262d; font-size: 13px; font-weight: 600; text-align: center; line-height: 1.45; }
:root[data-theme="dark"] .mg-need { color: #ffb0b0; }

/* ★ 2026-10-10 Chat watcher: votes per player during the vote, night scene at night */
.player-cell { position: relative; }
.spec-votes { position: absolute; top: 3px; right: 3px; z-index: 3; min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px;
  background: #d63a3a; color: #fff; font-size: 12px; font-weight: 800; line-height: 20px; text-align: center; box-shadow: 0 2px 6px rgba(214,58,58,.35); }
.spec-night { flex: 1 1 auto; min-height: 0; }

/* ★ 2026-10-11 Lobby "Taklif yuborish" menu */
.invite-opts { display:flex; flex-direction:column; gap:8px; margin-top:12px; text-align:left; }
.invite-opt { display:flex; align-items:center; gap:12px; width:100%; padding:12px 14px; border-radius:14px;
  border:1px solid var(--border, rgba(255,255,255,.12)); background:var(--surface-2, rgba(255,255,255,.04)); color:inherit; font:inherit; cursor:pointer; }
.invite-opt:disabled { opacity:.5; cursor:default; }
.invite-opt__ic { width:38px; height:38px; flex:0 0 38px; border-radius:50%; display:grid; place-items:center; background:rgba(90,130,255,.15); }
.invite-opt__tx { display:flex; flex-direction:column; gap:2px; min-width:0; }
.invite-opt__tx small { opacity:.65; font-size:12.5px; }
.invite-opt.is-gold { border-color:rgba(232,180,60,.55); }
.invite-opt.is-gold .invite-opt__ic { background:rgba(232,180,60,.15); }
.invite-opt.is-gold b { color:#f0c24b; }
.invite-opt { justify-content:flex-start; text-align:left; }
.invite-opt__tx { align-items:flex-start; text-align:left; }

/* ★ 2026-10-11 Kirish talabi: PRO */
.mg-chips button.mg-pro { color:#f0c24b; border-color:rgba(232,180,60,.5); font-weight:700; }
.mg-chips button.mg-pro.is-on { background:linear-gradient(135deg,#f0c24b,#c9922a); color:#1a1408; border-color:transparent; }
.mg-chip.is-pro { color:#f0c24b; }

/* ★ 2026-10-11 Profile card: only the stats area may shrink (and scroll). The Ovul block,
   bio and buttons keep their full height — before, a tall card squeezed the Ovul block
   until its text was cut off (Ali). */
.popup-card.profile-card > *:not(.profile-scroll) { flex-shrink: 0; }
.popup-card.profile-card .pc-ovul { min-height: 74px; }

/* ★ 2026-10-11 Desktop: banner block above the weekly leaderboard, 3.5:1 like the images */
.dk-ads { margin-bottom: 14px; border-radius: 16px; overflow: hidden; border: 1px solid var(--border-soft, rgba(255,255,255,.08));
  background: var(--panel, #1b2130); }
.dk-ads .adc { max-width: none; margin: 0; }
.dk-ads .adc__vp { height: auto; aspect-ratio: 3.5 / 1; border-radius: 0; }
.dk-ads .adc__img { width: 100%; height: 100%; object-fit: cover; display: block; border-radius: 0; box-shadow: none; }

/* ★ 2026-10-12 🚫 on blocked players' tiles */
.player-cell.is-blocked { position: relative; }
.player-cell .blk-badge { position: absolute; top: 4px; right: 4px; font-size: 13px; line-height: 1; }
.vt__ava .blk-badge { position: absolute; top: -2px; right: -2px; font-size: 14px; line-height: 1; z-index: 2; }

/* ★ 2026-10-12 O'yinchini izlash */
.ps-bar { display: flex; align-items: center; gap: 10px; padding: 12px 14px; margin: 6px 0 14px; border-radius: 14px;
  background: var(--panel, #1b2130); border: 1px solid var(--border-soft, rgba(255,255,255,.1)); }
.ps-bar:focus-within { border-color: var(--accent, #4f6cf0); }
.ps-in { flex: 1; min-width: 0; background: none; border: 0; color: inherit; font: inherit; font-size: 16px; outline: none; }
.ps-in::-webkit-search-cancel-button { filter: invert(.6); }
.ps-hint { font-size: 12px; padding: 3px 8px; border-radius: 8px; background: rgba(255,255,255,.07); opacity: .7; }
.profile-uid { order: 2; font-size: 11.5px; color: var(--text-dim, #8e97a8); letter-spacing: .03em; margin-top: 2px; user-select: all; }
.profile-id { display: flex; flex-direction: column; }
.profile-id .profile-name { order: 1; }

/* ★ 2026-10-12 "Keep screen on" in the voice bar (players and spectators) */
.vr-btn.vr-wake { opacity: .6; }
.vr-btn.vr-wake.is-on { opacity: 1; color: #f0c24b; box-shadow: inset 0 0 0 2px rgba(240,194,75,.55); }

/* ★ 2026-10-12 With the keep-screen-on button the bar can hold 6 buttons (Rais + emote):
   never squash them into ovals — they stay round and get a little smaller instead. */
.vr-btn { flex: 0 0 auto; }
.vr-bar:has(.vr-rais):has(.vr-emo) .vr-btn:not(.vr-mic) { width: 44px; height: 44px; }
.vr-bar:has(.vr-rais):has(.vr-emo) .vr-mic { width: 56px; height: 56px; }
.vr-bar:has(.vr-rais):has(.vr-emo) { gap: 8px; }

/* ★ 2026-10-12 End-of-game celebration (winFx) */
.winfx { position: fixed; inset: 0; z-index: 9000; pointer-events: none; transition: opacity .2s linear; }
.winfx canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.winfx__glow { position: absolute; inset: 0; opacity: 0; animation: winfxGlow 3.6s ease-out forwards; }
.winfx.is-town .winfx__glow { background: radial-gradient(60% 40% at 50% 30%, rgba(240,194,75,.35), transparent 70%); }
.winfx.is-mafia .winfx__glow { background: radial-gradient(70% 60% at 50% 45%, transparent 40%, rgba(120,0,10,.75) 100%); }
@keyframes winfxGlow { 0% { opacity: 0 } 15% { opacity: 1 } 100% { opacity: .35 } }
.winfx__ban { position: absolute; left: 50%; top: 42%; transform: translate(-50%,-50%) scale(1.8); opacity: 0; white-space: nowrap;
  text-align: center; line-height: .92; font-family: var(--font-display, inherit); font-weight: 900; }
.winfx__ban b { display: block; font-size: clamp(46px, 17vw, 86px); letter-spacing: .04em; -webkit-text-stroke: 2px rgba(0,0,0,.45);
  text-shadow: 0 6px 0 rgba(0,0,0,.45), 0 0 40px currentColor; }
.winfx__ban span { display: block; margin-top: 8px; font-size: clamp(17px, 6.2vw, 30px); letter-spacing: .08em; color: #fff;
  text-shadow: 0 3px 14px #000; opacity: 0; }
.winfx__ban i { display: block; height: 3px; margin: 10px auto 0; width: 0; background: linear-gradient(90deg, transparent, currentColor, transparent); }
.winfx__ban::before { content: ""; position: absolute; inset: -34px -48px; z-index: -1;
  background: radial-gradient(closest-side, rgba(0,0,0,.62), rgba(0,0,0,.25) 70%, transparent); }
.winfx.is-town .winfx__ban { color: #f0c24b; }
.winfx.is-mafia .winfx__ban { color: #ff3b47; }
/* fly in big + blurred → slam (slightly under size) → settle; hold; fade with the overlay */
.winfx.show-ban .winfx__ban { animation: winfxSlam 3.6s cubic-bezier(.3,1.25,.4,1) forwards; }
.winfx.show-ban .winfx__ban span { animation: winfxSub 3.4s ease-out .32s forwards; }
.winfx.show-ban .winfx__ban i { animation: winfxLine .5s ease-out .4s forwards; }
@keyframes winfxSlam {
  0% { opacity: 0; transform: translate(-50%,-50%) scale(1.8); filter: blur(6px) }
  9% { opacity: 1; transform: translate(-50%,-50%) scale(.92) rotate(-2deg); filter: blur(0) }
  15% { transform: translate(-50%,-50%) scale(1.03) rotate(0) }
  20%, 88% { opacity: 1; transform: translate(-50%,-50%) scale(1) }
  100% { opacity: 0; transform: translate(-50%,-56%) scale(1) } }
@keyframes winfxSub { 0% { opacity: 0; transform: translateY(8px) } 12%, 86% { opacity: 1; transform: none } 100% { opacity: 0 } }
@keyframes winfxLine { to { width: 92% } }
.winfx__flash { position: absolute; inset: 0; opacity: 0; }
.winfx.is-mafia .winfx__flash { background: radial-gradient(55% 25% at 50% 42%, rgba(255,60,60,.55), transparent 70%); }
.winfx.is-town .winfx__flash { background: radial-gradient(55% 25% at 50% 42%, rgba(255,215,110,.55), transparent 70%); }
.winfx.is-hit .winfx__flash { animation: winfxFlash .7s ease-out forwards; }
@keyframes winfxFlash { 0% { opacity: 0 } 20% { opacity: 1 } 100% { opacity: 0 } }

/* ★ 2026-10-13 Xonaga kirish sheet (QR / code) */
.js-or { display: flex; align-items: center; gap: 10px; margin: 12px 0; color: var(--text-dim); font-size: 12px; }
.js-or::before, .js-or::after { content: ""; flex: 1; height: 1px; background: var(--border); }
.js-code { display: flex; flex-direction: column; gap: 8px; text-align: left; margin-top: 4px; }
.js-code label { font-weight: 700; }
.js-code__row { display: flex; gap: 8px; }
.js-code__in { flex: 1; min-width: 0; height: 52px; border-radius: 14px; border: 1px solid var(--border); background: var(--panel-2, var(--panel));
  color: var(--text); font: 800 24px/1 ui-monospace, "SF Mono", Menlo, monospace; letter-spacing: .5em; text-align: center; text-transform: uppercase; padding-left: .5em; }
.js-code__in:focus { outline: none; border-color: var(--accent, #4f6cf0); }
.js-code__row .btn { flex: 0 0 auto; height: 52px; padding: 0 20px; margin: 0; align-self: stretch; }
.js-code__hint { color: var(--text-dim); font-size: 12px; }
.dm-code { flex: 0 0 auto; height: 64px; padding: 0 22px; font-size: 18px; border-radius: 16px; white-space: nowrap; gap: 8px; }
.dm-code .ui-ic { width: 26px; height: 26px; margin: -3px 0; }

/* ★ 2026-11-06 Voice-game replay (cpanel → Ovozli yozuvlar): role chips of the god view,
   and none of a live player's controls. */
.vt__rprole{padding:1px 8px;border-radius:8px;font:800 10px/16px Inter,system-ui,sans-serif;letter-spacing:.04em;text-transform:uppercase;white-space:nowrap;background:#1f2433;color:#9aa3b5;border:1px solid #2a3142}
.vt__rprole.is-mafia{background:#3a1216;color:#ff8a8a;border-color:rgba(239,68,68,.5)}
.vt__rprole.is-doc{background:#0f2e1c;color:#6ee7a0;border-color:rgba(34,197,94,.45)}
.vt__rprole.is-det{background:#10233f;color:#7cb4ff;border-color:rgba(59,130,246,.5)}
.vt__rprole.is-rais{background:#33270b;color:#f5d585;border-color:rgba(217,168,64,.5)}
.vt__aim.is-check{color:#60a5fa}
.vt__aim.is-shot{color:#60a5fa}
.is-vreplay .vr-bar,.is-vreplay #vbar,.is-vreplay .is-me-watch,.is-vreplay .vr-log,.is-vreplay #toast,.is-vreplay .toast{display:none!important}
.is-vreplay.vr-hidenames .vt__name,.is-vreplay.vr-hidenames .vr-cap b{filter:blur(6px)}
