/* «Блоки» — игра-передышка со словами.

   Экран занимает высоту целиком и не прокручивается: прокрутка во время
   перетаскивания фигуры означает, что поле уезжает из-под пальца. Поэтому
   размер поля считается от меньшего из ширины и высоты, а не задаётся
   числом. */

.game-screen {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--gap-sm);
  padding: calc(var(--safe-top) + 8px) 12px calc(var(--safe-bottom) + 10px);
  min-height: 100dvh;
  /* Ни прокрутки, ни «потянуть, чтобы обновить»: и то и другое перехватывает
     жест, которым кладут фигуру. */
  overscroll-behavior: none;
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

/* Поле и лоток мерятся от одной величины: клетка лотка ровно вдвое меньше
   клетки поля, и фигура при подъёме вырастает предсказуемо. */
.game-screen {
  --board: min(92vw, 52vh, 440px);
  --cell: calc(var(--board) / 8);
}

.game-top {
  display: flex;
  align-items: center;
  gap: 10px;
  width: var(--board);
  max-width: 100%;
}

.game-score {
  font-size: var(--size-title);
  font-weight: 700;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}

/* Скрытый — значит скрытый. Собственный display перебивает [hidden] из
   правил браузера, и значок серии висел бы над счётом всегда. */
.game-combo[hidden] {
  display: none;
}

.game-combo {
  display: inline-block;
  margin-left: 8px;
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  background: var(--warning-soft);
  color: var(--warning);
  font-size: var(--size-micro);
  font-weight: 700;
}

.game-top .caption[data-fresh="true"] {
  color: var(--positive);
  font-weight: 700;
}

/* ------------------------------------------------------------------ поле */

.game-board {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  grid-auto-rows: 1fr;
  gap: 2px;
  width: var(--board);
  height: var(--board);
  padding: 4px;
  border-radius: var(--radius-lg);
  background: var(--glass-fill-sunken);
  border: 1px solid var(--glass-edge);
  box-shadow: var(--shadow-inset);
}

.game-cell {
  border-radius: 4px;
  background: var(--level-0);
  transition: background var(--fast) var(--ease), transform var(--fast) var(--ease);
}

/* Цвета фигур.

   Шесть оттенков, различимых и в светлой теме, и в тёмной. Взяты не из
   палитры смыслов приложения (зелёный «верно», красный «ошибка»): в игре они
   не значат ничего, кроме «это другая фигура», и путать их со смыслом
   нельзя. */
.game-screen {
  --piece-1: #4f6ef7;
  --piece-2: #f2994a;
  --piece-3: #27ae8f;
  --piece-4: #c86dd7;
  --piece-5: #f2c14e;
  --piece-6: #ef6f6c;
}

.game-cell[data-filled="true"] {
  background: var(--accent);
  box-shadow: inset 0 1px 0 var(--glass-edge-strong);
}

.game-cell[data-filled="true"][data-color="1"] { background: var(--piece-1); }
.game-cell[data-filled="true"][data-color="2"] { background: var(--piece-2); }
.game-cell[data-filled="true"][data-color="3"] { background: var(--piece-3); }
.game-cell[data-filled="true"][data-color="4"] { background: var(--piece-4); }
.game-cell[data-filled="true"][data-color="5"] { background: var(--piece-5); }
.game-cell[data-filled="true"][data-color="6"] { background: var(--piece-6); }

.game-piece[data-color="1"] .game-block { background: var(--piece-1); }
.game-piece[data-color="2"] .game-block { background: var(--piece-2); }
.game-piece[data-color="3"] .game-block { background: var(--piece-3); }
.game-piece[data-color="4"] .game-block { background: var(--piece-4); }
.game-piece[data-color="5"] .game-block { background: var(--piece-5); }
.game-piece[data-color="6"] .game-block { background: var(--piece-6); }

/* Куда ляжет фигура. Перебивает цвет клетки: подсказку надо видеть на любом
   фоне, а не только на пустом. */
.game-cell[data-preview="piece"],
.game-cell[data-filled][data-preview="piece"] {
  background: var(--accent-soft);
  outline: 1px solid var(--accent);
}

/* Что от этого сгорит. Видно до броска — в этом и состоит игра. */
.game-cell[data-preview="burn"],
.game-cell[data-filled][data-preview="burn"] {
  background: var(--positive-soft);
  outline: 1px solid var(--positive);
}

.game-cell[data-burn="true"],
.game-cell[data-filled][data-burn="true"] {
  background: var(--positive);
  transform: scale(0.72);
}


/* ----------------------------------------------------------------- лоток */

.game-tray {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  align-items: center;
  justify-items: center;
  gap: 6px;
  width: var(--board);
  min-height: calc(var(--cell) * 2.6);
  padding: 6px;
  border-radius: var(--radius-lg);
  background: var(--glass-fill);
  border: 1px solid var(--glass-edge);
  touch-action: none;
}

.game-slot {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: calc(var(--cell) * 2.5);
  transition: opacity var(--fast) var(--ease);
}

/* Фигура, которой некуда лечь, гаснет. Это не подсказка, а честность: иначе
   человек ищет для неё место, которого нет. */
.game-slot[data-playable="false"] {
  opacity: 0.34;
}

.game-slot[data-dragging="true"] {
  opacity: 0.2;
}

.game-piece {
  display: grid;
  gap: 2px;
}

.game-slot .game-piece {
  grid-auto-rows: calc(var(--cell) * 0.5);
}

.game-slot .game-piece > * {
  width: calc(var(--cell) * 0.5);
  height: calc(var(--cell) * 0.5);
}

.game-block {
  border-radius: 4px;
  background: var(--accent-strong);
  box-shadow: inset 0 1px 0 var(--glass-edge-strong);
}

.game-hole {
  background: none;
}

/* Фигура в полёте. Живёт в body, а не в экране: внутри сетки её обрезал бы
   край поля ровно в тот момент, когда целишься в крайний столбец. */
.game-ghost {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 60;
  pointer-events: none;
  will-change: transform;
}

.game-ghost .game-piece {
  gap: 2px;
}

/* Фигура, которой сюда нельзя, краснеет — цвет самой фигуры при этом не в
   счёт: «не влезает» важнее, чем «она оранжевая». */
.game-ghost[data-ok="false"] .game-piece .game-block,
.game-ghost[data-ok="false"] .game-block {
  background: var(--negative);
}

/* ----------------------------------------------------------------- слово */

/* Место под слово занято всегда, даже когда слова нет.
   Иначе появление пузырька сдвигает поле на десятки точек — под пальцем, в
   середине хода. */
.game-word {
  position: relative;
  width: var(--board);
  min-height: 108px;
  padding: 10px 10px 8px;
  border-radius: var(--radius-lg);
  background: var(--glass-fill-strong);
  border: 1px solid var(--glass-edge);
  backdrop-filter: blur(var(--glass-blur-soft));
  -webkit-backdrop-filter: blur(var(--glass-blur-soft));
  animation: word-in 180ms var(--ease);
}

/* Пока слова нет — рамка стоит, но не кричит: место занято, а внимания не
   просит. */
.game-word[data-state="idle"] {
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border-style: dashed;
  border-color: var(--glass-edge);
  animation: none;
}

.game-word-hint {
  color: var(--text-faint);
  font-size: var(--size-micro);
  text-align: center;
}

.game-word[data-state="live"] .game-word-hint {
  display: none;
}

@keyframes word-in {
  from {
    opacity: 0;
    transform: translateY(-6px);
  }
}

.game-word-timer {
  position: absolute;
  left: 0;
  top: 0;
  height: 3px;
  width: 100%;
  transform-origin: left center;
  border-radius: var(--radius-pill);
  background: var(--accent);
}

.game-word-term {
  margin-bottom: 8px;
  text-align: center;
  font-size: var(--size-section);
  font-weight: 700;
}

.game-word-options {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
}

.game-option {
  min-height: 40px;
  padding: 6px 8px;
  border-radius: var(--radius-md);
  font-size: var(--size-micro);
  line-height: 1.2;
  color: var(--text);
  text-align: center;
}

.game-option[data-state="waiting"] {
  opacity: 0.6;
}

.game-option[data-state="correct"] {
  background: var(--positive-soft);
  border-color: var(--positive);
  color: var(--positive);
  font-weight: 700;
}

.game-option[data-state="wrong"] {
  background: var(--negative-soft);
  border-color: var(--negative);
  color: var(--negative);
}

/* ------------------------------------------------------------------ итог */

.game-over {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(4, 7, 16, 0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  animation: word-in 200ms var(--ease);
}

.game-over-card {
  max-width: 340px;
  text-align: center;
}

.game-over-title {
  font-size: var(--size-section);
  font-weight: 700;
  color: var(--accent-strong);
}

.game-score-big,
.game-record-big {
  font-size: var(--size-hero);
  font-weight: 800;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}

/* ----------------------------------------------------------- перед игрой */

.game-deck-row {
  display: flex;
  align-items: center;
  gap: 12px;
  cursor: pointer;
}

.game-deck-row input {
  width: 22px;
  height: 22px;
  accent-color: var(--accent);
}

/* Тому, кто просил меньше движения, движения и не будет.
   Заодно это единственный способ снять анимацию в безголовом браузере: он
   рисует кадры по требованию, и запущенная анимация застревает на первом
   кадре — то есть на прозрачности ноль. */
@media (prefers-reduced-motion: reduce) {
  .game-word,
  .game-over {
    animation: none;
  }

  .game-cell,
  .game-slot {
    transition: none;
  }
}
