:root {
  --felt: #125c3a;
  --felt-dark: #0a3a24;
  --panel: #101a14;
  --panel-soft: #17241c;
  --line: #26382c;
  --text: #e8f1ea;
  --muted: #8ba394;
  --gold: #e3b455;
  --danger: #e0645c;

  /* Карты растут вместе с окном: на большом мониторе значки и цифры должны
     быть читаемыми, а на телефоне хватает своих размеров. */
  --card-w: clamp(84px, calc(8.3vw - 34px), 124px);
  --card-h: calc(var(--card-w) * 1.4);
  --card-w-sm: calc(var(--card-w) * 0.85);
  --card-h-sm: calc(var(--card-w-sm) * 1.4);
  /* Рука тянется на всю ширину стола: десять карт должны занимать её целиком,
     как в настольных приложениях, а не теряться среди пустого сукна. */
  --hand-w: clamp(86px, calc(10vw - 40px), 148px);
}

* { box-sizing: border-box; }

/* Без этого правила display из .overlay и #game перебивает атрибут hidden,
   и скрытые блоки продолжают занимать экран. */
[hidden] { display: none !important; }

html, body {
  height: 100%;
  margin: 0;
}

body {
  background: radial-gradient(circle at 50% 0%, #1a2b21, #0a120d 70%);
  color: var(--text);
  font: 15px/1.45 "Segoe UI", system-ui, -apple-system, sans-serif;
  overflow: hidden;
}

button {
  font: inherit;
  color: var(--text);
  background: var(--panel-soft);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 7px 12px;
  cursor: pointer;
  transition: background .12s, border-color .12s, transform .06s;
}
button:hover { background: #21352a; border-color: #3a5544; }
button:active { transform: translateY(1px); }
button.primary { background: var(--gold); border-color: var(--gold); color: #1c1405; font-weight: 600; }
button.primary:hover { background: #f0c569; }
button.ghost { background: transparent; color: var(--muted); }
button.ghost:hover { color: var(--text); }

.muted { color: var(--muted); font-size: 13px; }
.status { color: var(--muted); font-size: 12px; margin: 10px 0 0; min-height: 16px; }
.error { color: var(--danger); margin: 8px 0 0; min-height: 20px; }
.empty { color: rgba(255, 255, 255, .28); font-size: 13px; }

/* --- вход --------------------------------------------------------------- */

.overlay {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgba(4, 9, 6, .78);
  backdrop-filter: blur(3px);
  z-index: 20;
}

.panel {
  width: min(380px, 92vw);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 26px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, .55);
}
.panel h1 { margin: 0 0 8px; font-size: 24px; letter-spacing: .5px; }
.hint { color: var(--muted); font-size: 13px; margin: 0 0 18px; }
.field { display: block; margin-bottom: 14px; }
.field span { display: block; font-size: 12px; color: var(--muted); margin-bottom: 6px; }
.field input {
  width: 100%;
  padding: 9px 11px;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: #0b120e;
  color: var(--text);
  font: inherit;
}
.field input:focus { outline: none; border-color: var(--gold); }
.panel .primary { width: 100%; padding: 10px; margin-top: 4px; }

/* --- каркас ------------------------------------------------------------- */

#game {
  height: 100%;
  height: 100dvh; /* на мобильных высота не прыгает из-за адресной строки */
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr) auto;
}

.topbar {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 14px;
  padding: 8px 14px;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
}
.brand { font-weight: 600; letter-spacing: .4px; white-space: nowrap; }
.brand .room { color: var(--gold); font-weight: 400; }
.actions { display: flex; gap: 8px; flex: 1 1 auto; flex-wrap: wrap; }
.conn { font-size: 12px; color: var(--muted); white-space: nowrap; margin-left: auto; }
.conn.up { color: #63c98a; }
.conn.down { color: var(--danger); }

.tableArea {
  grid-column: 1;
  grid-row: 2;
  min-height: 0;
  overflow: auto;
  display: flex;
  flex-direction: column;
  padding: 12px 14px;
  background:
    radial-gradient(ellipse at 50% 45%, var(--felt) 0%, var(--felt-dark) 75%);
  box-shadow: inset 0 0 90px rgba(0, 0, 0, .45);
}

/* Стол круглый: каждый игрок у своей стороны, я — внизу по центру,
   прикуп, сброс и кнопка взятки — в середине. */
.tableInner {
  position: relative;
  flex: 1 1 auto;
  min-height: 430px;
}

.zones { position: absolute; inset: 0; }

.zone {
  position: absolute;
  min-width: 0;
  background: rgba(6, 20, 13, .45);
  border: 1px solid rgba(255, 255, 255, .08);
  border-radius: 12px;
  padding: 8px 10px 10px;
}
/* Контейнером делаем только зону с открытой рукой: у остальных ширина
   считается по содержимому, а containment её бы обнулил. */
.zone.has-hand { container-type: inline-size; }
.zone.me { border-color: rgba(227, 180, 85, .55); background: rgba(6, 20, 13, .62); }
.zone.offline { opacity: .55; }

/* Места вокруг стола. Отступ от края держим в процентах, чтобы стол
   одинаково выглядел и на широком мониторе, и в узком окне. */
.zone.pos-bottom { left: 50%; bottom: 0; transform: translateX(-50%); max-width: min(46%, 430px); }
.zone.pos-top { left: 50%; top: 0; transform: translateX(-50%); max-width: min(46%, 430px); }
.zone.pos-left { left: 0; top: 50%; transform: translateY(-50%); max-width: min(24%, 250px); }
.zone.pos-right { right: 0; top: 50%; transform: translateY(-50%); max-width: min(24%, 250px); }
.zone.pos-top-left { left: 0; top: 0; max-width: min(30%, 300px); }
.zone.pos-top-right { right: 0; top: 0; max-width: min(30%, 300px); }
.zone.pos-bottom-left { left: 0; bottom: 0; max-width: min(30%, 300px); }
.zone.pos-bottom-right { right: 0; bottom: 0; max-width: min(30%, 300px); }

/* Открытая чужая рука тянется вдоль края: у верхних и нижних зона становится
   шире, у боковых — выше. Закрытые зоны при этом остаются компактными,
   иначе на столе появлялись бы большие пустые панели. */
.zones.wide-seats .zone.has-hand.pos-top,
.zones.wide-seats .zone.has-hand.pos-bottom {
  left: 21%;
  right: 21%;
  max-width: none;
  /* Убираем старый сдвиг по центру: иначе зона уезжает за край экрана. */
  transform: none;
}
.zones.wide-seats .zone.has-hand.pos-top-left { right: 50%; max-width: none; }
.zones.wide-seats .zone.has-hand.pos-top-right { left: 50%; max-width: none; }
.zones.wide-seats .zone.has-hand.pos-bottom-left { right: 50%; max-width: none; }
.zones.wide-seats .zone.has-hand.pos-bottom-right { left: 50%; max-width: none; }
/* Раскрытая рука сбоку — компактный блок: строка на масть, карты внутри
   строки заходят друг за друга на треть. Зона обнимает блок и жмётся к краю
   по центру высоты: раньше она тянулась на пол-экрана, а карты сбивались
   в верхний угол. Размер карты считает app.js от свободного места на столе
   (fitSideHands) и кладёт в --mini-w; здесь только запасное значение, пока
   размер ещё не посчитан. Считать его от ширины зоны нельзя: зона обнимает
   содержимое, и вышел бы замкнутый круг (containment пришлось снять). */
.zones.wide-seats .zone.has-hand.pos-left,
.zones.wide-seats .zone.has-hand.pos-right {
  --mini-w: clamp(24px, 5vw, 56px);
  --mini-overlap: calc(var(--mini-w) * .35);
  container-type: normal;
  top: 50%;
  bottom: auto;
  width: max-content;
  /* Шапка зоны («открыты · 10 в руке») шире блока карт: без минимума она
     обрезалась бы. Максимум — треть стола: дальше уже середина с прикупом. */
  min-width: min(40vw, 168px);
  max-width: min(32vw, 380px);
  height: auto;
  transform: translateY(-50%);
}
.zones.wide-seats .zone.has-hand.pos-left { right: auto; }
.zones.wide-seats .zone.has-hand.pos-right { left: auto; }

.zones.wide-seats .zone.has-hand.pos-left .miniHand,
.zones.wide-seats .zone.has-hand.pos-right .miniHand {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
  width: max-content;
  max-width: 100%;
  padding: 0;
}
/* Короткая масть прижимается к тому же краю, что и остальные строки. */
.zones.wide-seats .zone.has-hand.pos-right .miniHand { align-items: flex-end; }

.zones.wide-seats .zone.has-hand.pos-left .suitGroup,
.zones.wide-seats .zone.has-hand.pos-right .suitGroup {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 0;
}

.zones.wide-seats .zone.has-hand.pos-left .mini,
.zones.wide-seats .zone.has-hand.pos-right .mini {
  flex: none;
  width: var(--mini-w);
  height: auto;
  aspect-ratio: 5 / 7;
  margin: 0;
}
.zones.wide-seats .zone.has-hand.pos-left .mini + .mini,
.zones.wide-seats .zone.has-hand.pos-right .mini + .mini {
  margin-left: calc(var(--mini-overlap) * -1);
}

/* Полоса верхней и нижней руки начинается за боковой зоной, а не на
   фиксированных 21%: иначе на средних ширинах панели налезали друг на друга. */
@media (min-width: 761px) {
  .zones.wide-seats .zone.has-hand.pos-top,
  .zones.wide-seats .zone.has-hand.pos-bottom {
    left: max(21%, 208px);
    right: max(21%, 208px);
  }
}

.zoneHead {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 6px;
  margin-bottom: 7px;
}
.zoneRight { display: flex; align-items: center; gap: 8px; margin-left: auto; }
.zoneOpen {
  flex: none;
  font-size: 10px;
  color: var(--gold);
  border: 1px solid rgba(227, 180, 85, .45);
  border-radius: 20px;
  padding: 1px 7px;
  white-space: nowrap;
}
.zoneName { font-weight: 600; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.zone.offline .zoneName::after { content: " · отошёл"; color: var(--danger); font-weight: 400; font-size: 11px; }
.zone.taker .zoneName::after { content: " · прикуп"; color: var(--gold); font-weight: 400; font-size: 11px; }
/* Чей ход — видно по золотой рамке и пометке. */
.zone.turn { border-color: rgba(227, 180, 85, .7); box-shadow: 0 0 0 1px rgba(227, 180, 85, .35); }
.zone.turn .zoneName::after { content: " · ходит"; color: var(--gold); font-weight: 400; font-size: 11px; }
.zoneCount {
  flex: none;
  font-size: 11px;
  color: rgba(255, 255, 255, .78);
  background: rgba(255, 255, 255, .08);
  border-radius: 20px;
  padding: 2px 8px;
  white-space: nowrap;
}

.slots { display: flex; flex-direction: column; gap: 5px; }

/* Взятки — мелкой стопкой в шапке зоны, рядом со счётчиком карт. */
.miniGroup { display: flex; align-items: center; gap: 7px; }
.miniStack { display: flex; align-items: center; gap: 2px; }
/* Открытая чужая рука: масти идут своими стопками, а размер карт считается
   от ширины зоны — рука должна занимать её почти целиком. */
.miniHand {
  --cards: var(--hand-all, 10);
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 8px 14px;
}
.suitGroup { display: flex; align-items: flex-start; gap: 3px; }
.miniHand .mini {
  flex: 0 0 auto;
  width: clamp(26px, calc((100cqw - 60px) / var(--cards)), var(--hand-w));
  height: auto;
  aspect-ratio: 5 / 7;
  border-radius: 4px;
}
.miniHand .mini + .mini { margin-left: 0; }

/* Рука тянется вдоль края, поэтому у верхних мест зона шире: иначе карты
   переносятся на вторую строку и зона налезает на середину стола. */
.zone.has-hand.pos-top,
.zone.has-hand.pos-top-left,
.zone.has-hand.pos-top-right { max-width: min(58%, 640px); }
.mini {
  display: block;
  width: 30px;
  height: 42px;
  border-radius: 3px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .45);
}
.mini + .mini { margin-left: -9px; }
.miniCount { font-size: 12px; color: var(--gold); margin-left: 3px; }

/* Середина стола: сюда ложатся карты, которыми ходят, и тут же снос и кнопки.
   Ширину подбираем так, чтобы блок не наезжал на зоны игроков по бокам. */
.middle {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  max-width: min(58%, 520px);
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: center;
  padding: 10px 14px;
  border-radius: 14px;
  background: rgba(6, 20, 13, .38);
  border: 1px dashed rgba(255, 255, 255, .12);
}
.controls {
  display: flex;
  gap: 10px 14px;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
}

/* Карты в ход раскладываются по сторонам: каждая со стороны своего игрока.
   Имя подписано, но и по месту видно, чья это карта. */
.played {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-template-areas:
    "p-tl p-t  p-tr"
    "p-l  .    p-r"
    "p-bl p-b  p-br";
  gap: 4px 16px;
  justify-items: center;
  align-items: center;
}
.playedBox { display: flex; flex-direction: column; align-items: center; gap: 3px; }
.playedBox.pos-top-left { grid-area: p-tl; }
.playedBox.pos-top { grid-area: p-t; }
.playedBox.pos-top-right { grid-area: p-tr; }
.playedBox.pos-left { grid-area: p-l; }
.playedBox.pos-right { grid-area: p-r; }
.playedBox.pos-bottom-left { grid-area: p-bl; }
.playedBox.pos-bottom { grid-area: p-b; }
.playedBox.pos-bottom-right { grid-area: p-br; }
.playedName {
  font-size: 11px;
  color: rgba(255, 255, 255, .7);
  max-width: 90px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Что было в прикупе: уголком, и только до первой взятки. */
.talonNote {
  position: absolute;
  left: 4px;
  bottom: 4px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 6px 9px;
  border-radius: 10px;
  background: rgba(6, 20, 13, .45);
  border: 1px dashed rgba(255, 255, 255, .12);
}
.talonNote .cards { gap: 4px; }
.talonNote .card.small { width: 34px; height: 48px; }
/* Прикуп в центре — карты чуть меньше остальных на столе, иначе блок
   не влезает в строку. Только для широкого стола: на телефоне свой размер. */
@media (min-width: 861px) {
  .middle .card.small {
    width: calc(var(--card-w-sm) * 0.88);
    height: calc(var(--card-w-sm) * 0.88 * 1.4);
  }
}
.pileBox { display: flex; flex-direction: column; gap: 5px; min-width: 96px; }
.pileLabel { font-size: 11px; text-transform: uppercase; letter-spacing: .08em; color: rgba(255, 255, 255, .55); }
.pileValue { font-size: 22px; color: var(--gold); }
.cards { display: flex; flex-wrap: wrap; gap: 5px; align-items: flex-start; }

.takeBox {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  text-align: center;
  max-width: 340px;
}
.takeBox .muted { font-size: 12.5px; color: rgba(255, 255, 255, .72); }

.handArea {
  grid-column: 1;
  grid-row: 3;
  padding: 8px 14px 12px;
  background: var(--panel);
  border-top: 1px solid var(--line);
}
.areaHead { display: flex; align-items: baseline; gap: 10px; margin-bottom: 6px; }
.hand { min-height: var(--card-h); padding: 2px 0; }

/* На широком столе карты в руке сами делят ширину: десять карт занимают её
   целиком, двенадцать — чуть теснее, а четыре не раздуваются сверх меры.
   Высота строки держится по самой крупной карте, чтобы стол не дёргался. */
@media (min-width: 761px) {
  .hand {
    flex-wrap: nowrap;
    justify-content: center;
    align-items: center;
    gap: 5px;
    min-height: calc(var(--hand-w) * 1.4);
  }
  .hand > .card {
    flex: 1 1 auto;
    min-width: 0;
    width: auto;
    height: auto;
    max-width: var(--hand-w);
    aspect-ratio: 5 / 7;
  }
}



/* Журнал с болтовнёй выезжает справа по кнопке и места в раскладке
   не занимает: пока он закрыт, стол работает на всю ширину. */
.side {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(360px, 88vw);
  z-index: 15;
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--panel);
  border-left: 1px solid var(--line);
  padding: 12px;
  gap: 4px;
  transform: translateX(102%);
  transition: transform .22s ease;
  box-shadow: -16px 0 34px rgba(0, 0, 0, .5);
}
body.log-open .side { transform: translateX(0); }
.sideHead { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 6px; }
.sideHead button { padding: 2px 9px; font-size: 17px; line-height: 1.1; }
.log, .chat { list-style: none; margin: 0 0 10px; padding: 0; overflow: auto; font-size: 13px; }
.log { flex: 1 1 50%; color: var(--muted); }
.chat { flex: 1 1 30%; }
.log li, .chat li { padding: 3px 0; border-bottom: 1px solid rgba(255, 255, 255, .04); overflow-wrap: anywhere; }
.chat li b { color: var(--gold); font-weight: 600; }
.chatForm { display: flex; gap: 6px; }
.chatForm input {
  flex: 1;
  min-width: 0;
  padding: 8px 10px;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: #0b120e;
  color: var(--text);
  font: inherit;
}
.chatForm input:focus { outline: none; border-color: var(--gold); }

/* --- карты -------------------------------------------------------------- */

/* Полотно карты рисует SVG (250×350), поэтому у рамки нет ни фона,
   ни своей рамки — только тень и подсветка выбора. */
.card {
  position: relative;
  flex: 0 0 auto;
  width: var(--card-w);
  height: var(--card-h);
  padding: 0;
  border: none;
  border-radius: 5px;
  background: none;
  box-shadow: 0 3px 7px rgba(0, 0, 0, .35);
  user-select: none;
}
.card .face { display: block; width: 100%; height: 100%; }

.card.small { width: var(--card-w-sm); height: var(--card-h-sm); border-radius: 4px; }
.card.small.dim { opacity: .92; }

button.card { cursor: pointer; }
button.card:hover { transform: translateY(-6px); box-shadow: 0 9px 16px rgba(0, 0, 0, .45); }
.card.small.dim:hover { transform: none; }

/* Карты, отложенные в снос: подняты и обведены, пока снос не подтверждён. */
.card.picked {
  transform: translateY(-9px);
  box-shadow: 0 0 0 3px var(--gold), 0 8px 16px rgba(0, 0, 0, .5);
}
button.card.picked:hover { transform: translateY(-9px); }

.card.back { box-shadow: 0 2px 4px rgba(0, 0, 0, .35); }

/* --- всплывающее сообщение --------------------------------------------- */

.toast {
  position: fixed;
  left: 50%;
  bottom: 26px;
  transform: translateX(-50%);
  background: rgba(224, 100, 92, .95);
  color: #fff;
  padding: 9px 16px;
  border-radius: 10px;
  font-size: 14px;
  z-index: 30;
  box-shadow: 0 10px 26px rgba(0, 0, 0, .45);
}

/* --- планшет и телефон --------------------------------------------------- */

@media (max-width: 860px) {
  .log { flex: 1 1 40%; }
  .column-hint { display: none; }
  /* В списке игроков середина стола стоит первой, поэтому карты в ход
     оказываются как раз между рядами игроков. */
  .middle { max-width: min(94%, 520px); }

  /* Круг остаётся и на телефоне: карты соперников ложим по краям экрана,
     а не строками. Места мало, поэтому и зоны, и карты мельче. */
  .tableInner { min-height: 320px; }
  .middle { max-width: 78%; }
}

@media (max-width: 760px) {
  :root {
    --card-w: 56px;
    --card-h: 78px;
    --card-w-sm: 48px;
    --card-h-sm: 67px;
  }


  /* Панель в две строки: название с состоянием связи, под ними кнопки.
     Сетка, а не флекс: у флекса строка с flex-basis не помещалась и кнопки
     уезжали за правый край. */
  .topbar {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "brand conn"
      "actions actions";
    gap: 6px;
    padding: 6px 10px;
  }
  .brand { grid-area: brand; font-size: 14px; }
  .conn { grid-area: conn; margin-left: 0; }
  .actions { grid-area: actions; display: flex; flex-wrap: wrap; gap: 6px; }
  .actions button { flex: 1 1 auto; padding: 6px 8px; font-size: 12.5px; white-space: nowrap; }
  .hide-sm { display: none; }

  .tableArea { padding: 10px; }
  .tableInner { gap: 8px; }

  /* На телефоне стол — список игроков: одна строка на игрока.
     В коробках на весь экран всё не помещалось и уезжало за край. */
  .zone {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 10px;
    padding: 5px 9px 6px;
  }
  .zoneHead { justify-content: flex-start; margin-bottom: 0; gap: 6px; }
  .zoneName { font-size: 13px; }
  /* Боковая зона узкая: длинная подпись должна переноситься, а не уезжать
     за край экрана (так было с «карта прикупа» в распасах). */
  .zone { overflow: hidden; }
  .zoneRight { min-width: 0; }
  .zoneCount { white-space: normal; }
  /* Слоты занимают всю ширину строки: иначе карты упираются в край экрана
     и не переносятся. */
  .slots { flex: 1 1 100%; min-width: 0; }
  .mini { width: 26px; height: 36px; }
  .mini + .mini { margin-left: -10px; }

  /* --- открытая рука соперника на телефоне ------------------------------ */
  /* Карты крупные и идут наполовину друг за другом: чем больше карт, тем
     плотнее они заходят, но видно уголок с мастью у каждой. Строки (столбик)
     и столбцы (ряд) грид делит поровну по свободному месту зоны, поэтому
     рука влезает всегда — считать размер карты вручную не нужно. */
  .zones.wide-seats .zone.has-hand.pos-top,
  .zones.wide-seats .zone.has-hand.pos-top-left,
  .zones.wide-seats .zone.has-hand.pos-top-right,
  .zones.wide-seats .zone.has-hand.pos-bottom,
  .zones.wide-seats .zone.has-hand.pos-bottom-left,
  .zones.wide-seats .zone.has-hand.pos-bottom-right {
    flex-direction: column;
    align-items: stretch;
    /* Перенос выключаем: в столбик подпись и рука должны идти друг под другом,
       иначе рука уезжает во второй столбец за пределы зоны. */
    flex-wrap: nowrap;
  }
  /* Соперник сверху: рука идёт вдоль верхнего края одним рядом, карты заходят
     друг за друга наполовину. Размер считает app.js от ширины зоны. */
  .zones.wide-seats .zone.has-hand.pos-top .miniHand,
  .zones.wide-seats .zone.has-hand.pos-top-left .miniHand,
  .zones.wide-seats .zone.has-hand.pos-top-right .miniHand,
  .zones.wide-seats .zone.has-hand.pos-bottom .miniHand,
  .zones.wide-seats .zone.has-hand.pos-bottom-left .miniHand,
  .zones.wide-seats .zone.has-hand.pos-bottom-right .miniHand {
    display: flex;
    flex-wrap: nowrap;
    align-items: flex-start;
    gap: 0;
    width: 100%;
    /* Отступ слева гасит сдвиг первой карты: она тоже идёт с минус-отступом. */
    padding-left: var(--mini-overlap, 0);
  }
  .zones.wide-seats .zone.has-hand .miniHand .mini {
    flex: none;
    width: var(--mini-w, 26px);
    height: auto;
    aspect-ratio: 5 / 7;
  }

  /* Соперник сбоку и на телефоне — тот же компактный блок из строк по мастям:
     раскладку и размер карт задают правила выше, здесь их переопределять
     нечем. Раньше тут была вытянутая зона во весь край. */
  .zones.wide-seats .zone.has-hand.pos-top .miniHand .mini,
  .zones.wide-seats .zone.has-hand.pos-top-left .miniHand .mini,
  .zones.wide-seats .zone.has-hand.pos-top-right .miniHand .mini,
  .zones.wide-seats .zone.has-hand.pos-bottom .miniHand .mini,
  .zones.wide-seats .zone.has-hand.pos-bottom-left .miniHand .mini,
  .zones.wide-seats .zone.has-hand.pos-bottom-right .miniHand .mini {
    margin-left: calc(var(--mini-overlap, 0) * -1);
  }

  /* Верхняя и нижняя рука ложится одним веером: коробки мастей разбираем.
     Боковые строки, наоборот, оставляем отдельными — по строке на масть. */
  .zones.wide-seats .zone.has-hand:not(.pos-left):not(.pos-right) .suitGroup {
    display: contents;
  }

  .middle { gap: 8px 10px; padding: 8px 10px; }
  /* Прикуп и сброс держим в одну строку — столбиком они съедают пол-экрана. */
  .middle .cards { flex-wrap: nowrap; }
  .pileBox { min-width: 0; }
  /* Кнопка — на своей строке во всю ширину. В одну строку с прикупом она
     обрезалась справа, а так помещается всегда и удобна для пальца. */
  .takeBox { flex: 1 1 100%; margin-left: 0; align-items: stretch; text-align: center; max-width: none; }
  .takeBox .primary { width: 100%; }
  .takeBox .muted { text-align: center; }

  .handArea { padding: 6px 8px 8px; }
  /* Веер: карты заходят друг на друга, видно уголок с мастью.
     Шаг веера считает app.js (--fan-step) от ширины экрана, чтобы весь веер
     помещался целиком и прокручивать было нечего; auto-отступы центрируют его.
     Прокрутка оставлена только как страховка, если шаг почему-то не посчитан. */
  .hand { flex-wrap: nowrap; overflow-x: auto; }
  .hand > .card + .card { margin-left: calc(var(--fan-step, 32px) - var(--card-w)); }
  .hand > .card:first-child { margin-left: auto; }
  .hand > .card:last-child { margin-right: auto; }
  .hand > .empty { margin: 0 auto; }
}
