/* ============================================================
   МИНИ-ИГРЫ ПОД СТОЛОМ — только свой хром.
   Проект: docs/SIDEGAME-DESIGN.md §16.1. Образец: apps/arena/_demo-sidegame.css.

   Здесь НЕТ карт, кнопок, фишек и токенов: всё это боевое и приезжает из
   base.css / table.css / chips.css / cosmetics.css. Своего — ровно три вещи,
   которых в продукте не было: лента из двух кадров, живая полоса стола и лист
   мини-игры. Ровно так же устроен стенд, и переносить оттуда получается кусками,
   а не переписывая.
   ============================================================ */

/* ── подсказка про жест ─────────────────────────────────────────────────────
   Появляется после первого моего фолда в сессии и гаснет навсегда, как только
   лентой воспользовались: подсказка, которая висит и после того, как её поняли,
   перестаёт быть подсказкой. */
.sg-hint {
  position: absolute; bottom: 112px; left: 50%; transform: translateX(-50%); z-index: 22;
  display: flex; align-items: center; gap: 6px; padding: 5px 12px 5px 9px; border-radius: 999px;
  background: rgba(8, 6, 15, .66); border: 1px solid rgba(45, 226, 197, .34); backdrop-filter: blur(8px);
  font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 700; font-size: 11.5px;
  letter-spacing: .4px; color: #9af5e5; white-space: nowrap; cursor: pointer;
  transition: opacity .3s, transform .3s;
}
/* `display:flex` выше перебивает `display:none` от атрибута `hidden` (селектор
   по классу специфичнее, чем по атрибуту), и подсказка показывалась всем сразу,
   а не после первого фолда. Ровно тот случай, ради которого правило и пишется. */
.sg-hint[hidden] { display: none }
.sg-hint i { animation: sg-nudge 1.9s ease-in-out infinite }
.sg-hint.gone { opacity: 0; transform: translateX(-50%) translateY(8px); pointer-events: none }
@keyframes sg-nudge { 0%, 100% { transform: translateY(2px) } 50% { transform: translateY(-3px) } }

/* ── ЛЕНТА ──────────────────────────────────────────────────────────────────
   Положение кадра (0 — стол, 1 — мини-игра) ставит JS ПРЯМО в transform трёх
   слоёв, а не общей переменной на #scr: наследуемое свойство заставляло браузер
   пересчитывать стили всему сукну на каждый кадр жеста, и лента ехала с
   ощутимой тяжестью. Здесь остаются только слои и правила движения. */
.sg-dim {
  position: absolute; inset: 0; z-index: 55; pointer-events: none;
  background: #05040f; opacity: 0; will-change: opacity;
}
body[data-screen='game'] #g { will-change: transform }

/* Жест ленты — вертикальный, и браузер обязан отдать его нам, а не потратить
   на прокрутку или pull-to-refresh. Только НА СТОЛЕ: `#scr` — общий контейнер,
   и в лобби он прокручивается по-настоящему. Сукно не прокручивается никогда,
   поэтому здесь терять нечего. */
body[data-screen='game'] #scr { touch-action: none }
/* Внутренности листа мини-игры прокручиваются сами — иначе длинный экран игры
   стало бы нечем листать. Лента при этом ловит только то, что дошло до неё. */
.sg-scroll { overflow-y: auto; overscroll-behavior: contain; touch-action: pan-y; -webkit-overflow-scrolling: touch }
/* Экран умещается целиком — прокручивать нечего, и обещание `pan-y` браузеру
   не выдаётся: иначе он забирает вертикальный жест себе, обрывает наши
   pointer-события и лента замирает под пальцем. Класс ставит `sheetFit()`. */
.sg-scroll.fits { touch-action: none }

#sg {
  position: absolute; inset: 0; z-index: 60; pointer-events: none; touch-action: none;
  transform: translate3d(0, 100%, 0); will-change: transform; contain: layout paint;
}
#sg.live { pointer-events: auto }
.tb.live { pointer-events: auto }

/* Доводка после броска — единственное место, где движение анимирует браузер.
   Во время самого жеста переходов нет: кадр ставит палец. */
#scr.anim #g, #scr.anim #sg, #scr.anim .tb, #scr.anim .sg-dim {
  transition: transform .34s cubic-bezier(.22, .86, .28, 1), opacity .26s linear;
}
#scr.anim.quick #g, #scr.anim.quick #sg, #scr.anim.quick .tb, #scr.anim.quick .sg-dim {
  transition-duration: .22s, .18s;
}

/* Пока лента едет, с неё снимается всё, что заставляет перерисовывать слой
   каждый кадр: размытия под шапкой и плашками (их на экране полтора десятка) и
   бесконечные анимации. Возвращается сразу по остановке — глазом переход не
   читается, а кадры перестают проседать. */
#scr.moving .ghud .pill, #scr.moving .seat .info, #scr.moving .pot,
#scr.moving .sg-hint, #scr.moving .tb { backdrop-filter: none }
#scr.moving .seat .timer, #scr.moving .tt-dot, #scr.moving .sg-hint i,
#scr.moving .sg-live i { animation-play-state: paused }
/* Компаньоны живут ВНЕ #scr (слой #companions на body) и иначе остались бы
   висеть над мини-игрой. Гасит их модуль ленты, здесь — только переход. */
#companions { transition: opacity .22s linear }
#companions.sg-away { opacity: 0; pointer-events: none }

.sg-sheet {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  padding-top: calc(var(--tbh, 92px) + 8px); transition: padding-top .3s ease;
  background: linear-gradient(180deg, #100c26, #08060f 46%);
  box-shadow: 0 -10px 26px rgba(0, 0, 0, .55);
}
.sg-body { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden }
.sg-grip {
  flex: none; height: 24px; display: flex; align-items: center; justify-content: center;
  cursor: pointer;
}
.sg-grip i { display: block; width: 34px; height: 3px; border-radius: 2px; background: rgba(255, 255, 255, .22) }

/* ── ЖИВАЯ ПОЛОСА СТОЛА ─────────────────────────────────────────────────────
   То, ради чего фича вообще возможна: стол уходит с глаз, но не из виду.
   Реплеер за столом запрещён ровно потому, что «засмотревшийся получает
   автофолд» (docs/REPLAY-DESIGN.md §9) — эта полоса и есть ответ на тот же
   риск. Лежит отдельным слоем и с лентой НЕ едет. */
.tb {
  position: absolute; top: 0; left: 0; right: 0; z-index: 70; pointer-events: none;
  opacity: 0; transform: translate3d(0, -12px, 0); will-change: transform, opacity;
  padding: calc(var(--safetop, 0px) + 8px) 12px 9px;
  background: linear-gradient(180deg, rgba(21, 16, 48, .96), rgba(13, 10, 30, .96));
  border-bottom: 1px solid rgba(255, 255, 255, .09);
}
.tb::before {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(45, 226, 197, .45), transparent);
}
/* ── ВТОРОЙ РЕЖИМ ПОЛОСЫ: СВЁРНУТЫЙ СТОЛ ────────────────────────────────────
   Тот же узел, но живёт он теперь не над мини-игрой, а над навигацией — как
   мини-плеер: игрок ходит по продукту, стол внизу продолжает играть
   (docs/MINIMIZE-DESIGN.md). Владелец — src/table/minibar.js.

   Прозрачность, сдвиг и касания перебиваются здесь, а инлайновые значения,
   которые пишет лента, снимает сам минибар: инлайн специфичнее любого класса.

   z-index 55 подобран по соседям, а не «повыше»: выше навигации (50), но НИЖЕ
   затемнения и панели задач (65/70) и шторок вкладки «Клубы» (.eco-sheet, 70).
   На 70 полоса торчала бы над затемнением и под самой панелью — то есть висела
   бы в воздухе поверх приглушённого экрана. */
.tb.tb-min {
  top: auto; bottom: var(--navh, 88px); z-index: 55;
  opacity: 1; transform: none; pointer-events: auto; cursor: pointer;
  border-bottom: 0; border-top: 1px solid rgba(255, 255, 255, .09);
  box-shadow: 0 -12px 28px rgba(0, 0, 0, .38);
  /* ОДНА СТРОКА, А НЕ ТРИ. Над мини-игрой полоса может позволить себе три
     этажа — она там главный экран. Над продуктом она фоновая, и в трёх этажах
     съедала треть телефона: борд, под ним чей ход с лентой действий, под ними
     строка состояния. Ряды схлопываются в один флекс (`display: contents` ниже),
     а лента последних действий в свёрнутом виде не показывается вовсе — из всего
     стола она единственное, что можно узнать позже и ничего не потерять.
     Вниз строкой отрываются только те, у кого своя цена: состояние и мой ход. */
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 7px;
  padding: 7px 12px;
  /* Колонка чтения на десктопе — та же, что у страниц (680px). Отступом, а не
     обёрткой: узел один на два режима, и лишний слой в разметке сломал бы
     раскладку ленты. */
  padding-inline: max(12px, calc(50% - 340px));
}
.tb.tb-min .tb-row, .tb.tb-min .tb-line { display: contents }
/* Карта в свёрнутой полосе мельче, чем над мини-игрой: там на неё смотрят между
   ходами игры, здесь — на бегу, и ряд из пяти обязан ужиться с банком, ходом и
   своей рукой в одной строке на 360px. Оба индекса на карте при этом остаются —
   без нижней масти карта перестаёт быть картой. */
.tb.tb-min .tb-board .pc { --pc-w: 20px; --pc-h: 27px; --pc-rk: 11px; --pc-su: 7px; --pc-big: 9px }
.tb.tb-min .tb-mine .pc { --pc-w: 21px; --pc-h: 28px; --pc-rk: 11px; --pc-su: 7px; --pc-big: 9px }
.tb.tb-min .tb-pot b { font-size: 13px }
.tb.tb-min .tb-back { width: 26px; height: 26px; border-radius: 8px }
.tb.tb-min .tb-feed { display: none }
.tb.tb-min .tb-who { margin-left: auto; order: 4; gap: 4px; font-size: 11px }
/* Всё, что можно не говорить, в свёрнутой полосе не говорится: слово «ходит»
   при имени и подпись «банк» под числом. Строка обязана уместиться в одну на
   360px, иначе полоса растёт вторым этажом ровно там, где её и так много. */
.tb.tb-min .tb-lbl { display: none }
.tb.tb-min .tb-pot small { display: none }
.tb.tb-min .tb-pot { line-height: 1 }
/* Длинный ник не имеет права уводить секунды на вторую строку. */
.tb.tb-min .tb-who b { max-width: 74px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
.tb.tb-min .tb-who .sec { font-size: 12px; padding: 0 4px }
.tb.tb-min .tb-mine small { display: none }
.tb.tb-min .tb-mine { order: 5; margin-left: 0 }
.tb.tb-min .tb-note { order: 6; flex-basis: 100%; margin-top: 0 }
.tb.tb-min .tb-turn { order: 7; flex-basis: 100% }
.tb.tb-min.mine .tb-turn { margin-top: 0 }
/* Пока ход не мой, панели действий в потоке нет вовсе: схлопнутая до нуля, она
   всё равно занимала бы свою строку переноса и промежуток между ними. */
.tb.tb-min:not(.mine) .tb-turn { display: none }
/* На моём ходу «ходит такой-то» лишнее — об этом кричит сама панель. */
.tb.tb-min.mine .tb-who { display: none }
/* Бирюзовая нить переезжает на верхнюю кромку — к той стороне, откуда полоса
   теперь граничит с содержимым экрана. */
.tb.tb-min::before { bottom: auto; top: -1px }
/* Непрозрачно, в отличие от полосы над мини-игрой: там под ней сукно, которое
   и должно просвечивать, а здесь — прокручиваемая страница, и её текст, читаемый
   сквозь полосу, выглядит грязью. */
.tb.tb-min { background: linear-gradient(180deg, #151030, #0d0a1e) }
.tb.tb-min.mine { background: linear-gradient(180deg, #2e200a, #160e22) }

.tb-row { display: flex; align-items: center; gap: 9px }
.tb-back {
  width: 30px; height: 30px; flex: none; border-radius: 10px; display: flex;
  align-items: center; justify-content: center; background: rgba(255, 255, 255, .06);
  border: 1px solid var(--bord); color: var(--text); padding: 0; cursor: pointer;
}
/* РАЗМЕР КАРТЫ В ПОЛОСЕ. До 13.09.2026 борд шёл картами 19×26 с рангом в девять
   пикселей — «практически не читаемы сверху»: на полосу смотрят вполглаза, между
   двумя ходами мини-игры, и карта обязана узнаваться с одного взгляда, а не
   разбираться. Карта выросла ровно настолько, чтобы на ней помещались ОБА
   индекса — верхний ранг с мастью и нижняя масть: без второго карта перестаёт
   быть картой и становится наклейкой с буквой. Дальше расти ей некуда — ряд из
   пяти, банк и своя рука должны уместиться в одну строку на телефоне в 360. */
.tb-board { display: flex; gap: 3px; flex: none }
.tb-board .pc { --pc-w: 24px; --pc-h: 34px; --pc-rk: 13px; --pc-su: 9px; --pc-big: 11px; border-radius: 5px }
.tb-board .pc .c { top: 3px; left: 3px }
.tb-board .pc .big { bottom: 2px; right: 3px }
.tb-pot { flex: none; text-align: left; line-height: 1.05 }
.tb-pot b { display: block; font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 700; font-size: 15px; color: var(--gold) }
.tb-pot small { font-size: 8.5px; letter-spacing: .7px; text-transform: uppercase; color: var(--dim) }
.tb-who { flex: none; display: flex; align-items: center; gap: 5px; font-size: 11.5px; color: var(--muted); white-space: nowrap }
.tb-who b { color: var(--text); font-weight: 700 }
.tb-who .sec {
  font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 700; font-size: 13px; color: var(--teal);
  padding: 1px 5px; border-radius: 6px; background: rgba(45, 226, 197, .12); border: 1px solid rgba(45, 226, 197, .3);
}
.tb-line { display: flex; align-items: center; gap: 9px; margin-top: 8px }
.tb-mine { flex: none; margin-left: auto; display: flex; gap: 3px; align-items: center }
/* `display:flex` выше перебивает `display:none` от атрибута `hidden` — а полоса
   прячет руку, когда её нет (наблюдаю со стороны). Без этой строки на экране
   оставалась подпись «рука» и пустота после неё. */
.tb-mine[hidden] { display: none }
.tb-mine small {
  font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 700; font-size: 9px; letter-spacing: .7px;
  text-transform: uppercase; color: var(--dim); margin-right: 2px;
}
.tb-mine .pc { --pc-w: 25px; --pc-h: 35px; --pc-rk: 14px; --pc-su: 9px; --pc-big: 11px; border-radius: 5px }
.tb-mine .pc .c { top: 3px; left: 3px }
.tb-mine .pc .big { bottom: 2px; right: 3px }
.tb-mine.folded { opacity: .42; filter: grayscale(.7) }
.tb-feed { flex: 1; min-width: 0; height: 15px; overflow: hidden; position: relative; text-align: right }
.tb-feed div {
  font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 600; font-size: 11.5px; letter-spacing: .2px;
  color: var(--dim); animation: tb-feed-in .32s ease both; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tb-feed div b { color: #cfc9e6; font-weight: 700 }

/* Почему стол может не дождаться: нет связи, за меня сходил автомат, я в
   ситауте и место держат до срока. За сукном всё это написано в доке, а у
   свёрнутого стола дока нет. Цвет — по цене новости, а не по настроению. */
.tb-note {
  margin-top: 7px; font-size: 11.5px; line-height: 1.35; color: var(--muted);
  font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 600; letter-spacing: .2px;
}
.tb-note[data-kind='warn'] { color: var(--gold) }
.tb-note[data-kind='bad'] { color: var(--red) }
.tb-note[hidden] { display: none }
@keyframes tb-feed-in { from { opacity: 0; transform: translateY(9px) } to { opacity: 1; transform: none } }

/* Мой ход: полоса перестаёт быть табло и становится действием. Кнопки те же,
   что в доке за столом, и уходят они той же функцией — второго пути к
   `net.send('action')` в клиенте не появляется (§16.2). */
.tb-turn { max-height: 0; overflow: hidden; opacity: 0; transition: max-height .32s ease, opacity .22s ease, margin .32s ease }
.tb.mine {
  background: linear-gradient(180deg, rgba(46, 32, 10, .97), rgba(22, 14, 34, .97));
  box-shadow: 0 0 0 1px rgba(255, 194, 75, .45), 0 10px 30px rgba(255, 157, 43, .18);
}
.tb.mine .tb-turn { max-height: 130px; opacity: 1; margin-top: 9px }
.tb.mine .tb-line { display: none }
.tt-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 7px }
.tt-ttl {
  display: flex; align-items: center; gap: 7px; font-family: 'Rajdhani', system-ui, sans-serif;
  font-weight: 800; font-size: 14px; letter-spacing: 1.4px; text-transform: uppercase;
  color: var(--gold); text-shadow: 0 0 14px rgba(255, 194, 75, .55);
}
.tt-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--gold); box-shadow: 0 0 10px var(--gold); animation: tt-beat 1s steps(1, end) infinite }
@keyframes tt-beat { 50% { opacity: .25 } }
.tt-sec { font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 800; font-size: 19px; line-height: 1; color: var(--clk, var(--gold)) }
.tt-thread { height: 2px; border-radius: 2px; background: rgba(255, 255, 255, .12); overflow: hidden; margin-bottom: 9px }
.tt-thread > i { display: block; height: 100%; background: var(--clk, var(--gold)); box-shadow: 0 0 8px var(--clk, var(--gold)); transition: width .2s linear }
.tt-btns { display: flex; gap: 7px }
.tt-btns .ab { padding: 11px 0; font-size: 15px; border-radius: 11px }
.tt-btns .ab.totable {
  flex: none; width: 46px; display: flex; align-items: center; justify-content: center;
  background: rgba(255, 255, 255, .08); border: 1px solid var(--bord);
}

/* Пока ход мой, лист мини-игры приглушается — но остаётся играбельным: ставка
   в раунде не должна сгореть из-за того, что позвали за стол (§3). */
#scr.myturn .sg-body { opacity: .76; transition: opacity .3s ease }

/* Тост и подсказка хода поверх ленты: событие за столом обязано выйти за
   пределы того места, куда игрок не смотрит. Со свёрнутым столом тост
   поднимается над полосой: сказанное под ней прочитать нельзя. */
#scr .toast { bottom: calc(28px + var(--minifull, 122px)); z-index: 200 }

/* ── карточка в рельсе (десктоп ≥1280) ─────────────────────────────────── */
.rc-sg-go {
  width: 100%; margin-top: 8px; padding: 9px 0; border-radius: 10px; cursor: pointer;
  font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 700; font-size: 13px; letter-spacing: .4px;
}

/* ============================================================
   ЛИСТ: хаб, игры, тренажёры, история.
   Карты, кнопки и токены — боевые; здесь только раскладка своих экранов.
   ============================================================ */

.sg-scroll { flex: 1; min-height: 0; padding: 0 12px 12px }
.sg-empty {
  flex: 1; display: flex; align-items: center; justify-content: center; padding: 24px;
  text-align: center; color: var(--dim); font-size: 13.5px;
}

/* ── ДВИЖЕНИЕ: два примитива на все экраны ─────────────────────────────────
   Экраны ленты живут по десять секунд, и всё на них появляется — вопрос только
   в том, когда. Поэтому не «анимация на каждый блок», а две готовые: `sg-in`
   (выход снизу) и `sg-pop` (прибытие суммы), обе с задержкой в `--d`. Момент
   задаёт РАЗМЕТКА, а не таблица стилей: последовательность вскрытия — это
   правило игры (flip.js: BEAT), и жить ей рядом с игрой, а не здесь.

   Задержка вместо таймеров: лист перерисовывается целиком, и анимация умирает
   вместе со своим узлом — досчитать до конца в чужом экране она не может. */
@keyframes sg-in { from { opacity: 0; transform: translateY(7px) } to { opacity: 1; transform: none } }
@keyframes sg-pop {
  0% { opacity: 0; transform: scale(.82) }
  62% { opacity: 1; transform: scale(1.06) }
  100% { opacity: 1; transform: scale(1) }
}
.sg-in { animation: sg-in .3s ease var(--d, 0s) both }
.sg-pop { animation: sg-pop .42s cubic-bezier(.2, .9, .3, 1.2) var(--d, 0s) both }

/* ЛИШНЯЯ ВЫСОТА УХОДИТ В ПОЛЯ, А НЕ В ЭЛЕМЕНТЫ. Растянуть блок по высоте листа —
   худший из способов убрать пустоту: она никуда не девается, а переезжает
   внутрь блока, и рука из двух карт едет по центру пустой панели в пол-экрана.
   Экран поэтому остаётся композицией своего размера и встаёт по середине листа.
   Занять лист содержимым — задача СОДЕРЖИМОГО (крупные карты на прогоне борда,
   шесть строк в хабе), а не резинки. */
.sg-flip, .sg-hilo, .sg-mines, .sg-quiz { display: flex; flex-direction: column; justify-content: center }

/* ── шапка экрана внутри листа ─────────────────────────────────────────── */
.sg-head {
  flex: none; display: flex; align-items: center; gap: 9px; padding: 10px 12px 8px;
}
.sg-head > b {
  font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 800; font-size: 16px;
  letter-spacing: .6px; text-transform: uppercase; color: var(--text);
}
.sg-back {
  width: 30px; height: 30px; flex: none; border-radius: 10px; display: flex;
  align-items: center; justify-content: center; padding: 0; cursor: pointer;
  background: rgba(255, 255, 255, .06); border: 1px solid var(--bord); color: var(--text);
}
.sg-score {
  margin-left: auto; display: flex; align-items: baseline; gap: 5px;
  font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 800; font-size: 15px; color: var(--gold);
}
.sg-score small { font-size: 9px; letter-spacing: .6px; text-transform: uppercase; color: var(--dim); font-weight: 700 }
.sg-streak {
  font-style: normal; font-size: 10px; padding: 1px 6px; border-radius: 7px; color: var(--teal);
  background: rgba(45, 226, 197, .12); border: 1px solid rgba(45, 226, 197, .3);
}

/* ── хаб: две полки ────────────────────────────────────────────────────── */
/* ЛИСТ ЗАНЯТ ЦЕЛИКОМ. До 13.09.2026 полки шли своей высотой и жались к шапке, а
   под ними оставалась треть пустого экрана — на телефоне это читается как
   недогруженная страница, а не как «дальше ничего нет». Полки делят свободную
   высоту поровну и растут вместе с ней; `min-height` карточки остаётся полом,
   ниже которого лист начинает прокручиваться, а не сминаться. */
.sg-hub { padding-top: 2px; display: flex; flex-direction: column; justify-content: center; gap: 12px }
.sg-shelf { margin-bottom: 0; display: flex; flex-direction: column; flex: 1 1 0; min-height: 0 }
.sg-shelf-h {
  display: flex; align-items: baseline; gap: 8px; margin: 0 2px 8px;
  font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 800; font-size: 12px;
  letter-spacing: 1.3px; text-transform: uppercase; color: var(--muted);
}
.sg-shelf-h small, .sg-points { font-size: 10px; letter-spacing: .5px; text-transform: none; color: var(--dim); font-weight: 600 }
.sg-points { margin-left: auto; color: var(--gold) }
/* СТРОКИ, А НЕ ПЛИТКИ. Три плитки в ряд оставляли под собой полэкрана пустоты,
   а растянутая по высоте плитка переносила ту же пустоту внутрь себя. Строка
   переживает любую высоту без потерь: содержимое в ней разложено ПОПЕРЁК, и
   лишняя высота уходит в поля вокруг него, а не в дыру посередине. Шесть строк
   занимают лист целиком. */
/* Строка ГИБКАЯ В ГРАНИЦАХ, а не фиксированная. Верхняя граница есть, потому
   что дальше строка начала бы растягиваться, а это ровно то, чего делать
   нельзя. Нижняя — потому что лист обязан УМЕЩАТЬСЯ: высота под ним меняется на
   ходу (полоса стола вырастает со 92 до 111 точек, когда ход мой и в ней
   появляются кнопки), и жёсткая строка делала хаб прокручиваемым ровно в этот
   момент. А прокручиваемый лист отдаёт вертикальный жест браузеру, тот обрывает
   наши pointer-события — и лента замирает под пальцем (см. `.sg-scroll.fits`). */
.sg-cards { flex: 1; min-height: 0; display: grid; grid-auto-rows: minmax(56px, 96px); gap: 8px }
.sg-card {
  display: flex; flex-direction: row; align-items: center; gap: 12px; padding: 10px 13px;
  border-radius: 13px; cursor: pointer; text-align: left; min-height: 56px;
  background: linear-gradient(180deg, rgba(255, 255, 255, .055), rgba(255, 255, 255, .02));
  border: 1px solid var(--bord); color: var(--text);
}
.sg-card:active { transform: scale(.98) }
.sg-card i { flex: none; width: 28px; text-align: center; font-size: 22px; color: var(--teal) }
.sg-card .tx { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px }
.sg-card b { font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 800; font-size: 15px; line-height: 1.1 }
.sg-card small { font-size: 11px; line-height: 1.25; color: var(--dim) }
.sg-last { flex: none; font-size: 11px; font-weight: 700; color: var(--muted); text-align: right }
.sg-last.win { color: var(--teal) }
.sg-last.lose { color: var(--red) }
.sg-badge {
  flex: none; font-size: 9px; font-weight: 800; letter-spacing: .6px; text-transform: uppercase;
  padding: 2px 7px; border-radius: 6px; color: var(--gold);
  background: rgba(255, 194, 75, .14); border: 1px solid rgba(255, 194, 75, .4);
}
/* Сноска: тише всего, что есть на экране. Она не новость и не действие — это
   подпись под страницей, и читают её один раз. */
.sg-beta {
  flex: none; text-align: center; margin-top: 8px; font-size: 10.5px; letter-spacing: .2px;
  color: var(--dim); opacity: .75;
}
.sg-history-go {
  width: 100%; flex: none; display: flex; align-items: center; justify-content: center; gap: 7px;
  padding: 10px 0; border-radius: 11px; cursor: pointer; font-size: 12.5px;
  background: rgba(255, 255, 255, .04); border: 1px solid var(--bord); color: var(--muted);
}

/* ── правила, ставка, док ──────────────────────────────────────────────── */
.sg-rules { margin: 4px 0 12px; padding-left: 18px; display: grid; gap: 4px }
.sg-rules li { font-size: 12.5px; line-height: 1.35; color: var(--muted) }
.sg-money {
  display: flex; justify-content: space-between; padding: 9px 11px; border-radius: 11px;
  background: rgba(255, 255, 255, .04); border: 1px solid var(--bord); font-size: 12px; color: var(--dim);
}
.sg-money b { color: var(--text); font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 700; font-size: 14px }
.sg-dock {
  flex: none; display: flex; gap: 8px; align-items: center; padding: 9px 12px;
  border-top: 1px solid rgba(255, 255, 255, .07); background: rgba(8, 6, 15, .5);
}
.sg-dock.sg-wait { justify-content: center; color: var(--dim); font-size: 12px; letter-spacing: .3px }
/* Док выбора ставки — в две строки: суммы и поле сверху, действие снизу.
   В одну строку на телефоне это нечитаемая полоска, по которой не попасть. */
.sg-dock.col { flex-direction: column; align-items: stretch; gap: 7px }
.sg-dock.col .sg-go { width: 100%; padding: 12px 0 }
.sg-bets { display: flex; gap: 6px; flex: 1; min-width: 0 }
.sg-chip {
  flex: 1; min-width: 0; padding: 10px 0; border-radius: 9px; cursor: pointer;
  font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 700; font-size: 12.5px;
  background: rgba(255, 255, 255, .05); border: 1px solid var(--bord); color: var(--muted);
}
.sg-chip.on { background: rgba(45, 226, 197, .14); border-color: rgba(45, 226, 197, .5); color: var(--teal) }
.sg-own {
  width: 74px; flex: none; padding: 10px 6px; border-radius: 9px; text-align: center;
  background: rgba(255, 255, 255, .05); border: 1px solid var(--bord); color: var(--text);
  font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 700; font-size: 12.5px;
}
.sg-go, .sg-alt {
  padding: 11px 16px; border-radius: 11px; cursor: pointer; white-space: nowrap;
  font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 800; font-size: 14px; letter-spacing: .4px;
}
.sg-go {
  flex: 1; color: #08060f;
  background: linear-gradient(180deg, var(--gold), #e0972c); border: 0;
}
.sg-go.off, .sg-go[disabled] { background: rgba(255, 255, 255, .07); color: var(--dim); cursor: default }
.sg-alt { flex: none; background: rgba(255, 255, 255, .06); border: 1px solid var(--bord); color: var(--text) }

/* ── Флип ──────────────────────────────────────────────────────────────── */
.sg-flip-ask, .sg-ask {
  text-align: center; margin: 6px 0 12px; font-size: 13px; color: var(--muted); line-height: 1.35;
}
.sg-flip-hint { text-align: center; margin-top: 12px; font-size: 11px; color: var(--dim) }
.sg-hands { display: grid; grid-template-columns: 1fr 1fr; gap: 10px }
.sg-hand {
  display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 12px 8px;
  border-radius: 14px; cursor: pointer; color: var(--text);
  background: rgba(255, 255, 255, .045); border: 1px solid var(--bord);
}
.sg-hand small { font-size: 10.5px; color: var(--dim) }
.sg-hand b { font-size: 12.5px; font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 700 }
.sg-hand.done { cursor: default }
/* Выбор игрока обводится СРАЗУ — это его собственное решение, не новость. */
.sg-hand.picked { border-color: rgba(255, 194, 75, .55); box-shadow: 0 0 0 1px rgba(255, 194, 75, .25) }
/* А вот кто взял банк — только после ривера (flip.js: BEAT.verdict). Статикой
   эти два состояния объявляли победителя на первом же кадре, и прогон борда
   смотреть было незачем: ответ уже стоял на экране. */
@keyframes sg-won { to { background: rgba(45, 226, 197, .1); border-color: rgba(45, 226, 197, .45) } }
@keyframes sg-lost { to { opacity: .58 } }
.sg-hand.done.won { animation: sg-won .42s ease var(--v, 1.5s) both }
.sg-hand.done.lost { animation: sg-lost .42s ease var(--v, 1.5s) both }
.sg-hand-cards { display: flex; gap: 4px }
.sg-hand-cards .pc { --pc-w: 38px; --pc-h: 53px; --pc-rk: 16px; --pc-su: 12px; --pc-big: 18px }
.sg-board { display: flex; justify-content: center; gap: 4px; margin: 14px 0 }
.sg-board .pc { --pc-w: 34px; --pc-h: 47px; --pc-rk: 14px; --pc-su: 11px; --pc-big: 16px }
/* Прогнанный борд — главное на экране итога, и карты на нём крупнее, чем в
   разборе тренажёра: на них смотрят, а не сверяются с ними. */
.sg-board.run .pc { --pc-w: 50px; --pc-h: 70px; --pc-rk: 21px; --pc-su: 15px; --pc-big: 23px }
.sg-eq { text-align: center; font-size: 12.5px; color: var(--dim); margin: 10px 0 2px }
.sg-eq b { font-size: 16px; font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 800; color: var(--text) }

/* ── итог раунда ───────────────────────────────────────────────────────── */
.sg-outcome {
  display: flex; flex-direction: column; align-items: center; gap: 1px; margin: 14px 0 6px;
}
.sg-outcome b { font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 800; font-size: 30px; line-height: 1 }
.sg-outcome small { font-size: 11px; color: var(--dim) }
.sg-outcome.win b { color: var(--teal); text-shadow: 0 0 22px rgba(45, 226, 197, .45) }
.sg-outcome.lose b { color: var(--red) }
.sg-outcome.push b { font-size: 18px; color: var(--gold) }

/* ── Выше или ниже ─────────────────────────────────────────────────────── */
.sg-hilo-top, .sg-mines-top {
  display: flex; justify-content: space-between; gap: 8px; margin: 4px 0 10px;
  font-size: 11px; color: var(--dim);
}
.sg-hilo-top b, .sg-mines-top b { color: var(--text); font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 700; font-size: 13px }
.sg-mines-top .next b { color: var(--gold) }
.sg-current { display: flex; justify-content: center; margin: 6px 0 14px }
.sg-current .pc { --pc-w: 68px; --pc-h: 95px; --pc-rk: 28px; --pc-su: 20px; --pc-big: 32px }
.sg-guesses { display: grid; grid-template-columns: 1fr 1fr; gap: 9px }
.sg-guess {
  display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 13px 0;
  border-radius: 13px; cursor: pointer; color: var(--text);
  background: rgba(255, 255, 255, .05); border: 1px solid var(--bord);
}
.sg-guess b { font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 800; font-size: 15px }
.sg-guess small { font-size: 12px; color: var(--gold); font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 700 }
.sg-guess.hi { border-color: rgba(45, 226, 197, .35) }
.sg-guess.lo { border-color: rgba(255, 122, 158, .3) }
.sg-guess.off { opacity: .4; cursor: default }
.sg-steps { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 14px; justify-content: center }
.sg-step .pc { --pc-w: 22px; --pc-h: 30px; --pc-rk: 10px; --pc-su: 8px; --pc-big: 10px; border-radius: 4px }
.sg-step .pc .big { display: none }
.sg-step.bad { opacity: .45; filter: grayscale(.6) }
.sg-step.skip { opacity: .6 }

/* ── Сапёр ─────────────────────────────────────────────────────────────── */
.sg-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 5px; margin: 4px 0 }
.sg-cell {
  aspect-ratio: 3 / 4; display: flex; align-items: center; justify-content: center; padding: 0;
  border-radius: 7px; cursor: pointer; background: none; border: 0;
}
.sg-cell .pc { --pc-w: 100%; --pc-h: 100%; --pc-rk: 24px; --pc-su: 17px; --pc-big: 26px; border-radius: 7px }

/* РУБАШКА РАСТЁТ ВМЕСТЕ С КАРТОЙ. Клетка Сапёра (66×88) заметно крупнее карты
   на сукне (52×74), а гравюра каталога задана в пикселях — на клетке та же
   сетка читалась не как своя колода, а как редкая крошка по пустому фону
   («вообще не близка»). `--pat` увеличивает рисунок, `--emb` — герб: карта
   просто становится больше, а не разъезжается. Коэффициент — отношение клетки
   к карте на сукне. */
.sg-cell .pc.back > .cbk { --pat: 1.25; --emb: 30px }
.sg-cell.open, .sg-cell.rest, .sg-cell.joker, .sg-cell.boom { cursor: default }
/* Осталась закрытой: та же рубашка, только приглушённая — открытые карты
   рядом должны читаться первыми. */
.sg-cell.rest { opacity: .4 }
.sg-cell.joker, .sg-cell.boom {
  border-radius: 7px; background: rgba(255, 59, 92, .16); border: 1px solid rgba(255, 59, 92, .5); color: var(--red);
}
.sg-cell.joker i, .sg-cell.boom i { font-size: 22px }

/* ПОПАЛ В ДЖОКЕРА — это конец раунда и потеря ставки, и экран обязан это
   отыграть. Раньше проигрыш отличался от выигрыша только цветом рамки: та же
   сетка, та же неподвижность, и «мимо» приходилось вычитывать. Здесь бьёт
   клетка (вырастает и садится), вспыхивает её свечение, и вздрагивает вся
   сетка — три такта одного удара, полсекунды. Джокеры, которых игрок НЕ задел,
   открываются молча: они не событие, а справка. */
@keyframes sg-boom {
  0% { transform: scale(.62) rotate(-9deg); opacity: 0 }
  40% { transform: scale(1.2) rotate(5deg); opacity: 1 }
  66% { transform: scale(.95) rotate(-2deg) }
  100% { transform: scale(1) rotate(0) }
}
@keyframes sg-boom-glow {
  0% { box-shadow: 0 0 0 rgba(255, 59, 92, 0) }
  34% { box-shadow: 0 0 46px 11px rgba(255, 59, 92, .85) }
  100% { box-shadow: 0 0 18px rgba(255, 59, 92, .45) }
}
@keyframes sg-shake {
  0%, 100% { transform: translateX(0) }
  14% { transform: translateX(-7px) }
  30% { transform: translateX(6px) }
  46% { transform: translateX(-4px) }
  62% { transform: translateX(3px) }
  80% { transform: translateX(-2px) }
}
.sg-cell.boom { animation: sg-boom .5s cubic-bezier(.2, .9, .3, 1.3) both, sg-boom-glow .72s ease both }
.sg-grid.blown { animation: sg-shake .42s ease .12s both }

/* ── тренажёры ─────────────────────────────────────────────────────────── */
.sg-stats { display: flex; gap: 8px; margin-top: 4px }
.sg-stats span {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: 1px; padding: 9px 0;
  border-radius: 11px; background: rgba(255, 255, 255, .04); border: 1px solid var(--bord);
}
.sg-stats b { font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 800; font-size: 17px; color: var(--text) }
.sg-stats small { font-size: 9.5px; color: var(--dim) }
.sg-myhand { display: flex; align-items: center; justify-content: center; gap: 5px; margin: -6px 0 10px }
.sg-myhand small { font-size: 9.5px; letter-spacing: .6px; text-transform: uppercase; color: var(--dim); margin-right: 3px }
.sg-myhand .pc { --pc-w: 34px; --pc-h: 47px; --pc-rk: 14px; --pc-su: 11px; --pc-big: 16px }
.sg-opts { display: grid; grid-template-columns: 1fr 1fr; gap: 8px }
.sg-opt {
  display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 10px 6px;
  border-radius: 13px; cursor: pointer; color: var(--text);
  background: rgba(255, 255, 255, .05); border: 1px solid var(--bord);
}
.sg-opt.num b { font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 800; font-size: 24px }
.sg-opt b { font-size: 11.5px; font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 700; text-align: center }
.sg-opt small { font-size: 9.5px; color: var(--dim) }
.sg-opt small.right { color: var(--teal); font-weight: 700 }
.sg-opt.done { cursor: default }
.sg-opt.right { background: rgba(45, 226, 197, .12); border-color: rgba(45, 226, 197, .5) }
.sg-opt.wrong { background: rgba(255, 59, 92, .1); border-color: rgba(255, 59, 92, .45) }
.sg-verdict { display: flex; flex-direction: column; align-items: center; gap: 1px; margin: 2px 0 12px }
.sg-verdict b { font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 800; font-size: 22px; letter-spacing: .8px; text-transform: uppercase }
.sg-verdict small { font-size: 11px; color: var(--dim) }
.sg-verdict.ok b { color: var(--teal) }
.sg-verdict.bad b { color: var(--red) }
.sg-outs { margin-top: 14px; display: grid; gap: 9px }
.sg-outs-group small { display: block; font-size: 10px; letter-spacing: .5px; text-transform: uppercase; color: var(--dim); margin-bottom: 4px }
.sg-outs-fan { display: flex; flex-wrap: wrap; gap: 3px }
.sg-outs-fan .pc { --pc-w: 24px; --pc-h: 33px; --pc-rk: 11px; --pc-su: 8px; --pc-big: 11px; border-radius: 4px }
.sg-outs-fan .pc .big { display: none }

/* ── история и честность ───────────────────────────────────────────────── */
.sg-hnote { font-size: 11.5px; line-height: 1.4; color: var(--dim); margin: 2px 0 10px }
.sg-hrow {
  display: flex; align-items: center; gap: 8px; padding: 9px 10px; margin-bottom: 6px;
  border-radius: 11px; background: rgba(255, 255, 255, .04); border: 1px solid var(--bord); font-size: 12px;
}
.sg-hrow .g { flex: 1; min-width: 0; color: var(--text) }
.sg-hrow .m { color: var(--dim); font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 700 }
.sg-hrow .s { font-family: 'Rajdhani', system-ui, sans-serif; font-weight: 800; min-width: 54px; text-align: right }
.sg-hrow .s.win { color: var(--teal) }
.sg-hrow .s.lose { color: var(--red) }
.sg-hrow .s.push { color: var(--gold) }
.sg-hrow .d { flex: none; font-size: 10.5px; color: var(--dim); min-width: 38px; text-align: right }

/* Рельс на столе растягивает карточки на всю высоту колонки (styles/desktop.css):
   чат и журнал так и задуманы, а эта карточка — короткая врезка, и растянутая
   она читалась бы как пустая панель. */
@media (min-width: 1280px) {
  body[data-screen='game'] #rail .rc-sg { flex: none }
}

/* ── Флип: карты как содержимое экрана ─────────────────────────────────────
   Пустоту на листе убирает РАЗМЕР КАРТ, а не растянутые панели под ними: здесь
   карты и есть то, ради чего экран открыли — слепой выбор и прогон борда. */
.sg-flip .sg-hand-cards .pc { --pc-w: 58px; --pc-h: 80px; --pc-rk: 24px; --pc-su: 16px; --pc-big: 26px }
.sg-flip .sg-hand-cards .pc.back > .cbk { --pat: 1.1; --emb: 26px }

/* ── тихий режим ───────────────────────────────────────────────────────────
   Движение снимается целиком, СОДЕРЖИМОЕ ОСТАЁТСЯ: у `sg-in`/`sg-pop` нулевой
   кадр — прозрачность, и без анимации блок просто стоит на месте видимым. Итог
   вскрытия при этом виден сразу, без раскадровки, — так и задумано: человеку,
   который просил не двигать экран, нечего ждать полторы секунды. */
@media (prefers-reduced-motion: reduce) {
  .sg-in, .sg-pop, .sg-hand.done.won, .sg-hand.done.lost,
  .sg-cell.boom, .sg-grid.blown,
  #sgBody .pc.deal, #sgBody .pc.reveal { animation: none !important }
  .sg-cell.boom { box-shadow: 0 0 18px rgba(255, 59, 92, .45) }
  .sg-hand.done.won { background: rgba(45, 226, 197, .1); border-color: rgba(45, 226, 197, .45) }
  .sg-hand.done.lost { opacity: .58 }
}

/* ── широкий экран ─────────────────────────────────────────────────────────
   Лист лежит во всю ширину сукна (на 1440 это ~850 точек), и строка хаба
   растягивалась бы через весь экран: знак у левого края, состояние у правого,
   между ними полоса пустоты. Колонка ограничивается и встаёт по центру — той же
   ширины, что на планшете, где она и рисовалась. */
@media (min-width: 900px) {
  #sgBody .sg-scroll { width: 100%; max-width: 620px; margin-left: auto; margin-right: auto }
}
