:root {
  --ink: #1b2140;
  --stroke: rgba(255, 255, 255, 0.18);
  --panel: rgba(12, 18, 32, 0.66);
  color-scheme: light;
}
* { box-sizing: border-box; }
html, body {
  margin: 0; padding: 0; height: 100%; overflow: hidden;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  background: #87ceeb;
  -webkit-user-select: none; user-select: none;
  -webkit-tap-highlight-color: transparent;
  /* A phone: the page itself never pans, zooms or pulls to refresh — a thumb
     steering on the left half off the canvas dragged the whole page with it. */
  touch-action: none; overscroll-behavior: none;
}
#hub { display: block; width: 100%; height: 100%; touch-action: none; }
/* A tap on a button is a tap at once, never the start of a double-tap zoom. */
button { touch-action: manipulation; }
/* What scrolls says which way, and scrolls inside itself, not the page. */
.parent-card, .awards-card, .records-card, .salon-items, #phrases { touch-action: pan-y; overscroll-behavior: contain; }
@media (max-width: 620px) { .salon-tabs { touch-action: pan-x; } }

/* ---- Teleport flash (§3) ---- */
#flash {
  position: fixed; inset: 0; background: #fff; opacity: 0;
  pointer-events: none; transition: opacity .22s ease; z-index: 60;
}
#flash.on { opacity: 1; }

/* ---- HUD ---- */
#hud {
  position: fixed; top: max(10px, env(safe-area-inset-top)); left: 0; right: 0;
  display: flex; justify-content: space-between; align-items: flex-start;
  padding: 0 12px; gap: 12px; pointer-events: none; z-index: 20;
  /* Lying on its side, the phone's notch is on the left or the right: the row
     of buttons (🏆 🎥 🔊 👩‍👦 go up here lying down) stays out of it. */
  padding-left: max(12px, env(safe-area-inset-left)); padding-right: max(12px, env(safe-area-inset-right));
}
.hud-left { display: flex; align-items: center; gap: 10px; }
.chevron {
  display: flex; align-items: center; gap: 6px;
  background: linear-gradient(135deg, #ffd34d, #ff9f1c);
  color: #3a2a00; font-weight: 800; font-size: 20px;
  padding: 7px 14px 7px 10px; border-radius: 999px;
  border: 2px solid rgba(255, 255, 255, 0.6);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
}
.chev-icon { font-size: 18px; }
.xp-bar {
  width: 140px; height: 12px; border-radius: 999px;
  background: rgba(10, 14, 24, 0.5); border: 1px solid var(--stroke); overflow: hidden;
}
#xp-fill { height: 100%; width: 0%; background: linear-gradient(90deg, #7bff9b, #37b34a); transition: width .4s ease; }
.hud-right { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
#hud-tools { display: flex; gap: 8px; }
.pill {
  background: var(--panel); color: #fff; font-weight: 700; font-size: 15px;
  padding: 8px 13px; border-radius: 999px; border: 1px solid var(--stroke);
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
}

/* Телефон: семь пилюль в одну строку не помещаются никогда, и «просто
   перенести» их некуда — под баром стоит палитра, и нижний ряд уезжал прямо
   под неё. Поэтому бар делится по смыслу: наверху остаётся то, что читают
   (монеты, энергия, сколько нас), а всё, по чему жмут, встаёт колонкой у
   правого края — включая 🎨, которая раньше висела отдельно и как раз в это
   место и попадала. */
@media (pointer: coarse) {
  .hud-right { flex-wrap: nowrap; flex: none; }
  /* Показания не переносятся: на 360 «💰 0» ломалось в две строки, пилюли
     вырастали до 54 px и наезжали на 🏆, а 👥 уходила за край экрана.
     Место отдаёт полоска опыта — она сжимается первой. */
  .hud-right .pill { white-space: nowrap; }
  .hud-left { min-width: 0; flex: 1 1 auto; }
  .xp-bar { flex: 0 1 140px; min-width: 36px; }
  #hud-tools {
    position: fixed; right: max(10px, env(safe-area-inset-right));
    top: calc(58px + env(safe-area-inset-top));
    flex-direction: column; gap: 8px; z-index: 21;
  }
  #hud-tools .pill-btn {
    width: 46px; height: 46px; padding: 0; font-size: 22px; line-height: 1;
  }
}

/* ---- Следующая цель и монеты (hub/goals.js, hub/main.js) ----
   Цель — пилюля под уровнем, слева: справа колонка кнопок, а под уровнем на
   любом телефоне, стоя и лёжа, пусто. Нажимается только она сама (тап —
   сказать цель ещё раз); открытая палитра 🎨 ложится поверх неё (#skin-block
   позже в разметке). «+N» у 💰 не ловит пальцы. */
#goal-chip {
  position: fixed; left: max(12px, env(safe-area-inset-left));
  top: calc(max(10px, env(safe-area-inset-top)) + 52px);
  z-index: 20; pointer-events: auto; cursor: pointer; touch-action: manipulation;
  height: 40px; padding: 0 14px; border-radius: 999px; white-space: nowrap;
  font: inherit; font-weight: 800; font-size: 16px; line-height: 1; color: #fff;
  background: rgba(12, 18, 32, 0.66); border: 2px solid #ffd34d;
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
}
#goal-chip.hidden { display: none; }
#goal-chip.done { background: #37b34a; border-color: #fff; }
#goal-chip:active { transform: scale(0.95); }
#coin-pop {
  position: fixed; left: 0; top: 0; z-index: 21; pointer-events: none;
  color: #ffd34d; font-weight: 900; font-size: 22px; white-space: nowrap;
  text-shadow: 0 2px 3px rgba(0, 0, 0, 0.55); opacity: 0;
}
#coin-pop.go { animation: coin-pop 1.1s ease-out; }
@keyframes coin-pop {
  0% { opacity: 0; transform: translate(-50%, 22px) scale(0.8); }
  25% { opacity: 1; transform: translate(-50%, 10px) scale(1.15); }
  100% { opacity: 0; transform: translate(-50%, -6px) scale(1); }
}
#hud-coins.go { animation: coin-bump 0.45s ease-out; }
@keyframes coin-bump { 0%, 100% { transform: scale(1); } 40% { transform: scale(1.18); } }

/* ---- Toast (spoken hints duplicate here) ---- */
#toast {
  position: fixed; left: 50%; top: 24%; transform: translate(-50%, -6px);
  background: rgba(12, 18, 32, 0.9); color: #fff; font-weight: 700; font-size: 17px;
  padding: 13px 20px; border-radius: 16px; border: 1px solid var(--stroke);
  /* max-content: a box at left:50% is only as wide as the half of the screen to
     its right, so «Это площадь! Иди к звёздочке — там арка в мир» stood in a
     180 px column of seven lines on a 360 px phone, over the child's head, and
     max-width never got the chance to say 86vw. */
  width: max-content; max-width: min(86vw, 520px); text-align: center; line-height: 1.35;
  opacity: 0; pointer-events: none; transition: opacity .25s ease, transform .25s ease;
  /* Над панелями салона, рекордов, наград и взрослого (60–62): под панелью
     салона пропадали «Куплено ✨», «Не хватает 💰» и «Фото готово!». Под
     загрузочным экраном (70). А мир — рамка на весь экран, и поверх неё
     тост площади не нужен: его не видно, как и раньше (подсказки ждут
     возвращения на площадь, hub/main.js) — кроме .over, ниже. */
  z-index: 63;
}
#toast.show { opacity: 1; transform: translate(-50%, 0); }
/* The few that must be read wherever the child is (hub/main.js, toast `over`):
   the day's limit inside a world — over the world's frame, where every other
   toast is hidden — and «К тебе подключился взрослый» over the 👩‍👦 panel (60)
   or any other panel (62). Under #boot (70). */
body:has(#world:not(.hidden)) #toast:not(.over) { visibility: hidden; }
#toast.over { z-index: 65; }
/* Over a world it covers what the child is playing: «Ещё 5 минут…» sat on the
   letter of the task card for its two and a half seconds. At the bottom edge,
   below the jump button and the joystick's place, there is nothing to read there. */
#toast.over { top: auto; bottom: calc(14px + env(safe-area-inset-bottom)); transform: translate(-50%, 6px); }
#toast.over.show { transform: translate(-50%, 0); }
/* Over the salon it covered the mirror at the very moment of buying («Куплено:
   Котик ✨» on the face that had just been painted) and the row of tabs.
   Just above the bottom bar with the coins and «Готово» instead. */
body:has(#salon-panel.open) #toast:not(.over) { top: auto; bottom: calc(92px + env(safe-area-inset-bottom)); transform: translate(-50%, 6px); }
body:has(#salon-panel.open) #toast:not(.over).show { transform: translate(-50%, 0); }

/* ---- Игра обновилась ----
   Сверху, поверх полоски уровня: появляется только когда ребёнок свободен и
   стоит на ногах (hub/main.js), и через десять секунд сама перезагружает
   страницу. Кнопка — под палец, чтобы не ждать. */
#update-banner {
  position: fixed; left: 50%; top: max(8px, env(safe-area-inset-top)); transform: translateX(-50%);
  width: max-content; max-width: calc(100vw - 20px); z-index: 45;
  display: flex; align-items: center; gap: 12px;
  background: rgba(12, 18, 32, 0.92); color: #fff; border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 16px; padding: 8px 8px 8px 16px;
  font-weight: 800; font-size: 15px; line-height: 1.3;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
}
#update-banner.hidden { display: none; }
#btn-update {
  flex: none; min-height: 44px; padding: 0 16px; border: none; border-radius: 12px;
  background: #ffd34d; color: #23180a; font: inherit; font-weight: 900; cursor: pointer;
  box-shadow: 0 3px 0 #b8912c;
}
#btn-update:active { transform: translateY(2px); box-shadow: none; }

/* ---- Emotions + phrases (§2) ----
   Desktop: the wheel sits open at the bottom-left, there is room.
   Touch: the bottom-left belongs to the joystick thumb, so the controls collapse
   into two buttons on the RIGHT, above the jump button. */
#social {
  position: fixed; left: max(10px, env(safe-area-inset-left));
  bottom: calc(18px + env(safe-area-inset-bottom));
  display: flex; align-items: flex-end; gap: 8px; z-index: 30;
}
#wheel { display: grid; grid-template-columns: repeat(4, 44px); gap: 6px; }
.wheel-btn, .social-toggle {
  width: 44px; height: 44px; border-radius: 50%; font-size: 22px; line-height: 1;
  background: var(--panel); color: #fff; border: 1px solid var(--stroke);
  cursor: pointer; -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); padding: 0;
}
.wheel-btn:active, .social-toggle:active { transform: scale(0.92); }
#btn-emotes { display: none; }          /* desktop: the wheel is already open */
#phrases {
  position: fixed; left: max(10px, env(safe-area-inset-left));
  bottom: calc(74px + env(safe-area-inset-bottom));
  display: none; flex-direction: column; gap: 6px; max-height: 42vh; max-height: 42dvh; overflow: auto;
  background: var(--panel); padding: 10px; border-radius: 16px; border: 1px solid var(--stroke);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); z-index: 31;
}
#phrases.open { display: flex; }
.phrase-btn {
  background: rgba(255, 255, 255, 0.1); color: #fff; border: 1px solid var(--stroke);
  border-radius: 12px; padding: 10px 14px; font-size: 15px; font-weight: 600;
  text-align: left; cursor: pointer; white-space: nowrap;
}
.phrase-btn:active { background: rgba(255, 255, 255, 0.2); }

@media (pointer: coarse) {
  /* Keep the whole bottom-left clear for the floating joystick. */
  #social {
    left: auto; right: max(14px, env(safe-area-inset-right));
    bottom: calc(184px + env(safe-area-inset-bottom));
    flex-direction: column; align-items: flex-end; gap: 10px;
  }
  #btn-emotes { display: block; }
  #wheel {
    display: none;
    position: fixed; right: max(70px, env(safe-area-inset-right));
    bottom: calc(184px + env(safe-area-inset-bottom));
    grid-template-columns: repeat(4, 52px); gap: 8px;
    background: var(--panel); padding: 10px; border-radius: 18px;
    border: 1px solid var(--stroke); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  }
  #wheel.open { display: grid; }
  .wheel-btn, .social-toggle { width: 52px; height: 52px; font-size: 26px; }
  #phrases {
    left: auto; right: max(70px, env(safe-area-inset-right));
    bottom: calc(184px + env(safe-area-inset-bottom));
    max-width: 62vw;
  }
  .phrase-btn { white-space: normal; }
}

/* ---- Look picker ---- */
#skin-block {
  position: fixed; right: max(10px, env(safe-area-inset-right)); top: 78px;
  display: flex; align-items: center; gap: 6px; z-index: 20;
  background: var(--panel); padding: 7px 10px; border-radius: 999px; border: 1px solid var(--stroke);
}
.skin-label { font-size: 15px; background: none; border: 0; color: #fff; padding: 0; cursor: default; }
.skin-row { display: flex; gap: 5px; }
.skin-swatch {
  width: 22px; height: 22px; border-radius: 50%; border: 2px solid rgba(255, 255, 255, 0.5);
  cursor: pointer; padding: 0;
}
.skin-swatch.selected { border-color: #fff; box-shadow: 0 0 0 2px #ffd34d; }

@media (pointer: coarse) {
  /* A narrow screen can't spare a row of eight swatches over the scene. */
  .skin-label { font-size: 20px; cursor: pointer; }
  #skin-block .skin-row { display: none; }
  #skin-block.open .skin-row { display: flex; flex-wrap: wrap; max-width: 54vw; }
  /* Продолжение той же колонки: 58 сверху + четыре кнопки по 46 + три зазора
     по 8 = 266. Палитра встаёт следующей, а не поверх последней кнопки. */
  #skin-block {
    top: calc(274px + env(safe-area-inset-top));
    justify-content: center; padding: 0; border-radius: 999px;
    min-width: 46px; min-height: 46px;
  }
  /* Обработчик висит на самой 🎨, поэтому она и должна быть кнопкой целиком:
     иначе палец, попавший в поле вокруг значка, не делает ничего. */
  #skin-block .skin-label {
    font-size: 22px; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    width: 46px; height: 46px;
  }
  /* Открытая палитра — полкой наверху, под показаниями, слева от колонки
     кнопок: над небом, а не над ребёнком. Рядом с 🎨 она ложилась ровно на
     фигурку, которую перекрашивают, — на 360×640 цвет выбирали вслепую.
     И кружки под палец: 40, а не 28. */
  #skin-block.open .skin-row {
    position: fixed; top: calc(58px + env(safe-area-inset-top));
    left: max(10px, env(safe-area-inset-left)); right: calc(66px + env(safe-area-inset-right));
    max-width: none; justify-content: flex-start; gap: 8px;
    padding: 8px 10px; border-radius: 20px;
    background: var(--panel); border: 1px solid var(--stroke); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
  }
  .skin-swatch { width: 40px; height: 40px; }
}

/* ---- Touch controls ---- */
#touch-controls { position: fixed; inset: 0; pointer-events: none; z-index: 25; }
/* Floating joystick (Roblox-style): drawn wherever the finger lands on the left
   half of the screen. Touches are handled window-wide, so the ring itself must
   never intercept them. */
.joystick {
  position: fixed;
  left: 0; top: 0;
  width: 132px; height: 132px;
  margin: -66px 0 0 -66px;   /* centre on the touch point */
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12); border: 2px solid rgba(255, 255, 255, 0.32);
  pointer-events: none; touch-action: none;
  opacity: 0; transition: opacity .12s ease;
}
.joystick.active { opacity: 1; }
.joystick-knob {
  position: absolute; left: 50%; top: 50%; width: 56px; height: 56px; margin: 0;
  transform: translate(-50%, -50%);
  border-radius: 50%; background: rgba(255, 255, 255, 0.85);
  border: 2px solid rgba(255, 255, 255, 0.6); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.35);
}
/* ---- Призрак джойстика ----
   Джойстик невидим, пока палец не лёг, и новичок на телефоне не знал, что
   ходить надо пальцем слева: ни руки, ни стрелки. Кружок с пальцем плывёт
   вверх и назад, пока ребёнок не сделает первый шаг. Сквозь него касание
   проходит — это та же половина экрана, где рождается настоящий джойстик. */
#ghost-stick {
  position: fixed; left: max(34px, env(safe-area-inset-left));
  bottom: calc(118px + env(safe-area-inset-bottom));
  width: 120px; display: none; flex-direction: column; align-items: center; gap: 8px;
  pointer-events: none;
}
#ghost-stick.show { display: flex; animation: ghost-in .4s ease-out; }
.ghost-ring {
  position: relative; width: 112px; height: 112px; border-radius: 50%;
  background: rgba(255, 255, 255, 0.14); border: 2px dashed rgba(255, 255, 255, 0.6);
}
.ghost-knob {
  position: absolute; left: 50%; top: 50%; width: 48px; height: 48px; margin: -24px 0 0 -24px;
  border-radius: 50%; background: rgba(255, 255, 255, 0.8); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
  animation: ghost-drag 1.8s ease-in-out infinite;
}
.ghost-hand { position: absolute; left: 14px; top: 20px; font-size: 34px; filter: drop-shadow(0 2px 3px rgba(0,0,0,.4)); }
.ghost-say {
  background: rgba(12, 18, 32, 0.8); color: #fff; font-weight: 800; font-size: 15px;
  padding: 5px 12px; border-radius: 12px; white-space: nowrap;
}
@keyframes ghost-drag {
  0%, 15% { transform: translate(0, 0); }
  50%, 65% { transform: translate(0, -34px); }
  100% { transform: translate(0, 0); }
}
@keyframes ghost-in { from { opacity: 0; } to { opacity: 1; } }
@media (pointer: fine) { #ghost-stick { display: none !important; } }
/* ---- Призрак свайпа ----
   Пара призраку джойстика, справа: палец ездит вбок, пока новичок ни разу не
   повернул камеру. Посередине правой половины — ниже кнопок наверху и выше
   кнопок внизу; касание сквозь него проходит, как и сквозь джойстик.
   По ширине — между серединой экрана и колонкой кнопок у правого края (46 px
   и отступ): на 360×640 по высоте между 🎨 и 😊 места нет, и при 150 px
   ширины призрак ложился прямо на них. */
#ghost-swipe {
  position: fixed; left: calc(75% - 32px); top: 44%; transform: translateX(-50%);
  width: min(150px, calc(50% - 72px)); display: none; flex-direction: column; align-items: center; gap: 8px;
  pointer-events: none;
}
#ghost-swipe.show { display: flex; animation: ghost-in .4s ease-out; }
#ghost-swipe .ghost-say { font-size: clamp(12px, 3.6vw, 15px); }
/* На узком экране и подпись — в ширину дорожки, в две строки. */
@media (max-width: 380px) { #ghost-swipe .ghost-say { max-width: 100%; white-space: normal; text-align: center; } }
.swipe-track {
  position: relative; width: 100%; height: 58px; border-radius: 29px;
  background: rgba(255, 255, 255, 0.14); border: 2px dashed rgba(255, 255, 255, 0.6);
}
.swipe-hand {
  position: absolute; left: 50%; top: 6px; margin-left: -18px; font-size: 34px;
  filter: drop-shadow(0 2px 3px rgba(0,0,0,.4));
  animation: ghost-swipe 2s ease-in-out infinite;
}
@keyframes ghost-swipe {
  0%, 10% { transform: translateX(0); }
  35%, 45% { transform: translateX(-36px); }
  70%, 80% { transform: translateX(36px); }
  100% { transform: translateX(0); }
}
@media (pointer: fine) { #ghost-swipe { display: none !important; } }

/* ---- Клавиши на картинке ----
   За компьютером джойстика нет: внизу слева, над колесом эмоций, рисуются
   клавиши — стрелки и WASD, мышь, пробел, — пока новичок ни разу ими не
   воспользовался. Сквозь картинку мышь проходит. */
#key-picture {
  position: fixed; left: max(16px, env(safe-area-inset-left)); bottom: calc(128px + env(safe-area-inset-bottom));
  display: none; pointer-events: none; z-index: 24;
  padding: 12px 14px; border-radius: 16px;
  background: rgba(12, 18, 32, 0.72); border: 1px solid var(--stroke);
}
#key-picture.show { display: block; animation: ghost-in .4s ease-out; }
#key-picture .kp { display: none; align-items: center; gap: 12px; }
#key-picture[data-k="move"] .kp-move, #key-picture[data-k="look"] .kp-look, #key-picture[data-k="jump"] .kp-jump { display: flex; }
.kp-keys { display: grid; grid-template-columns: repeat(3, 36px); grid-auto-rows: 36px; gap: 4px; }
.kp-keys .kp-up { grid-column: 2; grid-row: 1; }
.kp-keys .kp-cap:not(.kp-up) { grid-row: 2; }
.kp-cap {
  display: grid; place-items: center; min-width: 36px; height: 36px; padding: 0 8px;
  background: #f4f6fb; color: #1b2140; font-weight: 900; font-size: 18px;
  border-radius: 8px; box-shadow: 0 3px 0 #9aa3b8;
  animation: kp-press 1.6s ease-in-out infinite;
}
.kp-keys .kp-up { animation-delay: 0s; }
.kp-or { color: #dfe6ff; font-weight: 800; font-size: 15px; }
.kp-space { width: 180px; font-size: 16px; }
@keyframes kp-press {
  0%, 60%, 100% { transform: translateY(0); box-shadow: 0 3px 0 #9aa3b8; }
  30% { transform: translateY(3px); box-shadow: 0 0 0 #9aa3b8; }
}
.kp-mouse {
  position: relative; width: 38px; height: 56px; border-radius: 19px 19px 22px 22px;
  background: #f4f6fb; box-shadow: 0 3px 0 #9aa3b8;
  animation: kp-sway 2s ease-in-out infinite;
}
.kp-wheel { position: absolute; left: 50%; top: 9px; width: 6px; height: 12px; margin-left: -3px; border-radius: 3px; background: #1b2140; }
.kp-sway { color: #fff; font-size: 30px; font-weight: 900; }
@keyframes kp-sway {
  0%, 100% { transform: translateX(0); }
  30% { transform: translateX(-14px); }
  70% { transform: translateX(14px); }
}

/* ---- Затемнение перед переносом (первый выбор новичка) ---- */
#fade {
  position: fixed; inset: 0; background: #0b1020; opacity: 0;
  pointer-events: none; transition: opacity .25s ease; z-index: 59;
}
#fade.on { opacity: 1; }
/* И прыжок: после первых шагов кнопка ⤒ пару раз вспыхивает, пока ребёнок
   ни разу не прыгнул. */
.touch-btn.jump.nudge { animation: jump-nudge 1.1s ease-in-out 4; }
@keyframes jump-nudge {
  0%, 100% { transform: scale(1); box-shadow: none; }
  50% { transform: scale(1.14); box-shadow: 0 0 0 8px rgba(255, 211, 77, 0.55); }
}

/* The buttons' size and spacing, kept here because the horse prompts below
   have to stay clear of them too. Every button has to stay in the RIGHT half:
   the left half belongs to the joystick (input.js), and a button reaching into
   it takes the thumb that came down to steer. At 76 the pair of them reached
   two pixels past the middle of a 360 px phone. */
:root { --tbtn: 76px; --tgap: 12px; }
@media (max-width: 380px) { :root { --tbtn: 70px; --tgap: 10px; } }
.touch-buttons {
  position: absolute; right: max(18px, env(safe-area-inset-right));
  bottom: calc(96px + env(safe-area-inset-bottom)); display: flex; gap: var(--tgap);
}
.touch-btn {
  width: var(--tbtn); height: var(--tbtn); border-radius: 50%; font-size: 30px; pointer-events: auto;
  background: rgba(255, 255, 255, 0.24); color: #fff; border: 2px solid rgba(255, 255, 255, 0.45);
}
.touch-btn.ride { background: rgba(255, 211, 77, 0.32); border-color: rgba(255, 211, 77, 0.7); }
.touch-btn.ride2 { background: rgba(83, 193, 255, 0.3); border-color: rgba(83, 193, 255, 0.7); }
/* «Высадить друга» stands on top of the 🐴 rather than beside it. As the first
   of three in the row it sat in the joystick's half of a 360-390 px phone, and
   a rider steering with their thumb put their friend down without meaning to. */
#btn-ride2 { position: absolute; right: calc(var(--tbtn) + var(--tgap)); bottom: calc(100% + var(--tgap)); }
.touch-btn.hidden, #ride-prompt.hidden, #ride-prompt2.hidden { display: none !important; }
@media (pointer: fine) { #touch-controls { display: none; } }

/* ---- The horse prompt ----
   Just above the middle of the screen, like a Roblox ProximityPrompt: close
   enough to what you are looking at to be about it, clear of the joystick. */
#ride-prompt {
  position: fixed; left: 50%; bottom: 26%; transform: translateX(-50%);
  z-index: 34; pointer-events: none;
  display: flex; align-items: center; gap: 10px;
  background: rgba(12, 18, 32, 0.82); border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 16px; padding: 9px 16px 9px 10px;
  font-weight: 800; font-size: 16px; color: #fff;
  /* One line always. Held at the middle of the screen, a prompt may only use
     the half to the right of it: «Слезть с Искорки» broke in two on a 360 px
     phone, grew taller than the gap to the second prompt, and ran into it. */
  white-space: nowrap;
  animation: ride-in .18s ease-out;
}
/* The second prompt sits just above the first, in the same style. */
#ride-prompt2 {
  position: fixed; left: 50%; bottom: calc(26% + 54px); transform: translateX(-50%);
  z-index: 34; pointer-events: none;
  display: flex; align-items: center; gap: 10px;
  background: rgba(12, 18, 32, 0.82); border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 16px; padding: 9px 16px 9px 10px;
  font-weight: 800; font-size: 16px; color: #fff; white-space: nowrap;
}
#ride-key, #ride-key2 {
  display: inline-grid; place-items: center; min-width: 30px; height: 30px;
  border-radius: 8px; background: #ffd34d; color: #23180a;
  font-size: 15px; font-weight: 900; padding: 0 7px;
  box-shadow: 0 3px 0 #b8912c;
}
/* On a phone there is no E to press — the 🐴 button says it instead. */
@media (pointer: coarse) { #ride-key, #ride-key2 { display: none; } }
/* And on a narrow one 👋, on top of the 🐴, stands where the prompts are: while
   it is there they move up above it — the row's own 96, two buttons, the gap
   between them and 14 px of air — still 54 px apart. A wide screen keeps them
   where they were: the buttons are far off to the right of them. */
@media (pointer: coarse) and (max-width: 600px) {
  :root { --above-ride2: calc(96px + 2 * var(--tbtn) + var(--tgap) + 14px + env(safe-area-inset-bottom)); }
  .ride2-on #ride-prompt { bottom: max(26%, var(--above-ride2)); }
  .ride2-on #ride-prompt2 { bottom: calc(max(26%, var(--above-ride2)) + 54px); }
}
@keyframes ride-in {
  from { opacity: 0; transform: translateX(-50%) translateY(6px); }
  to { opacity: 1; transform: translateX(-50%) translateY(0); }
}

/* ---- World frame (§7: our bar stays above the world) ---- */
#world { position: fixed; inset: 0; background: #0b1020; z-index: 50; }
#world.hidden { display: none; }
#world-bar {
  position: absolute; top: 0; left: 0; right: 0; height: 64px;
  display: flex; align-items: center; gap: 18px; padding: 0 16px;
  background: #151b33; color: #fff; font-weight: 700; font-size: 16px; z-index: 2;
  padding-top: env(safe-area-inset-top);
  height: calc(64px + env(safe-area-inset-top));
}
#world-clock.low { color: #ff8a9b; }
/* Nothing in this bar may wrap: it is a fixed 64 px tall, so a second line
   simply falls out of it. On a phone "⚡ 3" was breaking between the icon and
   the number, and the world's name between its two words. */
#world-bar > * { white-space: nowrap; }
#world-title {
  opacity: .65; font-weight: 600; margin-left: auto;
  min-width: 0; overflow: hidden; text-overflow: ellipsis;
}
#world-exit {
  background: rgba(255, 255, 255, 0.12); color: #fff; border: 1px solid var(--stroke);
  width: 36px; height: 36px; border-radius: 10px; font-size: 17px; cursor: pointer;
}
#world-frame { position: absolute; inset: 0; }
#world-frame iframe { width: 100%; height: 100%; border: 0; display: block; }
#world-loading {
  position: absolute; inset: 0; display: none; flex-direction: column; gap: 14px;
  align-items: center; justify-content: center; color: #fff; background: #0b1020; z-index: 3;
}
#world.loading #world-loading { display: flex; }
/* Under our bar, not over it: the energy that just came back is shown there. */
#world-stall {
  position: absolute; left: 0; right: 0; bottom: 0; top: calc(64px + env(safe-area-inset-top));
  display: none; flex-direction: column; gap: 6px;
  align-items: center; justify-content: center; text-align: center; padding: 24px;
  color: #fff; background: #0b1020; z-index: 3;
}
#world.stalled #world-stall { display: flex; }
#world-stall p { margin: 0; }
#world-stall .stall-icon { font-size: 52px; line-height: 1.1; }
#world-stall .stall-title { font-size: 24px; font-weight: 800; }
#world-stall .stall-note { font-size: 16px; opacity: 0.8; margin-bottom: 14px; }
#world-stall-back {
  font: inherit; font-size: 19px; font-weight: 800; color: #1a1f38; background: #ffd34d;
  border: 0; border-radius: 16px; padding: 14px 30px; min-width: 200px; cursor: pointer;
}

/* ---- Boot ---- */
#boot {
  position: fixed; inset: 0; display: flex; flex-direction: column; gap: 14px;
  align-items: center; justify-content: center; color: #fff;
  background: linear-gradient(160deg, #2a3560, #121935); z-index: 70;
}
#boot.hidden { display: none; }
.spinner {
  width: 46px; height: 46px; border-radius: 50%;
  border: 5px solid rgba(255, 255, 255, 0.25); border-top-color: #ffd34d;
  animation: spin 0.9s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ---- "Позови взрослого": the pairing panel (§9) ----
   The HUD ignores pointer events so the child can look around through it, so the
   one button in there has to opt back in. */
.pill-btn {
  pointer-events: auto; cursor: pointer; font-family: inherit;
  line-height: 1; padding: 7px 12px;
}
.pill-btn:active { transform: scale(0.95); }
.pill-btn.off { opacity: 0.55; }

#parent-panel {
  position: fixed; inset: 0; z-index: 60;
  display: none; align-items: center; justify-content: center;
  background: rgba(8, 12, 24, 0.66); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  padding: 16px;
}
#parent-panel.open { display: flex; }
.parent-card {
  position: relative; width: min(94vw, 520px); max-height: 92vh; max-height: 92dvh; overflow: auto;
  background: #ffffff; color: var(--ink); border-radius: 22px;
  padding: 22px 20px 18px; text-align: center;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.4);
}
/* Clear of the ✕ on both sides (it sits in the top-right corner): the 👩‍👦 ran
   into it at 390 px and was cut off at 360. */
.parent-card h2 { margin: 0 0 6px; font-size: 24px; padding: 0 38px; }
.parent-lead { margin: 0 0 16px; font-size: 15px; line-height: 1.4; color: #4a5372; }
.parent-close {
  position: absolute; top: 10px; right: 10px; width: 36px; height: 36px;
  border: 0; border-radius: 50%; background: #eef1f8; color: #4a5372;
  font-size: 17px; cursor: pointer;
}
#parent-body { display: flex; gap: 18px; align-items: center; justify-content: center; flex-wrap: wrap; }
#parent-qr {
  width: 216px; height: 216px; border-radius: 14px;
  border: 1px solid #e3e7f2; background: #fff; image-rendering: pixelated;
}
.parent-code-wrap { min-width: 180px; }
.parent-code-hint { font-size: 13px; color: #7a839e; }
#parent-code {
  font-size: 34px; font-weight: 800; letter-spacing: 3px; margin: 4px 0 2px;
  font-variant-numeric: tabular-nums;
}
/* The address may wrap, but only before its «?code=…»: at 360 px it broke in
   the middle of the code, and a grown-up typing it off the screen got two
   halves. */
#parent-url { font-size: 13px; color: #4a5372; overflow-wrap: anywhere; }
#parent-url .code { white-space: nowrap; }
#parent-left { font-size: 13px; color: #7a839e; margin-top: 8px; }
/* The code was just used (parentlink.js, showJoined): no «наведёт камеру» and
   no «или пусть введёт код» over a code that is gone. */
#parent-panel.joined .parent-lead,
#parent-panel.joined .parent-code-hint { display: none; }
#parent-panel.joined #parent-left { font-size: 16px; font-weight: 700; color: #1f9d55; }
.parent-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin-top: 18px; padding-top: 14px; border-top: 1px solid #eef1f8;
  font-size: 14px; color: #7a839e; text-align: left;
}
#parent-status.ok { color: #1f9d55; font-weight: 700; }
.parent-btn {
  border: 0; border-radius: 12px; background: #4a63d8; color: #fff;
  font-weight: 700; font-size: 14px; padding: 10px 15px; cursor: pointer;
  font-family: inherit; white-space: nowrap;
}
.parent-btn:active { transform: scale(0.97); }

@media (max-width: 430px) {
  #parent-qr { width: 190px; height: 190px; }
  #parent-code { font-size: 29px; }
}

/* ---- The world bar on a phone ----
   Only the side padding shrinks: `padding` shorthand here would wipe out the
   safe-area padding-top and slide the bar under the notch. */
@media (max-width: 560px) {
  #world-bar {
    gap: 10px;
    padding-left: 10px;
    padding-right: 10px;
    font-size: 14px;
  }
  /* Up to two lines here: «Обби · Уровень 4 «Снежные горы»» (levelTitle) was
     cut to «…«Снежные …» on every phone, and at 360 px on all seven levels.
     Two lines of 13 px fit the 64 px bar; the title breaks between its halves
     (no-break spaces inside them), balanced. */
  #world-title {
    font-size: 13px; line-height: 1.2; text-align: right; white-space: normal;
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
    text-wrap: balance;
  }
  #world-exit { width: 32px; height: 32px; font-size: 15px; flex: 0 0 auto; }
}

/* ---- Салон красоты ----
   A full-screen card like the parent panel, but laid out as a shop: the avatar
   on the left, what you can put on them on the right. On a phone the two stack,
   and the preview shrinks rather than pushing the swatches off the screen. */
#salon-panel {
  position: fixed; inset: 0; z-index: 62;
  display: none; align-items: center; justify-content: center;
  background: rgba(18, 8, 24, 0.7); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  padding: 14px;
}
#salon-panel.open { display: flex; }
#salon-panel.flash::after {
  content: ""; position: absolute; inset: 0; background: #fff;
  animation: salon-pop 0.32s ease-out forwards; pointer-events: none;
}
@keyframes salon-pop { from { opacity: 0.9; } to { opacity: 0; } }

.salon-card {
  position: relative; width: min(96vw, 860px); max-height: 94vh; max-height: 94dvh;
  display: flex; flex-direction: column;
  background: linear-gradient(160deg, #fff3fa, #ffe3f1);
  color: var(--ink); border-radius: 24px; padding: 18px 18px 14px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45);
}
.salon-card h2 { margin: 0 0 12px; font-size: 23px; text-align: center; color: #8d2a63; }

.salon-body { display: flex; gap: 16px; min-height: 0; flex: 1; }
/* The mirror: a vanity mirror's gold frame with a row of bulbs along the top,
   because that is what a beauty salon's mirror looks like to a child. */
.salon-stage {
  position: relative; flex: 0 0 44%;
  border-radius: 20px; overflow: hidden;
  background: radial-gradient(ellipse at 50% 35%, #9a73c0, #4a2f63 75%);
  border: 5px solid #f7cf5c;
  box-shadow: 0 0 0 3px #c9962c, inset 0 0 26px rgba(0, 0, 0, 0.4), 0 6px 18px rgba(141, 42, 99, 0.35);
}
.salon-stage::before {
  content: ""; position: absolute; left: 10px; right: 10px; top: 5px; height: 14px; pointer-events: none;
  background: radial-gradient(circle, #fffbe0 0 4px, rgba(255, 236, 160, 0.75) 5px, rgba(255, 236, 160, 0) 8px) 0 0 / 28px 14px repeat-x;
  filter: drop-shadow(0 0 4px rgba(255, 240, 180, 0.9));
}
#salon-preview { width: 100%; height: 100%; display: block; touch-action: none; }
.salon-spin, .salon-before {
  position: absolute; bottom: 8px;
  height: 40px; border: 0; border-radius: 20px;
  background: rgba(255, 255, 255, 0.88); color: #8d2a63; cursor: pointer;
  font-family: inherit; font-weight: 800;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
}
.salon-spin { right: 8px; width: 40px; font-size: 17px; }
.salon-spin.off { opacity: 0.5; }
/* Held down, the mirror shows how the child came in: «Было». */
.salon-before { left: 8px; padding: 0 12px; font-size: 14px; user-select: none; -webkit-user-select: none; touch-action: none; }
.salon-before.on { background: #8d2a63; color: #fff; }

.salon-pick { flex: 1; display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.salon-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.salon-tab {
  display: flex; align-items: center; gap: 5px;
  border: 0; border-radius: 12px; background: #ffffff; color: #6b4a63;
  font-family: inherit; font-size: 13px; font-weight: 700;
  padding: 7px 10px; cursor: pointer;
}
.salon-tab.on { background: #d8467f; color: #fff; }
.salon-tab-icon { font-size: 17px; }
/* The names come from the admin panel now, so a long one wraps inside its own
   tab instead of pushing the row past the edge of a phone. */
.salon-tab { max-width: 100%; text-align: left; overflow-wrap: anywhere; }
/* The showcase (Новинки) is gold, so it reads as a shop window rather than one
   more drawer wherever the panel has put it in the row. */
.salon-tab.showcase { background: #fff1c2; color: #8a5a00; }
.salon-tab.showcase.on { background: #f2a500; color: #fff; }

.salon-hint {
  display: none; font-size: 13px; color: #8d2a63;
  background: #ffe8b8; border-radius: 10px; padding: 6px 10px; margin-bottom: 8px;
}
.salon-hint.show { display: block; }

/* Tiles, each with a picture of what it is: a child who cannot read yet picks
   by the picture, and hears the name when they tap it. */
.salon-items {
  flex: 1; overflow-y: auto; min-height: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 8px;
  align-content: start; padding: 2px;
}
.salon-item {
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  border: 3px solid transparent; border-radius: 16px;
  background: #ffffff; color: var(--ink);
  font-family: inherit; font-size: 13px; text-align: center;
  padding: 7px 5px 6px; cursor: pointer; min-width: 0;
  box-shadow: 0 2px 5px rgba(141, 42, 99, 0.12);
}
.salon-item.worn { border-color: #d8467f; background: #ffeaf4; }
.salon-item.locked { background: #f7f2f9; color: #6e5f74; }
.salon-item.trying { border-color: #f2a500; background: #fff7dd; animation: salon-try 0.9s ease-in-out infinite alternate; }
@keyframes salon-try { from { box-shadow: 0 0 0 0 rgba(242, 165, 0, 0.5); } to { box-shadow: 0 0 0 5px rgba(242, 165, 0, 0.18); } }
.salon-item:active { transform: scale(0.97); }
.salon-pic {
  width: 64px; height: 64px; flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
  border-radius: 14px; background: #f3e9f5; overflow: hidden;
}
.salon-pic.emoji { font-size: 40px; }
.salon-pic.none { font-size: 26px; color: #b9a6c2; }
.salon-thumb { width: 100%; height: 100%; display: block; }
/* Names wrap rather than truncate: "Без при…" is not a haircut anybody can
   recognise, and the tile has room for a second line. */
.salon-item-name { width: 100%; min-width: 0; line-height: 1.15; font-weight: 700; overflow-wrap: anywhere; }
.salon-item-from { position: absolute; top: 4px; left: 6px; font-size: 15px; }
.salon-dot {
  width: 46px; height: 46px; border-radius: 50%; flex: 0 0 auto;
  box-shadow: inset 0 -4px 8px rgba(0, 0, 0, 0.25), 0 1px 3px rgba(0, 0, 0, 0.2);
}
.salon-dot.plain { background: linear-gradient(135deg, #2a2f3a 45%, #e5e4df); }
.salon-price { font-size: 12px; font-weight: 800; color: #9a8fa4; white-space: nowrap; min-height: 14px; }
.salon-price.cost { color: #c06a00; }
.salon-price.worn { color: #d8467f; }
.salon-buy {
  width: 100%; margin-top: 2px; padding: 7px 4px; border-radius: 11px;
  background: #2fb35a; color: #fff; font-weight: 800; font-size: 13px; line-height: 1.1;
  box-shadow: 0 3px 0 #1f8a42;
}
.salon-buy.poor { background: #b9a6c2; box-shadow: 0 3px 0 #9a87a4; }

.salon-foot {
  display: flex; align-items: center; gap: 10px;
  margin-top: 12px; padding-top: 11px; border-top: 1px solid #f3cfe2;
}
.salon-wallet { flex: 1; font-size: 17px; font-weight: 800; color: #8d2a63; }
.salon-btn {
  border: 0; border-radius: 13px; background: #ffffff; color: #8d2a63;
  font-family: inherit; font-weight: 700; font-size: 15px;
  padding: 10px 16px; cursor: pointer;
}
.salon-btn.primary { background: #d8467f; color: #fff; }
.salon-btn:active { transform: scale(0.97); }

@media (max-width: 620px) {
  .salon-card { padding: 14px 12px 10px; }
  .salon-card h2 { font-size: 19px; margin-bottom: 8px; }
  .salon-body { flex-direction: column; gap: 10px; }
  /* Зеркало поменьше, а вкладки — одной строкой, которая листается вбок.
     На 360×640 зеркало в 34vh и семь вкладок в четыре ряда оставляли полке
     95 px — меньше одной плитки: ребёнок видел полплитки, и «Не хватает 💰»
     без самой вещи. Теперь на полке видно два ряда и больше. */
  .salon-stage { flex: 0 0 min(27vh, 250px); flex: 0 0 min(27dvh, 250px); }
  .salon-tabs {
    flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-x: contain;
    scrollbar-width: none; margin: 0 -12px 8px; padding: 0 12px 2px;
    /* Край строки тает — видно, что там есть ещё. */
    -webkit-mask-image: linear-gradient(to right, #000 88%, transparent);
    mask-image: linear-gradient(to right, #000 88%, transparent);
  }
  .salon-tabs::-webkit-scrollbar { display: none; }
  .salon-tab { flex: none; white-space: nowrap; max-width: none; }
  .salon-items { grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 6px; }
  .salon-pic { width: 54px; height: 54px; }
  .salon-dot { width: 40px; height: 40px; }
  .salon-foot { margin-top: 8px; padding-top: 8px; }
}
/* Высокий телефон (390×844 и выше): места полке хватает и с тремя рядами вкладок,
   а в одну строку, листающуюся вбок, влезало две с половиной из семи: макияж,
   одежда и тату — то, за чем ребёнок пришёл, — были за краем, о котором знала
   только тающая кромка. Все семь на виду. */
@media (max-width: 620px) and (min-height: 760px) {
  .salon-tabs {
    flex-wrap: wrap; overflow: visible; margin: 0 0 8px; padding: 0;
    -webkit-mask-image: none; mask-image: none;
  }
  .salon-tab { flex: 0 1 auto; }
}
/* Низкий экран (телефон 360×640 и ниже): заголовок и зеркало ещё меньше. */
@media (max-width: 620px) and (max-height: 700px) {
  #salon-panel { padding: 8px; }
  .salon-card { max-height: calc(100vh - 16px); max-height: calc(100dvh - 16px); padding: 10px 10px 8px; }
  .salon-card h2 { font-size: 17px; margin-bottom: 6px; }
  .salon-stage { flex-basis: min(25vh, 200px); flex-basis: min(25dvh, 200px); }
  .salon-body { gap: 8px; }
  .salon-btn { padding: 8px 14px; }
}

/* ---- Рыбалка ----
   Sits above the joystick on a phone and centred low on a desktop: while you
   are in the boat this is the only thing you can do, so it owns the bottom of
   the screen and nothing else has to move out of its way. */
#fish-panel {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(18px + env(safe-area-inset-bottom));
  z-index: 55; display: none;
  width: min(94vw, 460px);
  background: rgba(12, 28, 44, 0.86); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
  border-radius: 20px; padding: 12px 14px;
  box-shadow: 0 14px 40px rgba(0, 0, 0, 0.45);
  color: #eaf4ff;
}
#fish-panel.open { display: block; }
#fish-panel.biting { background: rgba(70, 18, 40, 0.9); }

.fish-row { display: flex; align-items: center; gap: 10px; }
.fish-words { flex: 1; min-width: 0; }
#fish-state { font-size: 18px; font-weight: 800; line-height: 1.2; }
#fish-panel.biting #fish-state { color: #ffd34d; animation: fish-shout 0.4s ease-in-out infinite alternate; }
@keyframes fish-shout { from { transform: scale(1); } to { transform: scale(1.06); } }
#fish-hint { font-size: 13px; opacity: 0.75; margin-top: 2px; }
#fish-tally { font-size: 13px; opacity: 0.9; margin-top: 4px; font-weight: 700; }

.fish-btn {
  flex: 0 0 auto; width: 52px; height: 52px;
  border: 0; border-radius: 50%; background: rgba(255, 255, 255, 0.16);
  color: #fff; font-size: 24px; cursor: pointer; font-family: inherit;
}
.fish-btn.big { width: 66px; height: 66px; font-size: 30px; background: #2f86c9; }
#fish-panel.biting .fish-btn.big { background: #ff2d78; animation: fish-shout 0.3s ease-in-out infinite alternate; }
.fish-btn:disabled { opacity: 0.4; }
.fish-btn:active { transform: scale(0.94); }

/* The strike window, draining left to right. */
.fish-bar {
  height: 0; overflow: hidden; border-radius: 6px;
  background: rgba(255, 255, 255, 0.2); margin-bottom: 0;
  transition: height 0.12s ease, margin-bottom 0.12s ease;
}
.fish-bar.show { height: 10px; margin-bottom: 10px; }
#fish-fill { height: 100%; width: 100%; background: linear-gradient(90deg, #ffd34d, #ff2d78); }

/* The catch, popped up over the panel. */
.fish-card-pop {
  position: absolute; left: 50%; bottom: 100%; transform: translate(-50%, 8px);
  display: flex; align-items: center; gap: 10px;
  background: #fff; color: #163049; border-radius: 16px;
  padding: 10px 16px; margin-bottom: 10px; white-space: nowrap;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.4);
  opacity: 0; pointer-events: none; transition: opacity 0.2s ease, transform 0.2s ease;
}
.fish-card-pop.show { opacity: 1; transform: translate(-50%, 0); }
.fish-card-pop.rare { background: linear-gradient(120deg, #fff3c4, #ffd34d); }
.fish-card-icon { font-size: 30px; }
.fish-card-name { font-weight: 800; font-size: 17px; }
.fish-card-coins { font-weight: 800; color: #c06a00; }

@media (max-width: 620px) {
  /* Clear of the joystick thumb and the jump button. */
  #fish-panel { bottom: calc(150px + env(safe-area-inset-bottom)); width: 92vw; }
}

/* ---- 🏆 Награды ----
   Для читателя шести лет: крупная иконка, короткое название, и у каждой
   незаработанной — полоска «сколько осталось». Смысл списка в том, что
   следующая награда кажется достижимой; серый квадрат, который когда-нибудь
   загорится, этого не делает. */
#awards-panel {
  position: fixed; inset: 0; z-index: 62;
  display: none; align-items: center; justify-content: center;
  background: rgba(18, 8, 24, 0.7); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  padding: 14px;
}
#awards-panel.open { display: flex; }
.awards-card {
  position: relative;
  width: min(560px, 96vw); max-height: 88vh; max-height: 88dvh; overflow-y: auto;
  background: linear-gradient(170deg, #2e3a6e, #1a2144);
  border: 2px solid #4a63d8; border-radius: 20px;
  padding: 18px 18px 22px; color: #fff;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.5);
}
.awards-card h2 { margin: 0 0 4px; font-size: 22px; }
.awards-count { margin: 0 0 14px; color: #b9c4ee; font-size: 15px; }
.awards-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 10px; }

.award {
  display: flex; gap: 10px; align-items: flex-start;
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 14px; padding: 11px 12px;
}
.award.done {
  background: linear-gradient(150deg, rgba(255, 211, 77, 0.22), rgba(255, 211, 77, 0.07));
  border-color: #ffd34d;
}
.award-icon { font-size: 26px; line-height: 1; filter: grayscale(1); opacity: 0.4; }
.award.done .award-icon { filter: none; opacity: 1; }
.award-body { flex: 1; min-width: 0; }
.award-body b { display: block; font-size: 15px; line-height: 1.2; }
.award-sub { display: block; font-size: 12px; color: #b9c4ee; margin-top: 2px; }
.award-bar { display: block; height: 5px; border-radius: 3px; background: rgba(255, 255, 255, 0.15); margin-top: 6px; overflow: hidden; }
.award-bar i { display: block; height: 100%; background: #6f8bff; border-radius: 3px; }
.award.done .award-bar i { background: #ffd34d; }

/* Только что заработанная — коротко подпрыгивает, чтобы её заметили. */
.award.fresh { animation: award-pop 0.7s ease-out 2; }
@keyframes award-pop {
  0%, 100% { transform: none; }
  30% { transform: scale(1.06) rotate(-1.5deg); }
  60% { transform: scale(1.02) rotate(1deg); }
}

/* ---- 🏅 Рекорды ----
   The same lists as the boards in the park, in type a six-year-old can read
   on an upright phone: ten big rows, and "ты" in green. */
#records-panel {
  position: fixed; inset: 0; z-index: 62;
  display: none; align-items: center; justify-content: center;
  background: rgba(18, 8, 24, 0.7); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  padding: 14px;
}
#records-panel.open { display: flex; }
.records-card {
  position: relative;
  width: min(480px, 96vw); max-height: 88vh; max-height: 88dvh; overflow-y: auto;
  background: linear-gradient(170deg, #2e3a6e, #1a2144);
  border: 2px solid #ffd34d; border-radius: 20px;
  padding: 18px 16px 18px; color: #fff;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.5);
}
.records-card h2 { margin: 0 0 10px; font-size: 22px; }
.records-tabs { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; padding-right: 40px; }
.records-tab {
  border: 0; border-radius: 12px; padding: 9px 14px; font-weight: 800; font-size: 16px;
  background: rgba(255, 255, 255, 0.12); color: #dfe6ff; cursor: pointer;
}
.records-tab.on { background: #ffd34d; color: #241a08; }
.records-sub { margin: 0 0 10px; color: #b9c4ee; font-size: 14px; }
.records-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.records-row {
  display: flex; align-items: center; gap: 10px;
  background: rgba(255, 255, 255, 0.07); border-radius: 14px; padding: 8px 12px;
  font-size: 19px; font-weight: 800;
}
.records-place {
  flex: none; width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center;
  background: #3a4a7a; font-size: 16px; font-weight: 900;
}
.records-row.m1 .records-place { background: #ffd34d; color: #241a08; }
.records-row.m2 .records-place { background: #d7e1ea; color: #241a08; }
.records-row.m3 .records-place { background: #e2924a; color: #241a08; }
/* Ник переносится, а не обрезается: «Триплет 3…» на двух строках списка — это
   два разных ребёнка, и различало их как раз то, что съедало многоточие. */
.records-nick { flex: 1; min-width: 0; overflow-wrap: anywhere; line-height: 1.15; }
@media (max-width: 400px) {
  .records-row { font-size: 17px; gap: 8px; padding: 8px 10px; }
}
.records-val { flex: none; color: #ffd34d; }
.records-row.me { background: rgba(110, 240, 138, 0.22); outline: 2px solid #6ef08a; }
.records-row.me .records-nick { color: #6ef08a; }
.records-empty { padding: 14px; text-align: center; color: #dfe6ff; font-size: 17px; font-weight: 700; }
.records-you { margin: 12px 0 0; text-align: center; color: #6ef08a; font-weight: 800; font-size: 18px; }

/* ---- Телефон на боку ----
   Колонка справа (четыре кнопки, 🎨, 😊 и 💬) рассчитана на высоту 640 и больше.
   Лёжа экран 360–430 высотой, и колонка ложилась на кнопки внизу: кружок прыжка —
   ровно на 👩‍👦 (тап по «позвать взрослого» нажимал прыжок), а 😊 и 💬 — на 🎥 и
   🔊. Поэтому лёжа: кнопки-инструменты уходят в верхний ряд, к показаниям, где
   слева и посередине пусто; в колонке справа остаются 🎨, а под ней 😊 и 💬 — над
   кнопками прыжка, которые опущены к самому низу. */
@media (pointer: coarse) and (max-height: 460px) {
  :root { --tbtn: 66px; --tgap: 10px; }
  #hud-tools {
    position: static; flex-direction: row; gap: 6px; z-index: auto;
  }
  #hud-tools .pill-btn { width: 42px; height: 42px; font-size: 20px; }
  .touch-buttons { bottom: calc(16px + env(safe-area-inset-bottom)); }
  #skin-block { top: calc(58px + env(safe-area-inset-top)); }
  #skin-block .skin-label { width: 42px; height: 42px; font-size: 20px; }
  #skin-block { min-width: 42px; min-height: 42px; }
  #social {
    bottom: calc(16px + var(--tbtn) + 10px + env(safe-area-inset-bottom));
    gap: 8px;
  }
  .wheel-btn, .social-toggle { width: 44px; height: 44px; font-size: 22px; }
  /* Открытые колесо и фразы — левее колонки, а не поверх неё. */
  #wheel, #phrases {
    right: calc(74px + env(safe-area-inset-right));
    bottom: calc(16px + var(--tbtn) + 10px + env(safe-area-inset-bottom));
  }
  #wheel { grid-template-columns: repeat(4, 44px); gap: 6px; padding: 8px; }
}
@media (pointer: coarse) and (max-height: 460px) and (max-width: 600px) {
  :root { --above-ride2: calc(16px + 2 * var(--tbtn) + var(--tgap) + 14px + env(safe-area-inset-bottom)); }
}

/* «Позови взрослого» лёжа: QR слева, код справа — код выше сгиба (карточка в
   два ряда была выше экрана 390, и цифры уходили под нижний край). */
@media (max-height: 460px) {
  .parent-card { width: min(94vw, 680px); padding: 12px 18px 12px; }
  .parent-card h2 { font-size: 20px; margin-bottom: 4px; }
  .parent-lead { display: none; }
  #parent-body { flex-wrap: nowrap; gap: 20px; }
  #parent-qr { width: 150px; height: 150px; flex: none; }
  .parent-code-wrap { min-width: 0; text-align: left; }
  #parent-code { font-size: 30px; }
  .parent-foot { margin-top: 10px; padding-top: 10px; }
}
