/*
 * Общая оболочка движков раздела «Тренажёры» (docs/16-trenazhery.md).
 *
 * Стиль тот же, что у умных игр (docs/09-games.md): сочные цвета, крупные
 * скруглённые кнопки, читаемый шрифт от 18px, задание от 28px. Отличие одно —
 * файл общий на все движки, а не свой у каждого: двенадцать копий одной
 * оболочки разошлись бы через месяц.
 *
 * 26.08.2026 оформление перерисовано: вместо эмодзи по углам — рисованная
 * сцена (`scene.js`), вместо значка «🦊» — сам герой (`hero.js`), вместо
 * полосы заполнения — дорожка раунда с фишкой и сундуком. 27.08.2026 героем
 * стал совёнок Наум — тот же персонаж, что и в знаке сайта.
 */

* {
  box-sizing: border-box;
}

:root {
  --bg1: #fff6e5;
  --bg2: #ffe3f1;
  --bg3: #eef1ff;
  --theme-accent: #ff7a59;
  --theme-deep: #2e2a4f;
  --ink: #2e2a4f;
  --ok: #3bc97d;
  --bad: #ff5a6e;
  --card: #ffffff;
  --exit-space: 96px;
}

html,
body {
  margin: 0;
  padding: 0;
  min-height: 100%;
}

body {
  font-family: "Naukino Emoji", system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  font-size: 18px;
  color: var(--ink);
  background: linear-gradient(160deg, var(--bg1), var(--bg2) 55%, var(--bg3));
  min-height: 100dvh;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

/* ---------- сцена ---------- */

/* Задник и летающая мелочь. Приглушены намеренно: сцена — это место, где
   происходит занятие, а не то, что рассматривают вместо задания. */

.theme-deco {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  overflow: hidden;
}

.scene-back {
  position: absolute;
  inset: 0;
  opacity: 0.3;
}

/* Вуаль поверх сцены. Без неё белая карточка задания ложится на светлый
   рисунок и перестаёт читаться как карточка: на экране просто светло. */
.theme-deco::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(
    ellipse at 50% 55%,
    rgba(255, 255, 255, 0.82) 0%,
    rgba(255, 255, 255, 0.55) 42%,
    rgba(255, 255, 255, 0) 78%
  );
}

.scene-back svg {
  width: 100%;
  height: 100%;
  display: block;
}

.float {
  position: absolute;
  display: block;
  opacity: 0.4;
  animation: drift 12s ease-in-out infinite alternate;
}

.float svg {
  width: 100%;
  height: 100%;
  display: block;
}

@keyframes drift {
  from {
    transform: translate3d(0, 0, 0) rotate(-3deg);
  }
  to {
    transform: translate3d(18px, -22px, 0) rotate(4deg);
  }
}

.wrap {
  position: relative;
  z-index: 1;
  max-width: 900px;
  margin: 0 auto;
  padding: 14px 16px 32px;
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
}

/* ---------- верхняя панель ---------- */

.bar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.exit-btn {
  border: 0;
  border-radius: 18px;
  padding: 10px 16px;
  font: inherit;
  font-weight: 700;
  color: #fff;
  background: rgba(46, 42, 79, 0.72);
  cursor: pointer;
}

.exit-btn:hover {
  background: rgba(46, 42, 79, 0.88);
}

.bar-spacer {
  flex: 1;
}

.icon-btn {
  border: 0;
  border-radius: 50%;
  width: 44px;
  height: 44px;
  font-size: 20px;
  background: rgba(255, 255, 255, 0.8);
  cursor: pointer;
  /* Сеткой, а не строкой: у звука внутри эмодзи, а у «Во весь экран» —
     рисунок, и по базовой линии он встал бы ниже середины кружка. */
  display: grid;
  place-items: center;
  color: var(--ink);
}

.icon-btn[aria-pressed='false'] {
  opacity: 0.5;
}

.theme-chip {
  background: rgba(255, 255, 255, 0.8);
  border-radius: 999px;
  padding: 8px 14px;
  font-size: 15px;
  font-weight: 600;
}

/* ---------- общие элементы ---------- */

.card {
  background: var(--card);
  border-radius: 24px;
  box-shadow: 0 10px 30px rgba(46, 42, 79, 0.12);
  padding: clamp(16px, 3vmin, 28px);
}

.btn {
  border: 0;
  border-radius: 20px;
  padding: 14px 24px;
  font: inherit;
  font-weight: 700;
  font-size: 19px;
  color: #fff;
  background: var(--theme-accent);
  cursor: pointer;
  transition: transform 0.12s ease;
}

.btn:hover {
  transform: translateY(-2px);
}

.btn:active {
  transform: translateY(1px);
}

.btn--ghost {
  background: rgba(255, 255, 255, 0.9);
  color: var(--ink);
  box-shadow: inset 0 0 0 2px rgba(46, 42, 79, 0.15);
}

button:focus-visible,
[tabindex]:focus-visible {
  outline: 3px solid #4ec5f1;
  outline-offset: 3px;
}

h1 {
  font-size: clamp(24px, 5vmin, 34px);
  margin: 12px 0 6px;
}

.lead {
  font-size: 19px;
  line-height: 1.5;
  margin: 0 0 18px;
}

/* ---------- стартовый экран ---------- */

.levels {
  display: grid;
  gap: 12px;
  margin: 18px 0;
}

.level-btn {
  display: flex;
  align-items: center;
  gap: 12px;
  text-align: left;
  border: 0;
  border-radius: 20px;
  padding: 16px 18px;
  font: inherit;
  background: var(--card);
  box-shadow: 0 6px 18px rgba(46, 42, 79, 0.1);
  cursor: pointer;
  transition: transform 0.12s ease;
}

.level-btn:hover {
  transform: translateY(-2px);
}

/* Пройденный уровень виден слева зелёной чертой: звёзды справа говорят,
   как он дался, а черта — что он вообще закрыт. */
.level-btn.is-cleared {
  box-shadow: inset 6px 0 0 var(--ok), 0 6px 18px rgba(46, 42, 79, 0.1);
}

.level-btn__no {
  width: 38px;
  height: 38px;
  flex: 0 0 38px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-weight: 800;
  color: #fff;
  background: var(--theme-accent);
}

.level-btn__text {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.level-btn__name {
  font-weight: 700;
}

.level-btn__count {
  font-size: 14px;
  opacity: 0.6;
}

.level-btn__stars {
  font-size: 17px;
  letter-spacing: 2px;
}

/* ---------- полка с наклейками ---------- */

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

.shelf {
  margin-top: 18px;
  background: rgba(46, 42, 79, 0.05);
  border-radius: 20px;
  padding: 14px 16px;
}

.shelf__head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 10px;
}

.shelf__title {
  font-weight: 800;
}

.shelf__count {
  font-size: 15px;
  opacity: 0.65;
}

.shelf__row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(48px, 1fr));
  gap: 8px;
}

.shelf__cell {
  display: block;
}

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

.sticker.is-locked {
  opacity: 0.55;
}

.shelf__cell.is-new svg {
  animation: prize-pop 0.8s ease backwards;
}

.shelf__note {
  margin: 10px 0 0;
  font-size: 15px;
  opacity: 0.7;
}

/* ---------- дорожка раунда ---------- */

/* Полоса заполнения показывала долю, а идти по доле нельзя. Здесь видно
   то, что важно ребёнку: сколько шагов позади и что впереди сундук. */

.round-line {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 14px 0 10px;
  font-weight: 600;
}

.round-line__no {
  font-size: 16px;
}

.streak {
  border-radius: 999px;
  padding: 6px 14px;
  font-size: 15px;
  font-weight: 800;
  color: #8a3b00;
  background: linear-gradient(120deg, #ffd76a, #ffb15c);
  box-shadow: 0 4px 12px rgba(255, 150, 60, 0.35);
}

.streak.is-lit {
  animation: streak-pop 0.5s ease;
}

@keyframes streak-pop {
  40% {
    transform: scale(1.18) rotate(-3deg);
  }
}

/* Высота с запасом сверху: фишка стоит над дорожкой и не должна налезать
   на строку с номером задания. */
.track {
  position: relative;
  display: flex;
  align-items: flex-end;
  height: 58px;
  margin-bottom: 4px;
  padding-right: 42px;
}

.track__rail {
  position: absolute;
  bottom: 3px;
  left: 0;
  right: 42px;
  height: 8px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.75);
  box-shadow: inset 0 1px 3px rgba(46, 42, 79, 0.12);
}

.track__done {
  height: 100%;
  border-radius: 999px;
  background: var(--theme-accent);
  transition: width 0.3s ease;
}

.track__steps {
  position: relative;
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
}

.track__dot {
  position: relative;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 0 3px rgba(46, 42, 79, 0.12);
}

.track__dot.is-done {
  background: var(--theme-accent);
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.8);
}

.track__dot.is-now {
  background: var(--theme-accent);
}

/* Фишка стоит над своей точкой и не раздвигает дорожку: иначе на каждом
   шаге все десять точек ехали бы вбок. */
.track__token {
  position: absolute;
  left: 50%;
  bottom: 6px;
  width: 40px;
  height: 40px;
  transform: translateX(-50%);
  animation: token-step 0.45s ease;
}

.track__token svg {
  width: 100%;
  height: 100%;
  display: block;
  filter: drop-shadow(0 3px 4px rgba(46, 42, 79, 0.25));
}

@keyframes token-step {
  from {
    transform: translate(-140%, 0) scale(0.7);
  }
  50% {
    transform: translate(-70%, -12px) scale(1.05);
  }
  to {
    transform: translate(-50%, 0) scale(1);
  }
}

.track__chest {
  position: absolute;
  right: 0;
  bottom: -6px;
  width: 38px;
  height: 38px;
}

.track__chest svg {
  width: 100%;
  height: 100%;
  display: block;
}

.stage {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 18px;
  padding: 10px 0;
  animation: stage-in 0.28s ease;
}

@keyframes stage-in {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
}

.question {
  font-size: clamp(28px, 6vmin, 40px);
  font-weight: 800;
  text-align: center;
  line-height: 1.25;
  margin: 0;
}

/* ---------- послушать ---------- */

/* Кнопка «Послушать» английского слова. Стоит над заданием и намеренно
   мельче всего остального: слушать — помощь, а не само задание, и когда
   голоса в системе нет, оболочка её просто не рисует. */

.listen {
  align-self: center;
  border: 0;
  border-radius: 999px;
  padding: 7px 16px;
  font: inherit;
  font-weight: 700;
  font-size: 15px;
  color: var(--ink);
  background: rgba(255, 255, 255, 0.9);
  box-shadow: inset 0 0 0 2px rgba(46, 42, 79, 0.15);
  cursor: pointer;
}

.listen:active {
  transform: translateY(1px);
}

/* ---------- о чём просят ---------- */

/* Строка «что сделать»: её показывают «Метки», «Сборка» и «Пары» — везде,
   где на экране лежит набор кнопок и без этой строки непонятно, что с ним
   делать. Тише самого задания: это указание, а не вопрос. */

.task-ask {
  font-size: clamp(17px, 3.4vmin, 21px);
  font-weight: 700;
  text-align: center;
  opacity: 0.85;
  margin: 0;
}

/* ---------- заголовок задания ---------- */

/* Название задания у «Сборки» и «Пар»: что именно собираем и что с чем
   соединяем. Мельче вопроса «Выбора»: там текст и есть задание, а здесь
   он только называет набор, лежащий ниже. */

.task-title {
  font-size: clamp(19px, 3.8vmin, 26px);
  font-weight: 800;
  text-align: center;
  line-height: 1.25;
  margin: 0;
}

/* ---------- картинка задания ---------- */

/* Рисунок, по которому узнают: гриб, дерево, зверь. Высота задана в vmin,
   а не в пикселях: на невысоком экране картинка не должна выдавливать
   варианты ответа за нижний край. */

.task-pic {
  display: flex;
  justify-content: center;
}

.task-pic img {
  width: auto;
  height: clamp(110px, 24vmin, 200px);
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 18px;
  background: rgba(255, 255, 255, 0.6);
  box-shadow: 0 4px 0 rgba(46, 42, 79, 0.12);
}

/* ---------- варианты ответа ---------- */

/* Два-четыре крупных ответа: ими отвечают и «Выбор», и «Задача по шагам». */

.options {
  display: grid;
  gap: 12px;
  grid-template-columns: 1fr;
}

@media (min-width: 560px) {
  .options {
    grid-template-columns: 1fr 1fr;
  }
}

.option {
  border: 0;
  border-radius: 20px;
  padding: 18px 20px;
  font: inherit;
  font-size: clamp(19px, 3.4vmin, 24px);
  font-weight: 700;
  color: var(--ink);
  background: var(--card);
  box-shadow: 0 8px 20px rgba(46, 42, 79, 0.12);
  cursor: pointer;
  transition: transform 0.12s ease;
}

.option:hover {
  transform: translateY(-3px);
}

.option:active {
  transform: translateY(1px);
}

/* ---------- клавиши ---------- */

/* Цифры и буквы под заданием: ими набирают ответ и «Ввод», и «Столбик». */

.keys {
  display: grid;
  gap: 10px;
  grid-template-columns: repeat(var(--keys, 5), minmax(0, 1fr));
  max-width: 520px;
  margin: 0 auto;
  width: 100%;
}

.key {
  border: 0;
  border-radius: 18px;
  padding: 16px 8px;
  font: inherit;
  font-size: clamp(22px, 4vmin, 28px);
  font-weight: 800;
  color: var(--ink);
  background: var(--card);
  box-shadow: 0 8px 18px rgba(46, 42, 79, 0.12);
  cursor: pointer;
  transition: transform 0.1s ease;
}

.key:hover {
  transform: translateY(-2px);
}

.key:active {
  transform: translateY(1px);
}

/* На невысоком окне клавиатура ужимается. У задачи по шагам под ней стоит
   «Проверить», и решение копится над ней строка за строкой: к пятому шагу
   кнопка уходила за нижний край, и ответ нечем было подтвердить. */
@media (max-height: 800px) {
  .keys {
    gap: 8px;
  }

  .key {
    padding: 9px 8px;
    font-size: clamp(20px, 3.4vmin, 24px);
  }

  .step-body {
    gap: 10px;
  }
}

/* Кнопки под заданием: «Проверить» и «Готово» у ввода, шкалы и задачи. */

.input-actions {
  display: flex;
  gap: 12px;
  justify-content: center;
}

/* ---------- совёнок Наум ---------- */

.hero {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  margin-top: 10px;
}

.hero__face {
  width: clamp(72px, 14vmin, 104px);
  flex: none;
  display: block;
}

.hero__face svg {
  width: 100%;
  height: auto;
  display: block;
  overflow: visible;
}

/* Наум живёт сам по себе: моргает и качает кисточкой. Неподвижный герой
   выглядит картинкой, а не собеседником. Всё остальное двигается только
   в ответ на ход.

   У прежнего лисёнка эту работу делал хвост — крупная деталь, заметная
   боковым зрением. Кисточка втрое меньше, поэтому и размах у неё больше:
   на 9° её качание попросту не видно. */
.owl__tassel {
  transform-origin: 141px 47px;
  animation: tassel 2.4s ease-in-out infinite;
}

@keyframes tassel {
  50% {
    transform: rotate(-17deg);
  }
}

/* Моргание: глаз сжимается по высоте вокруг своего центра. Пауза длинная,
   само моргание короткое — иначе герой выглядит сонным. */
.owl__lid {
  animation: owl-blink 5.4s ease-in-out infinite;
}

.owl__lid--l {
  transform-origin: 77px 84px;
}

.owl__lid--r {
  transform-origin: 123px 84px;
  animation-delay: 0.06s;
}

@keyframes owl-blink {
  0%,
  93%,
  100% {
    transform: scaleY(1);
  }
  96% {
    transform: scaleY(0.08);
  }
}

@media (prefers-reduced-motion: reduce) {
  .owl__tassel,
  .owl__lid {
    animation: none;
  }
}

/* Три настроения, и различаются они не картинкой, а тем, какие узлы
   видны: прищур вместо глаз, приоткрытый клюв вместо ровного, брови
   домиком и щёки. */
.owl__eyes-glad,
.owl__beak--glad,
.owl__brows,
.owl__cheek {
  opacity: 0;
}

.hero__face.is-happy .owl__eyes-open,
.hero__face.is-happy .owl__beak--calm {
  opacity: 0;
}

.hero__face.is-happy .owl__eyes-glad,
.hero__face.is-happy .owl__beak--glad,
.hero__face.is-happy .owl__cheek {
  opacity: 1;
}

.hero__face.is-happy .owl__body {
  animation: hop 0.6s ease;
}

.hero__face.is-sad .owl__brows {
  opacity: 1;
}

/* В огорчении зрачки опускаются, а брови сходятся к переносице:
   клюв у совы не гнётся, и всю работу рта делают брови. */
.hero__face.is-sad .owl__face {
  transform: translateY(3px);
}

.hero__face.is-sad .owl__brow--l {
  transform: translate(6px, 9px) rotate(13deg);
  transform-origin: 74px 61px;
}

.hero__face.is-sad .owl__brow--r {
  transform: translate(-6px, 9px) rotate(-13deg);
  transform-origin: 126px 61px;
}

.hero__face.is-sad .owl__body {
  animation: wobble 0.6s ease;
}

.hero__bubble {
  background: var(--card);
  border-radius: 20px 20px 20px 4px;
  padding: 12px 16px;
  box-shadow: 0 6px 18px rgba(46, 42, 79, 0.12);
  font-size: 17px;
  line-height: 1.45;
  flex: 1;
}

@keyframes hop {
  50% {
    transform: translateY(-14px);
  }
}

@keyframes wobble {
  25% {
    transform: rotate(-6deg);
  }
  75% {
    transform: rotate(6deg);
  }
}

@keyframes shake {
  25% {
    transform: translateX(-8px);
  }
  75% {
    transform: translateX(8px);
  }
}

.is-shaking {
  animation: shake 0.32s ease;
}

.is-wrong {
  background: var(--bad) !important;
  color: #fff !important;
}

.is-right {
  background: var(--ok) !important;
  color: #fff !important;
}

/* ---------- конфетти ---------- */

/* Летит на серии и на трёх звёздах. Поверх всего, но сквозь него можно
   нажимать: раунд не должен ждать, пока долетит последняя бумажка. */

.confetti {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 5;
  overflow: hidden;
}

.confetti i {
  position: absolute;
  top: -24px;
  width: 12px;
  height: 18px;
  border-radius: 3px;
  animation: fall 2s ease-in forwards;
}

@keyframes fall {
  to {
    transform: translateY(105vh) rotate(540deg);
    opacity: 0.2;
  }
}

/* ---------- итог ---------- */

.stars {
  font-size: clamp(38px, 9vmin, 64px);
  text-align: center;
  letter-spacing: 6px;
  /* Золотые, а не чернильные: звезда — награда, и чёрной она выглядит
     как знак препинания. Пустая звезда рисуется тем же цветом контуром. */
  color: #f2b134;
}

.stars span {
  display: inline-block;
  animation: pop 0.4s backwards;
}

@keyframes pop {
  from {
    transform: scale(0.2);
    opacity: 0;
  }
}

.prize {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 6px 0 4px;
  padding: 12px 16px;
  border-radius: 20px;
  background: linear-gradient(120deg, rgba(255, 215, 106, 0.35), rgba(255, 122, 89, 0.2));
}

.prize__art {
  width: 76px;
  flex: none;
}

.prize__art svg {
  width: 100%;
  height: auto;
  display: block;
  animation: prize-pop 0.8s ease backwards;
}

@keyframes prize-pop {
  from {
    transform: scale(0.2) rotate(-30deg);
    opacity: 0;
  }
  60% {
    transform: scale(1.15) rotate(8deg);
  }
}

.prize__title {
  font-weight: 800;
  font-size: 19px;
}

.prize__note {
  font-size: 15px;
  opacity: 0.7;
}

.result-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
  margin-top: 18px;
}

details.report {
  margin-top: 20px;
  background: rgba(255, 255, 255, 0.75);
  border-radius: 18px;
  padding: 12px 16px;
}

details.report summary {
  font-weight: 700;
  cursor: pointer;
}

details.report ul {
  margin: 10px 0 0;
  padding-left: 20px;
  line-height: 1.5;
}

@media (max-width: 640px) {
  .wrap {
    padding-top: 10px;
  }
  body {
    font-size: 17px;
  }
  .float {
    opacity: 0.4;
  }
  .track__token {
    width: 32px;
    height: 32px;
  }
}

@media (prefers-reduced-motion: reduce) {
  * {
    animation: none !important;
    transition: none !important;
  }
}
