/* Игры: колесо, найди пару, лопни шар, открой коробку.
 *
 * Слой для js/games.js. Подключается после a11y.css — значит, при равном
 * весе побеждают правила отсюда, и переопределять ничего не приходится.
 *
 * Цвета только из tokens.css: ни одного шестнадцатеричного значения.
 * Движение — только transform и opacity: сайт открывают на дешёвых
 * школьных телефонах, а всё остальное заставляет их перерисовывать слой
 * целиком на каждом кадре.
 *
 * Общий язык кликабельной плитки взят у .mcq-option: белая поверхность,
 * рамка 1.5px цветом --line, при наведении — мягкая подложка акцента.
 * Заведись здесь своя манера, игры выглядели бы приклеенными сбоку.
 */

/* ==========================================================================
   1. КОЛЕСО
   ========================================================================== */

.wheel-card { text-align: center; padding: var(--space-24) var(--space-16); }

/* 300px, а не «сколько влезет». Колесо и кнопки «знал / не знал» обязаны
   помещаться в один экран: если за ответом надо прокручивать, ученик
   отвечает вслепую или не отвечает вовсе. */
.wheel-wrap {
  position: relative;
  width: min(300px, 100%);
  aspect-ratio: 1;
  margin-inline: auto;
}

/* Указатель. Стоит НАД колесом и врезается в него сверху: иначе непонятно,
   какой из секторов выпал — соседние границы расходятся на пару градусов. */
.wheel-pin {
  position: absolute;
  top: -4px;
  left: 50%;
  z-index: 2;
  width: 0;
  height: 0;
  transform: translateX(-50%);
  border-left: 9px solid transparent;
  border-right: 9px solid transparent;
  border-top: 18px solid var(--ink);
}

.wheel-turn {
  transform-origin: 50% 50%;
  will-change: transform;
}

.wheel-svg { display: block; width: 100%; height: auto; }

/* Сектор — заливка из JS (три тона по очереди), тонкая разделительная линия.
   Толщина в единицах viewBox, а не в пикселях: колесо масштабируется. */
.wheel-sectors path {
  stroke: var(--line-soft);
  stroke-width: 0.8;
}

.wheel-sectors text {
  fill: var(--ink);
  font-family: var(--font-display);
  font-weight: 800;
  text-anchor: middle;
  dominant-baseline: central;
}

.wheel-rim {
  fill: none;
  stroke: var(--line-control);
  stroke-width: 1.6;
}

/* Втулка. Держит центр: без неё сектора сходятся в точку, и колесо
   выглядит недорисованным. */
.wheel-hub {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 17%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: var(--surface);
  border: 1.5px solid var(--line-control);
}

.wheel-panel { margin-top: var(--space-16); }
.wheel-panel .quiz-word { margin-bottom: var(--space-12); }
.wheel-wait { margin: var(--space-24) 0; }
.wheel-acts { margin-top: var(--space-8); flex-wrap: wrap; }
.wheel-acts .btn { min-width: 0; }

.wheel-answer {
  display: inline-block;
  margin: var(--space-12) 0 0;
  padding: var(--space-8) var(--space-16);
  border-radius: var(--radius-tag);
  background: var(--accent-soft);
  border: 1.5px solid var(--accent-line);
  color: var(--accent-deep);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--text-body-sm);
}


.wheel-panel .btn-wide { width: min(280px, 100%); }

/* ==========================================================================
   2. НАЙДИ ПАРУ
   ========================================================================== */

.mem-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-8);
  max-width: 560px;
  margin-inline: auto;
}
@media (min-width: 560px) {
  .mem-grid { grid-template-columns: repeat(4, 1fr); gap: var(--space-12); }
}

/* На телефоне карточка КВАДРАТНАЯ, а не карточной пропорции 3:4. Двенадцать
   вытянутых карточек занимают 605px — нижний ряд уходит под меню, и игру
   на память приходится играть с прокруткой, то есть не видя половину поля.
   Пропорция здесь дешевле: она стоит вида «колоды», а прокрутка — самой
   механики. На широком экране рядов три, и карточка возвращает себе рост. */
.mem-card {
  position: relative;
  aspect-ratio: 1;
  padding: 0;
  border: none;
  background: none;
  border-radius: var(--radius-input);
  font: inherit;
  perspective: 700px;
}
@media (min-width: 560px) { .mem-card { aspect-ratio: 3 / 4; } }

.mem-inner {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transition: transform var(--dur) var(--ease);
}
.mem-card.open .mem-inner,
.mem-card.done .mem-inner { transform: rotateY(180deg); }

.mem-face {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  padding: var(--space-8) var(--space-4);
  border-radius: var(--radius-input);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  font-family: var(--font-display);
  font-weight: 800;
  /* Ниже шкалы на телефоне: 16px внутри 101-пиксельной карточки разрывает
     «предпочитать» посреди слова. Тянется до 16px, как только место есть. */
  font-size: clamp(13px, 3.4vw, 16px);
  line-height: var(--leading-tight);
  text-align: center;
  overflow-wrap: anywhere;
}

/* Рубашка. Лапа, а не цифра: номер карточки нужен скринридеру (он в
   aria-label), а глазу он подсказывал бы порядок, которого в игре нет. */
.mem-back {
  background: var(--accent-soft);
  border: 1.5px solid var(--accent-line);
  color: var(--accent-deep);
}
.mem-card:hover .mem-back { background: var(--surface); border-color: var(--accent); }

.mem-front {
  background: var(--surface);
  border: 1.5px solid var(--line);
  color: var(--ink);
  transform: rotateY(180deg);
}

/* Сложившаяся пара — заливка акцентом: «правильно» и «главное действие»
   в этом интерфейсе говорят одним голосом. Плюс галочка из JS: одним
   цветом состояние отличать нельзя, при дальтонизме оно пропадает. */
.mem-card.done .mem-front {
  background: var(--accent-fill);
  border-color: var(--accent-fill);
  color: var(--on-accent-fill);
}
.mem-card.done .mem-mark { color: var(--on-accent-fill); }
.mem-mark { display: flex; }

.mem-card.bad .mem-front {
  background: var(--err-soft);
  border-color: var(--err);
  color: var(--ink);
}

/* ==========================================================================
   3. ЛОПНИ ШАР
   ========================================================================== */

.bal-card { text-align: center; padding: var(--space-24) var(--space-16); }
.bal-card .quiz-word { margin-bottom: var(--space-8); }

.bal-stage {
  position: relative;
  overflow: hidden;
  height: clamp(300px, 44vh, 400px);
  margin: var(--space-16) 0 var(--space-8);
  border-radius: var(--radius-card);
  background: var(--surface-alt);
  border: var(--border-w) solid var(--line-soft);
}

.bal {
  position: absolute;
  top: 100%;
  width: clamp(78px, 22%, 112px);
  padding: 0;
  border: none;
  background: none;
  font: inherit;
  border-radius: 50% 50% 46% 46% / 56% 56% 44% 44%;
  will-change: transform;
  animation-name: bal-rise;
  animation-timing-function: linear;
  animation-fill-mode: forwards;
}

/* Единственная анимация игры — подъём. Только transform: шары не трогают
   раскладку и не заставляют страницу пересчитываться на каждом кадре.
   Высоту подъёма (--rise) подставляет JS по живому размеру поля. */
@keyframes bal-rise {
  to { transform: translate3d(0, calc(-1 * var(--rise, 520px)), 0); }
}

.bal-stage.paused .bal { animation-play-state: paused; }

.bal-body {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1 / 1.14;
  padding: var(--space-8) var(--space-4);
  background: var(--accent-soft);
  border: 1.5px solid var(--accent-line);
  border-radius: 50% 50% 46% 46% / 56% 56% 44% 44%;
  transition: transform var(--dur-fast) var(--ease),
              opacity var(--dur-fast) var(--ease);
}
/* Узелок */
.bal-body::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -7px;
  width: 10px;
  height: 9px;
  transform: translateX(-50%);
  background: var(--accent-line);
  clip-path: polygon(50% 0, 100% 100%, 0 100%);
}

.bal:hover .bal-body { border-color: var(--accent); }

.bal-word {
  font-family: var(--font-display);
  font-weight: 800;
  /* Ниже шкалы: 16px внутри 78-пиксельного шара рвёт «understand» пополам.
     Тянется до 16px, как только места хватает. */
  font-size: clamp(13px, 3.4vw, 16px);
  line-height: var(--leading-tight);
  color: var(--ink);
  overflow-wrap: anywhere;
}

.bal-long .bal-word { font-size: clamp(11px, 2.9vw, 15px); }

.bal.pop .bal-body { transform: scale(1.4); opacity: 0; }
.bal.miss .bal-body {
  background: var(--err-soft);
  border-color: var(--err);
  transform: scale(.86);
  opacity: 0;
}
.bal.miss .bal-body::after { background: var(--err); }

.bal-acts { margin-top: var(--space-4); }

/* «Меньше движения»: шары никуда не летят и не улетают — стоят рядом и
   ждут ответа. Игра теряет спешку, но остаётся игрой; ползущая мишень
   била бы ровно по тем, кто эту настройку и включает. */
.bal-stage.bal-still {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-12);
  height: auto;
  padding: var(--space-16);
}
.bal-still .bal {
  position: static;
  animation: none;
  width: clamp(78px, 22%, 112px);
}

/* ==========================================================================
   4. ОТКРОЙ КОРОБКУ
   ========================================================================== */

.box-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-8);
  max-width: 460px;
  margin-inline: auto;
}
@media (min-width: 560px) { .box-grid { gap: var(--space-12); } }

.box-tile {
  position: relative;
  aspect-ratio: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  padding: var(--space-8);
  background: var(--surface);
  border: 1.5px solid var(--line);
  border-radius: var(--radius-input);
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 800;
  transition: transform var(--dur-fast) var(--ease),
              background-color var(--dur-fast) var(--ease);
}
.box-tile:hover { background: var(--accent-soft); border-color: var(--accent); }
.box-tile:active { transform: scale(.97); }
.box-ico { color: var(--accent); display: block; }
.box-num { font-size: var(--text-caption); color: var(--ink-soft); }

/* Крышка приоткрывается перед тем, как показать слово. Полсекунды
   ожидания — это и есть вся разница между коробкой и списком вопросов. */
.box-tile.opening { transform: translateY(-6px) scale(1.05); }

/* Открытая коробка. Вес правила выше общего `button:disabled` (тот красит
   всё выключенное в --surface-alt), иначе результат пропадал бы сразу
   после ответа. Значок ставится из JS: одним цветом различать нельзя. */
.box-tile.ok:disabled {
  background: var(--accent-fill);
  border-color: var(--accent-fill);
  color: var(--on-accent-fill);
}
.box-tile.ok:disabled .box-ico,
.box-tile.ok:disabled .box-num,
.box-tile.ok:disabled .box-mark { color: var(--on-accent-fill); }

.box-tile.err:disabled {
  background: var(--err-soft);
  border-color: var(--err);
  color: var(--ink);
}
.box-tile.err:disabled .box-ico,
.box-tile.err:disabled .box-mark { color: var(--err); }
.box-tile.err:disabled .box-num { color: var(--ink-soft); }

.box-mark {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  display: flex;
}

.box-card .quiz-word { margin-bottom: var(--space-12); }

/* ==========================================================================
   ДВИЖЕНИЕ ВЫКЛЮЧЕНО
   ==========================================================================
   tokens.css уже глушит длительности глобально, но полагаться на это
   нельзя: у колеса и шаров движение — не украшение, а механика, и JS
   в этом режиме идёт другой веткой. Здесь страховка на случай, если
   правило сверху когда-нибудь ослабят. */
@media (prefers-reduced-motion: reduce) {
  .wheel-turn,
  .mem-inner,
  .bal-body,
  .box-tile { transition: none !important; }
  .bal { animation: none !important; }
  .box-tile.opening { transform: none; }
}

/* Разбор диктанта: слово, которое ученик не расслышал. Красным помечаем
   в ОБРАЗЦЕ — так видно, что именно надо было услышать. */
.dict-review { display: block; line-height: 1.6; }
.dict-sample { display: inline-block; margin-top: 4px; }
.dw-miss {
  color: var(--red);
  border-bottom: 2px solid var(--red);
  padding-bottom: 1px;
}

/* Кнопки скорости озвучки. Стоят рядом с «Прослушать», выбранная залита —
   как переключатель скорости в голосовых сообщениях мессенджера. */
.audio-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; justify-content: center; }
.speed-pills { display: inline-flex; gap: 4px; padding: 3px; border-radius: 999px; background: var(--surface-alt); }
.speed-pill {
  border: 0; background: transparent; cursor: pointer;
  font: inherit; font-size: 13px; font-weight: 600; color: var(--ink-soft);
  padding: 5px 12px; border-radius: 999px; min-height: 32px;
}
.speed-pill.on { background: var(--surface); color: var(--ink); box-shadow: 0 1px 2px rgba(0,0,0,.08); }
.speed-pill:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.dict-voice { display: flex; justify-content: flex-end; }
.flashcard .audio-row { margin-top: 8px; }

/* Замечания к своему предложению: список под полем ввода. Не «ошибки» —
   ученик мог написать и хорошо, просто оформил не так. */
.self-hints { margin: 8px 0 0; padding-left: 20px; text-align: left; }
.self-hints li { font-size: var(--text-caption); color: var(--ink-soft); line-height: 1.5; margin-bottom: 4px; }
