/* ==========================================================================
   Марго Квиз — Design System v2 «Неон-сцена»
   captain.css — ЭКРАНЫ КАПИТАНА. Стадия 04, вторая поверхность.

   Требует: tokens.css (блок .mk-captain — шкала, --tap, межстрочник),
   motion.css, components.css (предметы 13–23 и 32).

   ЧТО ТАКОЕ ЭКРАН КАПИТАНА. Не слот внутри сцены, как в зале, а всё окно
   целиком: телефон держат в руке, и на нём в каждый момент живёт ровно одно
   дело. Каркас один на все экраны — шапка, тело, зона действия внизу под
   большим пальцем; меняется только тело.

   ТРИ ВЕЩИ, КОТОРЫХ НЕТ В ЗАЛЕ И БЕЗ КОТОРЫХ ЭКРАН В РУКЕ НЕ РАБОТАЕТ:

   1. БЕЗОПАСНЫЕ ЗОНЫ. Приложение ставится на домашний экран и открывается
      без адресной строки: сверху вырез камеры, снизу полоса жеста «домой».
      Полоса перекрывает нижние 34 pt — ровно там, где у капитана буззер.
      Отсюда env(safe-area-inset-*) в каркасе, а не в отдельных экранах.
   2. ВЫСОТА ОКНА ПЛАВАЕТ. Адресная строка мобильного браузера то есть, то
      нет; 100vh при этом врёт на её высоту, и низ экрана уезжает под неё.
      Поэтому 100dvh с откатом на 100vh для старых браузеров.
   3. ДЕЙСТВИЕ ВНИЗУ. Большой палец достаёт до нижней трети экрана; верх
      телефона — зона чтения, а не нажатия. Зона действия закреплена внизу
      и не уезжает вместе с содержимым.

   ЦВЕТ ЭМОЦИИ ЖИВЁТ И ЗДЕСЬ. Телефон капитана несёт тот же data-emotion,
   что сцена зала: пока Марго говорит с подколкой, экран в руке светится
   тем же светом, что экран на стене. Это самая дешёвая связь между двумя
   поверхностями и единственная, которую видно из любой точки зала.
   ========================================================================== */

.mk-captain {
    position: relative;
    display: grid;
    grid-template-rows: auto 1fr auto;
    /* КОЛОНКУ НАДО ОБЪЯВИТЬ ЯВНО, И ЭТО НЕ ФОРМАЛЬНОСТЬ. Без неё грид
       создаёт неявную колонку размером auto, а auto тянется до max-content
       ребёнка — и шапка с nowrap-строкой «Ночная смена промысла ГКП-51 ·
       Себастьян Перейро» распирала ВСЮ ПОВЕРХНОСТЬ на 226 px за правую
       кромку телефона. Многоточие в шапке при этом не срабатывало вовсе:
       обрезать было нечего, места хватало. minmax(0, 1fr) возвращает
       ограничение, и дальше работают и автоподгон кегля, и многоточие.
       Найдено переносом капитана 28.08 на самом длинном имени проекта. */
    grid-template-columns: minmax(0, 1fr);
    gap: var(--sp-4);
    min-height: 100vh;
    min-height: 100dvh;
    /* И ПОТОЛОК ТОЖЕ. Без него grid-template-rows: auto 1fr auto растёт
       вслед за содержимым: min-height — это пол, а не рамка. Пока все
       экраны были короче кадра, разницы не было; анкета регистрации
       на 375×812 вытянула поверхность до 1073 px, и вместо тела
       прокручивалась ВСЯ СТРАНИЦА — вместе с заголовком и кнопкой
       «Получить допуск», которую после этого надо искать, домотав донизу.
       С потолком строка 1fr ограничена, и прокрутка достаётся телу,
       как и задумано. Клавиатура телефона уменьшает dvh — зона действия
       остаётся над ней, а не уезжает под неё. */
    max-height: 100dvh;
    /* ПОЛЯ ПО БОКАМ ШИРЕ, ЧЕМ СВЕРХУ И СНИЗУ: 24 против 16. На приёмке
       содержимое читалось прижатым к кромкам — на 390 px шестнадцати
       пикселей мало, тем более что у карточек внутри есть свой паддинг,
       и глаз складывает их в одну тесную полосу. По вертикали место дороже:
       там его отнимают шапка, зона действия и системные полосы. */
    padding: calc(env(safe-area-inset-top, 0px) + var(--sp-4))
             calc(env(safe-area-inset-right, 0px) + var(--sp-5))
             calc(env(safe-area-inset-bottom, 0px) + var(--sp-4))
             calc(env(safe-area-inset-left, 0px) + var(--sp-5));
    background: var(--bg-0);
    color: var(--text-hi);
    font-family: var(--font-body);
    overflow: hidden;

    /* ДЛИННОЕ РУССКОЕ СЛОВО ОБЯЗАНО ПЕРЕНОСИТЬСЯ. Иначе оно не переносится
       никак: «Восстанавливаем» в --fs-h2 занимает 360 px при ширине тела 342,
       и никакой автоподгон тут не спасёт — уменьшать кегль ради одного слова
       значит уменьшить весь экран. Переносы по слогам (hyphens работают
       благодаря lang="ru" в разметке) плюс break-word как страховка для
       того, что не переносится по правилам: адресов, кодов, длинных
       названий команд. */
    hyphens: auto;
    overflow-wrap: break-word;
}

/* Живой фон — одно пятно в цвете эмоции, а не три, как в зале: телефон
   рисует его на батарее игрока, и второе пятно уже не окупается. */
.mk-captain::before {
    content: "";
    position: absolute;
    left: 50%;
    top: -30%;
    z-index: 0;
    width: 160%;
    height: 70%;
    transform: translateX(-50%);
    background: radial-gradient(ellipse at 50% 50%,
        var(--emotion-faint) 0%, transparent 70%);
    pointer-events: none;
}

[data-perf="low"] .mk-captain::before { display: none; }

.mk-captain > * { position: relative; z-index: 1; }

/* Тело экрана — единственная зона, которая меняется. Прокрутка разрешена
   только ей: шапка и действие остаются на месте всегда. */
.mk-captain__body {
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
    min-height: 0;
    overflow-y: auto;
    /* ГОРИЗОНТАЛЬНОЙ ПРОКРУТКИ У ЭКРАНА В РУКЕ НЕ БЫВАЕТ. Она появлялась сама:
       overflow-y: auto делает блок скролл-контейнером по обеим осям, а любая
       анимация scale внутри (дышащий бейдж таймера, пульс кнопки) расширяет
       его прокручиваемую область — и внизу кадра вылезала полоса прокрутки
       на пустом месте. Здесь она не «спрятана от глаз»: по горизонтали
       прокручивать в этом интерфейсе нечего и незачем. */
    overflow-x: hidden;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
}

/* Тело, у которого одно дело по центру: буззер, вердикт, ожидание.
   Ширину детям задаём явно: при align-items: center флекс-элемент получает
   ширину по содержимому и разъезжается шире телефона — экран ожидания
   с двумя цифрами в ряд вылезал за правый край кадра. */
.mk-captain__body--center {
    justify-content: center;
    align-items: center;
    text-align: center;
}

.mk-captain__body--center > * { width: 100%; }

.mk-captain__act {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
}

/* ==========================================================================
   1 · Вход по PIN
   Состояния: пусто · четыре цифры · отвергнут · сети нет ·
              сессия восстановлена из памяти телефона
   ========================================================================== */

.mk-enter-view {
    justify-content: center;
    gap: var(--sp-6);
    text-align: center;
}

.mk-enter-view__mark {
    --mk-enter-mark: 72px;
    width: var(--mk-enter-mark);
    height: var(--mk-enter-mark);
    margin: 0 auto;
    color: var(--emotion-soft);
}

.mk-enter-view__mark svg { width: 100%; height: 100%; }

.mk-enter-view__title {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: var(--fs-h1);
    line-height: 1.1;
    /* ЗАГОЛОВОК НЕ РУБИТСЯ ПОСРЕДИ СЛОВА. .mk-captain включает
       overflow-wrap: break-word на всю поверхность — для длинного имени
       команды в шапке это спасение, для дисплейного заголовка приговор:
       «С возвращением» на 375 px ложилось как «с / возвращен / ием»,
       без переносного знака и в три строки. Здесь перенос по словам,
       а слово, которое не влезло, честно вылезает — и его ловит либо
       приёмка, либо MargoFit по data-fit, уменьшая кегль до пола чтения.
       Молчаливый обрубок не ловит никто. */
    overflow-wrap: normal;
}

.mk-enter-view__sub {
    font-size: var(--fs-body);
    color: var(--text-mid);
}

/* Ссылки внизу входа: получить допуск и пред-игровые загадки. Не кнопки —
   это соседние двери, а не действие этого экрана. */
.mk-enter-view__links {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
    font-size: var(--fs-body);
}

.mk-enter-view__links a { color: var(--emotion-soft); }

/* Сессия восстановлена: капитан уже входил, PIN лежит в памяти телефона.
   Экран входа при этом не показывается вовсе — но состояние есть, и его
   надо уметь показать: «входим как …» с возможностью выйти. */
.mk-enter-view__resume {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
    border-radius: var(--r-md);
    background: var(--glass-bg);
    border: 1px solid var(--emotion-border);
    text-align: left;
    font-size: var(--fs-small);
    color: var(--text-mid);
}

/* Кнопка «Не мы» стоит В СТРОКЕ, а не под ней: .mk-send по умолчанию
   занимает всю ширину — это верно для зоны действия внизу, где кнопка
   одна и главная. Здесь она второстепенная и делит строку с именем
   команды, поэтому ширина по содержимому и сжиматься ей нечем. */
.mk-enter-view__resume .mk-send {
    width: auto;
    flex: none;
    padding-inline: var(--sp-4);
}

.mk-enter-view__resume b { color: var(--text-hi); font-size: var(--fs-body); }

/* ==========================================================================
   2 · Регистрация
   Состояния: анкета · обязательное не заполнено · допуск получен (PIN)
   Семь полей, четыре обязательных. Анкета — единственный длинный экран
   капитана, и она единственная, которой разрешено прокручиваться целиком.
   ========================================================================== */

.mk-signup-view { gap: var(--sp-5); }

.mk-signup-view__title {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: var(--fs-h2);
}

.mk-signup-view__note {
    font-size: var(--fs-small);
    color: var(--text-mid);
}

/* Допуск получен. PIN — единственное, что капитан отсюда унесёт, поэтому он
   и есть весь экран: крупно, моноширинно, с подписью, что его спросят. */
.mk-signup-done {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sp-5);
    text-align: center;
}

.mk-signup-done__pin {
    padding: var(--sp-4) var(--sp-6);
    border-radius: var(--r-lg);
    border: 1px solid var(--emotion);
    background: var(--emotion-faint);
    font-family: var(--font-num);
    font-variant-numeric: tabular-nums;
    font-size: var(--fs-hero);
    letter-spacing: 0.16em;
    line-height: 1;
    color: var(--text-hi);
    box-shadow: var(--glow-emotion-soft);
}

/* Персональная реплика Марго с печатной анимацией — то, ради чего экран
   успеха вообще смотрят. Курсор мигает, пока текст набирается. */
.mk-signup-done__say {
    padding: var(--sp-4);
    border-radius: var(--r-md);
    border-left: 3px solid var(--emotion);
    background: var(--glass-bg);
    text-align: left;
    font-size: var(--fs-body);
    color: var(--text-hi);
}

.mk-signup-done__say i {
    display: inline-block;
    width: 2px;
    height: 1em;
    margin-left: 2px;
    background: var(--emotion-soft);
    vertical-align: text-bottom;
    animation: mk-caret 1s steps(2) infinite;
}

@keyframes mk-caret { 50% { opacity: 0; } }

/* ==========================================================================
   3 · Тест связи
   Состояния: шаг 1 буззер · шаг 2 голосование · шаг 3 текст ·
              шаг 4 таймер и счёт · игра началась, а капитан на тесте
   Тест — единственное место, где капитан жмёт кнопки без последствий.
   Задача экрана: научить пальцем, а не текстом.
   ========================================================================== */

.mk-selftest-view { gap: var(--sp-5); text-align: center; }

.mk-selftest-view__steps {
    display: flex;
    justify-content: center;
    gap: var(--sp-2);
}

.mk-selftest-view__steps i {
    --mk-test-dot: 10px;
    width: var(--mk-test-dot);
    height: var(--mk-test-dot);
    border-radius: var(--r-full);
    background: var(--glass-border);
}

.mk-selftest-view__steps i.done { background: var(--ok); }
.mk-selftest-view__steps i.now {
    background: var(--emotion);
    box-shadow: var(--glow-emotion-soft);
}

.mk-selftest-view__task {
    font-size: var(--fs-h2);
    font-weight: 600;
    color: var(--text-hi);
}

.mk-selftest-view__hint { font-size: var(--fs-body); color: var(--text-mid); }

.mk-selftest-view__count {
    font-family: var(--font-num);
    font-variant-numeric: tabular-nums;
    font-size: var(--fs-h1);
    color: var(--emotion-soft);
}

/* Замер задержки — единственное число теста, которое что-то значит для
   оператора: по нему видно, потянет ли зал буззер. */
.mk-selftest-view__ms {
    font-family: var(--font-num);
    font-size: var(--fs-body);
    color: var(--text-dim);
}

/* Игра началась, а капитан застрял на тесте. Сервер выкидывает его на
   ожидание принудительно — экран обязан объяснить, почему всё исчезло. */
.mk-selftest-view--interrupted .mk-selftest-view__task { color: var(--warn); }

/* ==========================================================================
   4 · Игровые экраны: буззер, голосование, текстовый ответ
   Тела состоят из компонентов 15–17; экран отвечает за то, где стоит
   вопрос и куда уходит действие.
   ========================================================================== */

.mk-play-view__question {
    font-size: var(--fs-h2);
    line-height: 1.3;
    color: var(--text-hi);
    text-wrap: balance;
}

/* Строка «тур · таймер»: бейдж не жмётся и не переносится, название тура
   уступает ему место. На приёмке было наоборот — длинное название ломалось
   в две строки и выдавливало бейдж, у которого подпись тоже переносилась. */
.mk-play-view__tour {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
}

/* Длинное название тура уходит на свою строку целиком, а не режется
   многоточием: «тур 3 · промысловый юмор» вместе с бейджем таймера
   не помещается в 342 px, и подрезать здесь нечего — обе части нужны. */
.mk-play-view__tour > .mk-label { white-space: nowrap; }

.mk-play-view__tour > .mk-timer-badge { flex: none; }

/* ==========================================================================
   5 · Пред-игра: пять загадок
   Состояния: обзор пяти дней · день закрыт · день открыт · день разгадан ·
              все дни открыты · финал заблокирован · финал доступен ·
              слово собрано · разгадано ранее
   Отдельная ветка: идёт ПОСЛЕ регистрации и ДО игры, по одной загадке в день,
   за каждую — буква; пять букв складываются в слово и дают +3 на старте.
   ========================================================================== */

.mk-riddle-view { gap: var(--sp-5); }

/* Полоса букв — главный носитель прогресса: пять слотов, открытые буквы
   стоят на своих местах, закрытые молчат. */
.mk-riddle-letters {
    display: flex;
    justify-content: center;
    gap: var(--sp-3);
}

.mk-riddle-letters span {
    --mk-letter: 52px;
    width: var(--mk-letter);
    height: var(--mk-letter);
    display: grid;
    place-items: center;
    border-radius: var(--r-md);
    background: var(--glass-bg);
    border: 1px solid var(--glass-border);
    font-family: var(--font-display);
    font-weight: 700;
    font-size: var(--fs-h2);
    color: var(--text-dim);
}

.mk-riddle-letters span.open {
    border-color: var(--emotion);
    background: var(--emotion-faint);
    color: var(--text-hi);
}

/* Карточка дня. Три судьбы: закрыт (ждём даты), открыт (можно отвечать),
   разгадан (буква в копилке). */
.mk-riddle-day {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
    padding: var(--sp-4);
    border-radius: var(--r-md);
    background: var(--glass-bg);
    border: 1px solid var(--glass-border);
}

.mk-riddle-day__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-3);
    font-family: var(--font-body);
    font-size: var(--fs-label);
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--text-dim);
}

.mk-riddle-day__text { font-size: var(--fs-body); color: var(--text-hi); }

.mk-riddle-day__hint {
    font-size: var(--fs-small);
    font-style: italic;
    color: var(--text-mid);
}

.mk-riddle-day--locked { opacity: 0.5; }
.mk-riddle-day--locked .mk-riddle-day__head { color: var(--text-dim); }

.mk-riddle-day--open { border-color: var(--emotion-border); }

.mk-riddle-day--solved { border-color: var(--ok); }
.mk-riddle-day--solved .mk-riddle-day__head { color: var(--ok); }

/* Буква, полученная за день. Не «галочка», а именно буква: она и есть приз. */
.mk-riddle-day__letter {
    align-self: flex-start;
    padding: var(--sp-2) var(--sp-4);
    border-radius: var(--r-full);
    background: var(--ok-glow);
    font-family: var(--font-display);
    font-weight: 700;
    font-size: var(--fs-h3);
    color: var(--ok);
}

/* Финальное слово. Заблокировано, пока открыты не все пять букв. */
.mk-riddle-final {
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
    padding: var(--sp-5);
    border-radius: var(--r-lg);
    background: var(--glass-bg);
    border: 1px solid var(--emotion-border);
    text-align: center;
}

.mk-riddle-final--locked { border-color: var(--glass-border); opacity: 0.6; }

/* Слово из пяти букв в --fs-hero с трекингом 0.16em занимает 408 px —
   шире телефона вместе с полями карточки, и последняя буква уезжала за край.
   Кегль на ступень ниже, трекинг вдвое меньше, плюс автоподгон в разметке
   (data-fit="hero"): слово, которое собирали пять дней, обязано читаться
   целиком. */
.mk-riddle-final__word {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: var(--fs-h1);
    letter-spacing: 0.08em;
    line-height: 1.1;
    color: var(--emotion-soft);
    white-space: nowrap;
}

.mk-riddle-final__bonus {
    font-size: var(--fs-body);
    color: var(--ok);
}

/* ==========================================================================
   6 · Оверлей факта «а это ты знал?»
   Приходит после вердикта и держится до следующей смены состояния.
   Единственный экран капитана, который ничего не просит.
   ========================================================================== */

.mk-fact-card {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
    padding: var(--sp-4);
    border-radius: var(--r-md);
    background: var(--glass-bg);
    border-left: 3px solid var(--emotion);
    text-align: left;
}

.mk-fact-card__text { font-size: var(--fs-body); color: var(--text-hi); }
