:root{
  --bg:#0d0b09; --panel:#16120e; --panel-edge:#2a2016;
  --parchment:#e9dfc7; --parchment-dim:#b8ab8c;
  --ember:#c0392b; --ember-bright:#e0654f;
  --violet:#7d4fb5; --violet-bright:#a97ee0;
  --gold:#c9a13b;
  --necropolis-gray:#8a8a8a;
}
*{box-sizing:border-box;}
html,body{margin:0;padding:0;}
body{
  background: radial-gradient(ellipse at 50% 10%, #1a140f 0%, #0d0b09 60%);
  color: var(--parchment);
  font-family:'Spectral', Georgia, serif;
  min-height:100vh;
}
h1,h2,h3,.brand{ font-family:'Cinzel','Times New Roman',serif; letter-spacing:0.04em; }

.topbar{
  display:flex; align-items:center; justify-content:space-between;
  padding:14px 24px; border-bottom:1px solid var(--panel-edge);
  background: linear-gradient(180deg,#171208,#0d0b09);
  flex-wrap:wrap; row-gap:8px; column-gap:14px;
}
.brand{ color:var(--parchment); text-decoration:none; font-size:18px; font-weight:900; white-space:nowrap; }
.topnav{ display:flex; align-items:center; gap:14px; font-size:13px; flex-wrap:wrap; row-gap:6px; }
.topnav a{ color:var(--gold); text-decoration:none; white-space:nowrap; }
.topnav a:hover{ text-decoration:underline; }
.topnav a.return-battle{
  color:#fff; background:linear-gradient(180deg,var(--ember-bright),var(--ember));
  padding:4px 10px; border-radius:5px; font-weight:700;
}
.topnav a.return-battle:hover{ text-decoration:none; filter:brightness(1.1); }

/* Appears top-left once a battle ends (see game.js: socket.on('game_over'))
   with the same look as .return-battle above — needed because the mobile
   fullscreen battle screen (#game-root, see @media max-width:640px below)
   visually covers the topbar nav, so the ordinary "В лобби" link isn't
   reachable there until the page is reloaded. */
.post-game-lobby-link{
  position:fixed; top:10px; left:10px; z-index:40;
  color:#fff; background:linear-gradient(180deg,var(--ember-bright),var(--ember));
  padding:6px 12px; border-radius:5px; font-weight:700; font-family:'Cinzel',serif;
  font-size:13px; text-decoration:none; box-shadow:0 2px 8px rgba(0,0,0,0.45);
}
.post-game-lobby-link:hover{ text-decoration:none; filter:brightness(1.1); }
.post-game-lobby-link.hidden{ display:none; }

@media (max-width: 520px){
  .topbar{ padding:10px 14px; }
  .brand{ font-size:15px; }
  .topnav{ width:100%; gap:12px; font-size:12.5px; }
}

.page{ max-width:920px; margin:0 auto; padding:28px 18px 60px; }

.flash-box{ margin-bottom:16px; }
.flash{ padding:9px 14px; border-radius:6px; margin-bottom:8px; font-size:13.5px; }
.flash-error{ background: rgba(192,57,43,0.15); border:1px solid var(--ember); color:var(--ember-bright); }
.flash-ok{ background: rgba(76,175,80,0.12); border:1px solid #4caf50; color:#8fe19a; }

.card{
  background: linear-gradient(180deg, var(--panel), #100d0a);
  border:1px solid var(--panel-edge); border-radius:8px; padding:22px;
}
.card + .card{ margin-top:16px; }

label{ display:block; font-size:12.5px; color:var(--parchment-dim); margin:12px 0 4px; }
input[type=text], input[type=password]{
  width:100%; padding:10px 12px; border-radius:5px; border:1px solid var(--panel-edge);
  background:#100d0a; color:var(--parchment); font-family:'Spectral',serif; font-size:14px;
}
input:focus{ outline:none; border-color:var(--gold); }

button, .btn{
  font-family:'Cinzel',serif; font-size:13px; letter-spacing:0.04em;
  background:linear-gradient(180deg,#2a2016,#17130d); border:1px solid var(--panel-edge);
  color:var(--parchment); padding:10px 18px; border-radius:5px; cursor:pointer;
  text-decoration:none; display:inline-block;
}
button:hover, .btn:hover{ border-color:var(--gold); color:#fff; }
button.primary, .btn.primary{ border-color:var(--gold); color:#fff; background:linear-gradient(180deg,#3a2c15,#1a140b); }
button:disabled{ opacity:0.4; cursor:not-allowed; }

.radio-toggle-row{ display:flex; align-items:center; gap:8px; margin:12px 0 4px; font-size:14px; color:var(--parchment); }
.radio-toggle-row input[type=checkbox]{ width:16px; height:16px; accent-color:var(--gold); }
input[type=range]{ width:100%; margin:6px 0 4px; accent-color:var(--gold); }

.form-actions{ margin-top:18px; display:flex; gap:10px; align-items:center; }
.form-actions.footer-actions{ margin-top:24px; padding-top:16px; border-top:1px solid var(--panel-edge); justify-content:center; }
.hint{ font-size:12.5px; color:var(--parchment-dim); margin-top:14px; }
.hint a{ color:var(--gold); }

table.rooms{ width:100%; border-collapse:collapse; margin-top:10px; table-layout:fixed; }
table.rooms th, table.rooms td{ text-align:left; padding:9px 6px; border-bottom:1px solid var(--panel-edge); font-size:13.5px; }
table.rooms th{ color:var(--parchment-dim); font-weight:normal; text-transform:uppercase; font-size:11px; letter-spacing:0.05em; }
.room-name-cell{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
table.rooms td:nth-child(3), table.rooms td:nth-child(4){ text-align:center; }
table.rooms td .btn{ padding:6px 10px; font-size:11px; }
table.rooms th:nth-child(1), table.rooms td:nth-child(1){ width:30%; }
table.rooms th:nth-child(2), table.rooms td:nth-child(2){ width:24%; }
table.rooms th:nth-child(3), table.rooms td:nth-child(3){ width:15%; }
table.rooms th:nth-child(4), table.rooms td:nth-child(4){ width:14%; }
table.rooms th:nth-child(5), table.rooms td:nth-child(5){ width:17%; }
.status-tag{ font-size:10.5px; padding:2px 8px; border-radius:10px; text-transform:uppercase; letter-spacing:0.04em; }
.status-waiting{ background:rgba(201,161,59,0.15); color:var(--gold); }
.status-drafting{ background:rgba(224,101,79,0.15); color:var(--ember-bright); }
.status-playing{ background:rgba(125,79,181,0.18); color:var(--violet-bright); }
.status-finished{ background:rgba(255,255,255,0.06); color:var(--parchment-dim); }
table.rooms td form{ margin:0; display:inline; }
table.rooms td button{ padding:6px 10px; font-size:11px; }

/* Список игроков (/admin/players) — 6 колонок, свой набор ширин поверх
   общих table.rooms nth-child правил выше (те настроены под лобби, 5 колонок). */
table.admin-players-table th:nth-child(1), table.admin-players-table td:nth-child(1){ width:34px; }
table.admin-players-table th:nth-child(2), table.admin-players-table td:nth-child(2){ width:auto; }
table.admin-players-table th:nth-child(3), table.admin-players-table td:nth-child(3),
table.admin-players-table th:nth-child(4), table.admin-players-table td:nth-child(4){ width:8%; text-align:center; }
table.admin-players-table th:nth-child(5), table.admin-players-table td:nth-child(5){ width:14%; }
table.admin-players-table th:nth-child(6), table.admin-players-table td:nth-child(6){ width:76px; }

/* Рейтинг (/rating) — 8-9 колонок, свой набор ширин поверх общих table.rooms
   nth-child правил выше (те настроены под лобби, 5 колонок) — иначе колонки
   6-8 (Игр/Фракция/Юнит) остаются без ширины вообще (первые 5 уже забирают
   100% при table-layout:fixed), из-за чего их текст сжимается и накладывается
   друг на друга, особенно на мобильном.
   ⚠️ Все 8 колонок заданы В ПРОЦЕНТАХ (сумма ровно 100%), НЕ пикселями и не
   auto — смешивание px/auto с % тут само по себе вызывало ту же болезнь:
   на узком экране auto-колонка "Ник" схлопывалась почти до 0 и наезжала на
   "Win%", т.к. фиксированные px-колонки при table-layout:fixed отъедают своё
   ДО того, как auto-колонка получает остаток. Чистые проценты не зависят от
   ширины вьюпорта, поэтому отдельный @media-блок под мобильный не нужен. */
table.leaderboard-table th:nth-child(1), table.leaderboard-table td:nth-child(1){ width:5%; text-align:center; }
table.leaderboard-table th:nth-child(2), table.leaderboard-table td:nth-child(2){ width:15%; }
table.leaderboard-table th:nth-child(3), table.leaderboard-table td:nth-child(3){ width:14%; text-align:center; }
table.leaderboard-table th:nth-child(4), table.leaderboard-table td:nth-child(4),
table.leaderboard-table th:nth-child(5), table.leaderboard-table td:nth-child(5){ width:6%; text-align:center; }
table.leaderboard-table th:nth-child(6), table.leaderboard-table td:nth-child(6){ width:10%; text-align:center; }
table.leaderboard-table th:nth-child(7), table.leaderboard-table td:nth-child(7){ width:21%; }
table.leaderboard-table th:nth-child(8), table.leaderboard-table td:nth-child(8){ width:23%; }
/* 9-я колонка (кнопка "Удалить") видна только admin'у — не входит в сумму
   100% выше (она не рендерится в обычной 8-колоночной таблице вообще), для
   admin'а совокупная ширина слегка превысит контейнер и включит
   .table-scroll — это редкий и приемлемый случай, тем же духом, что и
   table.admin-players-table. */
table.leaderboard-table th:nth-child(9), table.leaderboard-table td:nth-child(9){ width:56px; text-align:center; }

/* Иконки-кнопки бан/разбан/удаление — всегда в одну строку, не наезжают на статус. */
.player-actions{ display:flex; gap:6px; flex-wrap:nowrap; }
.player-actions form{ margin:0; }
button.icon-btn{ padding:5px 7px; font-size:14px; line-height:1; min-width:30px; text-align:center; }

.player-slots{ display:flex; gap:14px; margin:18px 0; }
.player-slot{ flex:1; background:var(--panel); border:1px solid var(--panel-edge); border-radius:8px; padding:18px; text-align:center; }
.player-slot.filled.a{ border-top:3px solid var(--ember); }
.player-slot.filled.b{ border-top:3px solid var(--violet); }
.player-slot .ps-name{ font-family:'Cinzel',serif; font-size:15px; margin-bottom:6px; }
.player-slot .ps-status{ font-size:12px; color:var(--parchment-dim); }
.player-slot .ps-status.ready{ color:#8fe19a; }
.player-slot.empty{ opacity:0.5; border-style:dashed; }

#game-root.hidden{ display:none; }
#board-wrap{ display:flex; flex-direction:column; align-items:center; gap:12px; }
/* On desktop the wrapper is transparent to layout (the svg sizes exactly as
   it did before this element existed); mobile turns it into the flexible
   "rubber" area that absorbs the leftover height of the app shell. */
.board-flex-area{ display:contents; }
svg#board{ max-width:100%; height:auto; }
.hex{ stroke:#3c3122; stroke-width:1.1; fill:#1c1712; }
.hex.loc-neutral{ fill:#20190f; }
.hex.loc-necropolis{ fill:#242424; }
.necropolis-icon{ fill:var(--necropolis-gray); font-weight:700; pointer-events:none; }
.hex.loc-a{ fill:#2a1712; }
.hex.loc-b{ fill:#1c1428; }
.hex.clickable{ cursor:pointer; }
.hex.hl-move{ fill:rgba(76,175,80,0.4); cursor:pointer; }
.hex.hl-attack{ fill:rgba(192,57,43,0.42); cursor:pointer; }
.hex.hl-deploy{ fill:rgba(201,161,59,0.4); cursor:pointer; }
.hex.hl-final{ fill:rgba(125,79,181,0.42); cursor:pointer; }
.loc-ring{ fill:none; stroke-width:1.4; stroke-dasharray:3 3; pointer-events:none; }
.unit-disc-a{ fill:#241512; stroke:var(--ember-bright); stroke-width:2; }
.unit-disc-b{ fill:#17121f; stroke:var(--violet-bright); stroke-width:2; }
.barricade-a{ fill:#2a1712; stroke:var(--ember-bright); stroke-width:2; stroke-dasharray:4 2; }
.barricade-b{ fill:#1c1428; stroke:var(--violet-bright); stroke-width:2; stroke-dasharray:4 2; }

/* ---- "last move" overlay — chess-style arrows/highlights for whatever the
   most recent action (yours or the opponent's) just did on the board. See
   CLAUDE.md "Визуализация последнего хода противника". The whole layer is
   pointer-events:none so it never steals clicks from the hexes underneath. */
.last-action-layer{ pointer-events:none; }
.last-action-arrow{ stroke-linecap:round; animation:lastActionArrowIn .35s ease-out; }
.last-action-arrow-move{ stroke-width:3.5; opacity:0.85; }
.last-action-arrow-move.owner-a{ stroke:var(--ember-bright); }
.last-action-arrow-move.owner-b{ stroke:var(--violet-bright); }
.last-action-arrow-attack{ stroke-width:3.5; opacity:0.95; stroke-dasharray:2 5; animation:lastActionArrowIn .35s ease-out, lastActionDash 0.9s linear infinite; }
.last-action-arrow-attack.owner-a{ stroke:#ff6b52; }
.last-action-arrow-attack.owner-b{ stroke:#c98bff; }
.arrowhead-move-fill{ fill:var(--gold); }
.arrowhead-attack-fill{ fill:#ff4d3d; }
.last-action-ring{ fill:none; stroke-width:2.5; animation:lastActionPulse 1.6s ease-in-out infinite; }
.last-action-ring.owner-a{ stroke:var(--ember-bright); }
.last-action-ring.owner-b{ stroke:var(--violet-bright); }
.last-action-ring-destroyed{ stroke:#ff4d3d !important; stroke-dasharray:3 3; }
.last-action-ring-damaged{ stroke:#ff9f43 !important; }
.last-action-ring-reinforced{ stroke:#4caf50 !important; }
.last-action-ring-deployed{ stroke:var(--gold) !important; stroke-dasharray:1 4; }
.last-action-ring-captured{ stroke:var(--gold) !important; }
.last-action-ring-barricadeBuilt{ stroke:#b08653 !important; }
.last-action-ring-barricadeDestroyed{ stroke:#ff4d3d !important; stroke-dasharray:3 3; }
.last-action-ring-dodged{ stroke:#7fd8ff !important; stroke-dasharray:1 4; }
.last-action-ring-special{ stroke:var(--gold) !important; stroke-dasharray:1 3; }
.last-action-badge-text{ font-size:14px; paint-order:stroke; stroke:#0c0906; stroke-width:3px; fill:#fff; }
@keyframes lastActionPulse{ 0%,100%{ opacity:0.55; r:26; } 50%{ opacity:1; r:31; } }
@keyframes lastActionArrowIn{ from{ opacity:0; } to{ opacity:1; } }
@keyframes lastActionDash{ to{ stroke-dashoffset:-14; } }

/* ---- flying token overlay — smooth "physical coin" animation for moves,
   kills, reinforcement gained/lost and hand tokens landing in the discard
   pile. See static/js/game.js "token flight animations" for the JS side
   (position:fixed layer in screen space, appended lazily as #anim-fly-layer).
   Purely visual/additive: never intercepts clicks, always self-removes. */
.fly-token{ position:absolute; left:0; top:0; display:flex; align-items:center; justify-content:center;
  border-radius:50%; background:#1b1610; border:1px solid var(--panel-edge); box-shadow:0 2px 8px rgba(0,0,0,0.5);
  line-height:1; will-change:transform,opacity; }

.hand-tray{ display:flex; gap:8px; flex-wrap:wrap; }
.hand-token{ position:relative; width:66px; min-height:64px; border-radius:6px; border:1px solid var(--panel-edge); background:#1b1610;
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:3px; font-size:10px; text-align:center; padding:6px 3px; cursor:pointer; }
.hand-token:hover{ border-color:var(--gold); }
.hand-token.selected{ outline:2px solid var(--gold); }
.hand-token .icon{ font-size:19px; }
.hand-token .revealed-badge{ position:absolute; left:3px; bottom:2px; font-size:11px; line-height:1; }

.action-menu{ display:flex; gap:8px; flex-wrap:wrap; }
.action-menu button{ font-size:11.5px; padding:6px 10px; }

.discard-row{ display:flex; flex-wrap:wrap; gap:5px; min-height:22px; }
.discard-chip{ display:inline-flex; align-items:center; justify-content:center;
  width:24px; height:24px; border-radius:4px; background:#1b1610; border:1px solid var(--panel-edge);
  font-size:14px; cursor:default; }
.discard-chip.hidden{ color:var(--parchment-dim); font-size:12px; }

.hand-count-dot{ display:inline-block; width:18px; height:18px; border-radius:50%;
  background:#6b6b6b; border:1px solid #8a8a8a; }
.control-dots{ display:inline-flex; gap:4px; vertical-align:middle; }
.control-dot{ display:inline-block; width:13px; height:13px; border-radius:50%; }
.control-dot.a{ background:var(--ember-bright); }
.control-dot.b{ background:var(--violet-bright); }

.log-panel{ width:100%; max-width:660px; background:var(--panel); border:1px solid var(--panel-edge); border-radius:6px;
  padding:9px 13px; font-size:12px; color:var(--parchment-dim); max-height:140px; overflow-y:auto; position:relative; }
.log-panel .entry{ padding:2px 0; border-bottom:1px dashed rgba(255,255,255,0.04); }
.log-panel .entry:last-child{ color:var(--parchment); }
.log-close-btn{ display:none; }
.log-backdrop{ display:none; }
.panel-sheet-close{ display:none; }

/* Компактная сворачиваемая полоска игрока: заголовок+статы всегда видны,
   полный ростер+сброс скрыты за кнопкой ▾ на мобильном экране — основной
   пожиратель вертикального места на телефоне во время боя. */
.side-panel{ position:relative; }
/* Team color instead of a "teammate" icon — same ember/violet the board
   already uses for team A/B (see CLAUDE.md "Слот vs Фракция"), so a
   teammate's card reads as visually distinct from an enemy's at a glance,
   in both 1v1 (2 seats = 2 "teams" of one) and 2v2. */
.side-panel.team-a{ border-color:var(--ember-bright); }
.side-panel.team-b{ border-color:var(--violet-bright); }
.side-panel-head{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; cursor:pointer; }
.side-panel-head h3{ order:1; font-size:14px; margin:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width:0; flex:1 1 auto; }
.side-panel-head .hint{ order:3; margin:0; flex:1 1 100%; }
/* Active-effect row (Witch's «Пророчество» today) — its own line below the
   header, never squeezed inline after the bag/discard/reserve counters (see
   CLAUDE.md "Панели игроков — эффекты на отдельной строке"). */
.side-panel-effect{
  margin-top:4px; font-size:11.5px; color:var(--gold); font-weight:600;
  overflow-wrap:anywhere;
}
.side-panel-effect.hidden{ display:none; }
/* Icon-only, corner-pinned to the whole card (not just the header row) —
   position:relative on .side-panel above is what it's pinned against. */
.panel-toggle-btn{
  position:absolute; top:6px; right:6px; z-index:1; order:2;
  display:none; align-items:center; justify-content:center;
  width:20px; height:20px; padding:0; font-size:12px; line-height:1; flex-shrink:0;
}

.clock-row{ display:flex; gap:10px; margin-top:8px; }
.clock-chip{ font-family:'Cinzel',serif; font-size:14px; padding:5px 12px; border-radius:5px; background:#1b1610; border:1px solid var(--panel-edge); }
.clock-chip.ticking{ border-color:var(--gold); color:#fff; box-shadow:0 0 8px rgba(201,161,59,0.35); }
.connection-notice{ background:rgba(192,57,43,0.15); border:1px solid var(--ember); color:var(--ember-bright); padding:8px 14px; border-radius:6px; font-size:12.5px; margin-bottom:10px; }
/* Persistent «Пророчество» indicator — lives right under the turn banner,
   NOT inside the scrollable side-panel strip (.side-panels, max-height:34vh
   on mobile — see CLAUDE.md "Мобильный экран боя"), so it stays visible for
   the whole round even if the caster's own card or the watched enemy's card
   happens to be scrolled out of that strip. Only ever shown to the viewer
   who personally cast the tactic (driven by the same server-restricted
   `others[].peekedCards` the side-panel row uses — see engine/game.py
   public_view — never a teammate, never the watched player). */
.prophecy-banner{
  background:rgba(155,89,182,0.15); border:1px solid #9b59b6; color:#c9a1e0;
  padding:7px 14px; border-radius:6px; font-size:12.5px; margin-bottom:10px;
}
.prophecy-banner.hidden{ display:none; }
.prophecy-banner .prophecy-icons{ font-size:15px; letter-spacing:2px; }

.table-scroll{ width:100%; overflow-x:auto; -webkit-overflow-scrolling:touch; }

/* ============ Chat (in-battle) ============ */
#chat-btn{ position:relative; }
.unread-badge{
  position:absolute; top:-6px; right:-6px; min-width:16px; height:16px; padding:0 3px;
  border-radius:9px; background:var(--ember-bright); color:#fff; font-size:10px;
  line-height:16px; text-align:center; font-family:'Spectral',serif;
}
.chat-modal-box{ display:flex; flex-direction:column; }
.chat-log{
  display:flex; flex-direction:column; gap:6px; min-height:120px; max-height:min(50vh,360px);
  overflow-y:auto; background:var(--panel); border:1px solid var(--panel-edge); border-radius:6px;
  padding:10px; margin:8px 0;
}
.chat-msg{ font-size:13px; line-height:1.4; }
.chat-msg-author{ color:var(--gold); font-family:'Cinzel',serif; font-size:11px; display:block; }
.chat-msg.mine .chat-msg-author{ color:var(--violet-bright); }
.chat-msg-text{ word-break:break-word; }
.chat-input-row{ display:flex; gap:8px; }
.chat-input-row input{
  flex:1; padding:9px 11px; border-radius:5px; border:1px solid var(--panel-edge);
  background:#100d0a; color:var(--parchment); font-family:'Spectral',serif; font-size:14px;
}
.chat-input-row input:focus{ outline:none; border-color:var(--gold); }

.support-widget{ display:flex; justify-content:center; margin:36px 0 6px; }
.support-btn{
  display:inline-flex; align-items:center; gap:7px; padding:5px 14px;
  border-radius:999px; background:transparent; color:var(--gold);
  font-family:'Spectral',serif; font-weight:400; font-size:12.5px; opacity:0.7;
  text-decoration:none; border:1px solid rgba(201,161,59,0.35);
  transition:opacity 0.15s ease, border-color 0.15s ease;
}
.support-btn:hover{ opacity:1; border-color:var(--gold); }
.support-btn-icon{ font-size:13px; line-height:1; }

/* ============ Global site-wide chat widget (global_chat.js) ============ */
.gc-widget{
  position:fixed; right:20px; bottom:20px; width:54px; height:54px; border-radius:50%;
  background:linear-gradient(180deg, var(--gold), #8a6a1f); color:#1a1408;
  display:flex; align-items:center; justify-content:center; font-size:24px;
  box-shadow:0 3px 10px rgba(0,0,0,0.45); cursor:grab; z-index:45; user-select:none; touch-action:none;
}
.gc-widget:active{ cursor:grabbing; }
.gc-badge{
  position:absolute; top:-4px; right:-4px; min-width:18px; height:18px; padding:0 4px;
  border-radius:9px; background:var(--ember-bright); color:#fff; font-size:11px;
  line-height:18px; text-align:center; font-family:'Spectral',serif; box-shadow:0 0 0 2px #100d0a;
}
.gc-overlay{ position:fixed; inset:0; background:rgba(0,0,0,0.78); display:flex; align-items:center; justify-content:center; z-index:55; }
.gc-overlay.hidden{ display:none; }
.gc-modal{
  background:linear-gradient(180deg,#1c150e,#100d0a); border:1px solid var(--gold); border-radius:8px;
  width:min(560px,92vw); max-height:80vh; display:flex; flex-direction:column; overflow:hidden;
}
.gc-modal-header{ display:flex; align-items:center; justify-content:space-between; padding:14px 18px; border-bottom:1px solid var(--panel-edge); }
.gc-modal-header h3{ margin:0; color:var(--gold); font-size:16px; }
.gc-header-actions{ display:flex; gap:8px; }
.gc-header-actions button{ padding:6px 10px; font-size:12.5px; }
.gc-body{ display:flex; flex:1; min-height:0; }
.gc-users{ width:150px; flex:0 0 150px; border-right:1px solid var(--panel-edge); overflow-y:auto; padding:10px; }
.gc-user-row{ display:flex; align-items:center; justify-content:space-between; gap:4px; padding:4px 2px; font-size:12px; }
.gc-user-row.me{ color:var(--violet-bright); }
.gc-user-row.muted{ opacity:0.5; }
.gc-user-name{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.gc-mute-user-btn{ background:none; border:none; cursor:pointer; font-size:13px; padding:0 2px; flex:0 0 auto; }
.gc-chat{ flex:1; display:flex; flex-direction:column; min-width:0; padding:12px 14px; }
.gc-log{ flex:1; overflow-y:auto; display:flex; flex-direction:column; gap:6px; margin-bottom:8px; min-height:120px; }
.gc-input-row{ display:flex; gap:8px; }
.gc-input-row input{
  flex:1; padding:9px 11px; border-radius:5px; border:1px solid var(--panel-edge);
  background:#100d0a; color:var(--parchment); font-family:'Spectral',serif; font-size:14px;
}
.gc-input-row input:focus{ outline:none; border-color:var(--gold); }
.gc-mention-self{ background:rgba(201,161,59,0.35); border-radius:3px; padding:0 2px; font-weight:600; }

@media (max-width: 640px){
  .gc-widget{ width:48px; height:48px; font-size:20px; }
  .gc-modal{ width:96vw; max-height:88vh; }
  .gc-body{ flex-direction:column; }
  .gc-users{
    width:100%; flex:0 0 auto; max-height:96px; border-right:none;
    border-bottom:1px solid var(--panel-edge); display:flex; flex-wrap:wrap; gap:2px 12px;
  }
  .gc-user-row{ width:auto; }
}

/* ============ MOBILE ============ */
@media (max-width: 640px){
  body.game-fullscreen{ overflow:hidden; }
  .page{ padding:16px 10px 40px; }
  .card{ padding:14px; border-radius:6px; }
  .card + .card{ margin-top:12px; }
  h1{ font-size:22px; }
  h2{ font-size:17px; }
  h3{ font-size:14px; }

  input[type=text], input[type=password]{ font-size:16px; } /* iOS: prevents zoom-on-focus */
  button, .btn{ padding:9px 14px; font-size:12.5px; }
  .form-actions{ flex-wrap:wrap; gap:8px; }

  table.rooms th, table.rooms td{ padding:7px 4px; font-size:11px; }
  table.rooms td .btn{ padding:5px 6px; font-size:10.5px; }
  table.rooms td button{ padding:5px 6px; font-size:10px; }
  .status-tag{ padding:2px 5px; font-size:9.5px; }

  .player-slots{ flex-direction:column; gap:10px; }
  .player-slot{ padding:12px; }

  .hand-tray{ gap:6px; justify-content:center; }
  .hand-token{ width:58px; min-height:56px; font-size:9px; }
  .hand-token .icon{ font-size:16px; }
  .action-menu{ gap:6px; justify-content:center; }
  .action-menu button{ font-size:10.5px; padding:6px 8px; }

  .clock-row{ gap:6px; }
  .clock-chip{ font-size:12px; padding:4px 9px; }

  .modal-box{ padding:16px 16px; }

  table.rooms td[style*="flex"]{ flex-direction:column; align-items:stretch; }

  /* ---- Battle screen: single-screen app shell (see CLAUDE.md "Мобильный
     экран боя") ---- #game-root becomes a fixed, full-viewport flex column;
     the board is the ONLY flexible element, everything else (icon header,
     turn+clock line, player strips) is fixed-height, so the page never
     needs to scroll regardless of device height. Full roster/discard and
     the log live in bottom sheets opened by tapping a strip or the 📜 icon,
     instead of permanently eating vertical space. */
  #room-actions-bar .btn-label{ display:none; }
  #room-actions-bar button{
    display:inline-flex; align-items:center; justify-content:center;
    width:36px; height:36px; padding:0; font-size:16px; border-radius:6px; flex:none;
  }
  #room-actions-bar form{ display:inline-flex; margin:0; }

  #room-actions-bar.game-header-actions{
    order:1; flex:0 0 auto; display:flex; gap:6px; flex-wrap:nowrap; margin:0;
    padding:8px 10px; border-bottom:1px solid var(--panel-edge);
    background:linear-gradient(180deg,#171208,#0d0b09); justify-content:flex-end;
  }

  #game-root:not(.hidden){
    position:fixed; inset:0; z-index:10; display:flex; flex-direction:column;
    background: radial-gradient(ellipse at 50% 0%, #1a140f 0%, #0d0b09 65%);
    overflow:hidden;
  }
  #actions-anchor-game-top{ order:1; flex:0 0 auto; }
  #turn-banner{
    order:2; flex:0 0 auto; margin:0; display:flex; align-items:center;
    justify-content:space-between; flex-wrap:wrap; gap:4px 10px; padding:10px 14px;
  }
  #turn-banner #turn-label{ font-size:12.5px; }
  #turn-banner #phase-hint{ display:none; }
  #turn-banner .clock-row{ margin-top:0; }
  #connection-notice{ order:3; flex:0 0 auto; }
  #prophecy-banner{ order:3; flex:0 0 auto; }
  #board-wrap{
    order:4; flex:1 1 auto; min-height:0; display:flex; flex-direction:column;
    align-items:stretch; gap:6px; padding:4px 8px;
  }
  .side-panel-legend-row{ order:5; flex:0 0 auto; margin:0; padding:2px 2px 0; }
  .side-panels{ order:6; flex:0 0 auto; margin:0; max-height:34vh; overflow-y:auto; }

  .board-flex-area{ flex:1 1 auto; min-height:0; width:100%; display:flex; align-items:center; justify-content:center; }
  svg#board{ max-width:100%; max-height:100%; width:auto; height:auto; }
  .hand-tray, .action-menu{ flex:0 0 auto; }

  .side-panel-body{ display:none; margin-top:8px; }
  /* Grid cells (see room.html #side-panels.team-columns) default to
     min-width:auto like flex items — without min-width:0 a long nickname
     forces the cell wider than its 1fr share and the grid overflows the
     screen instead of shrinking, silently pushing later cells out of view
     (the same class of bug the grid switch itself was fixing). */
  .side-panel{ padding:8px 8px; min-width:0; }
  .side-panel-head{ gap:4px; padding-right:22px; }
  .side-panel-head h3{ font-size:11.5px; white-space:normal; overflow-wrap:anywhere; }
  .side-panel-head .hint{ font-size:10.5px; }
  .panel-toggle-btn{ display:flex; font-size:11px; }

  .side-panel-body.sheet-open{
    display:block; position:fixed; left:0; right:0; bottom:0; z-index:80;
    max-height:60vh; overflow-y:auto; margin:0; border-radius:12px 12px 0 0;
    background:linear-gradient(180deg,#1c150e,#100d0a); border-top:1px solid var(--gold);
    box-shadow:0 -8px 28px rgba(0,0,0,0.55); padding:16px 14px calc(14px + env(safe-area-inset-bottom, 0px));
  }
  .side-panel-body.sheet-open .panel-sheet-close{
    display:block; position:absolute; top:8px; right:10px; padding:2px 8px; font-size:12px;
  }
  #panel-sheet-backdrop.sheet-open{
    display:block; position:fixed; inset:0; background:rgba(0,0,0,0.55); z-index:75;
  }

  .log-toggle-btn{ font-size:11px; padding:6px 10px; }
  .log-panel{
    display:none;
  }
  .log-panel.sheet-open{
    display:block; position:fixed; left:0; right:0; bottom:0; z-index:80;
    max-width:none; max-height:55vh; border-radius:12px 12px 0 0; font-size:11px;
    box-shadow:0 -8px 28px rgba(0,0,0,0.55); padding:16px 14px 12px;
  }
  .log-panel.sheet-open .log-close-btn{
    display:block; position:absolute; top:8px; right:10px; padding:2px 8px; font-size:12px;
  }
  .log-backdrop.sheet-open{
    display:block; position:fixed; inset:0; background:rgba(0,0,0,0.55); z-index:75;
  }
}

@media (max-width: 400px){
  .draft-grid{ grid-template-columns:1fr; }
  .hand-token{ width:52px; min-height:50px; }
}
