﻿/* Живая викторина: экран зрителя, пульт админа и TV-экран для OBS.

   Стили лежат общим файлом, а не в scoped css компонентов, потому что все три экрана делят один
   визуальный словарь (таймер, столбики, таблица топа), а два из трёх компонента используются
   и на /quiz, и на /quiz/tv. */

/* ------------------------------------------------------------------ экран зрителя */

.quiz-live-shell {
    display: flex;
    flex-direction: column;
    gap: 16px;
    width: 100%;
}

.quiz-live-shell__tv-link {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    font-size: 0.8rem;
    opacity: 0.7;
    word-break: break-all;
}

/* Одна колонка с ограниченной шириной: экран читается с телефона одной рукой,
   а на десктопе не расползается на всю ширину монитора. */
.quiz-live {
    display: flex;
    flex-direction: column;
    gap: 18px;
    width: 100%;
    max-width: 640px;
    margin: 0 auto;
    padding: 8px 4px 48px;
}

.quiz-live__placeholder,
.quiz-live__blocker,
.quiz-live__accepted,
.quiz-live__closed {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    text-align: center;
    padding: 32px 16px;
}

.quiz-live__muted {
    opacity: 0.7;
}

/* Предстартовая карточка. Зритель смотрит на неё все 10–15 минут разминки, поэтому она не «заглушка
   до контента», а полноценный экран: единственное место, где объясняются правила эфира. */
.quiz-live-intro {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 18px;
    padding: 32px 22px 28px;
    border-radius: 20px;
    border: 1px solid rgba(255, 255, 255, 0.1);
    /* Мягкий световой градиент сверху: карточка не выглядит пустой при трёх строках текста. */
    background:
        radial-gradient(120% 90% at 50% -20%, rgba(124, 108, 255, 0.22), transparent 62%),
        rgba(255, 255, 255, 0.03);
    text-align: center;
}

.quiz-live-intro__badge {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 14px 6px 10px;
    border-radius: 999px;
    background: rgba(255, 107, 107, 0.14);
    color: #ff8a80;
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

/* Пульс — единственная движущаяся деталь на экране ожидания: она отличает «страница живая»
   от «страница зависла», а именно этот вопрос зритель задаёт себе, пока ничего не происходит. */
.quiz-live-intro__dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: currentColor;
    animation: quiz-live-pulse 1.8s ease-in-out infinite;
}

@keyframes quiz-live-pulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50% { opacity: 0.35; transform: scale(0.75); }
}

.quiz-live-intro__title {
    margin: 0;
    font-size: clamp(1.5rem, 6vw, 2.1rem);
    font-weight: 800;
    line-height: 1.15;
    letter-spacing: -0.01em;
}

.quiz-live-intro__subtitle {
    margin: -8px 0 0;
    max-width: 380px;
    opacity: 0.62;
    line-height: 1.45;
}

.quiz-live-intro__rules {
    list-style: none;
    margin: 4px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
    width: 100%;
    max-width: 420px;
    text-align: left;
}

.quiz-live-intro__rules li {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 12px 14px;
    border-radius: 12px;
    line-height: 1.4;
    font-size: 0.95rem;
}

/* Зебра вместо рамок: три правила подряд рамками выглядят как таблица ошибок. */
.quiz-live-intro__rules li:nth-child(odd) {
    background: rgba(255, 255, 255, 0.04);
}

.quiz-live-intro__rules li .mud-icon-root {
    flex: 0 0 auto;
    margin-top: 2px;
    opacity: 0.75;
}

.quiz-live-intro__player {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 9px 16px;
    border-radius: 999px;
    border: 1px solid rgba(125, 220, 130, 0.35);
    background: rgba(76, 175, 80, 0.12);
    color: #9fe6a3;
    font-size: 0.9rem;
}

.quiz-live-intro__player strong {
    color: #f4f4f8;
}

.quiz-live__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.quiz-live__counter {
    font-size: 0.85rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    opacity: 0.65;
}

/* Таймер — самый крупный элемент после текста вопроса: он единственный, что меняется каждую секунду. */
.quiz-live__timer {
    font-size: 2rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1;
}

.quiz-live__timer--warning {
    color: #ffb547;
}

.quiz-live__timer--danger {
    color: #ff6b6b;
}

.quiz-live__timer--out {
    opacity: 0.45;
}

.quiz-live__question {
    font-size: 1.4rem;
    font-weight: 600;
    line-height: 1.35;
    margin: 0;
}

.quiz-live__actions {
    position: sticky;
    bottom: 12px;
}

/* ------------------------------------------------------------------ поле ответа */

.quiz-live-answer {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.quiz-live-options {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* Крупная область нажатия: попасть пальцем под таймером важнее, чем компактность. */
.quiz-live-option {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    min-height: 56px;
    padding: 12px 16px;
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.04);
    color: inherit;
    font-size: 1.05rem;
    text-align: left;
    cursor: pointer;
    transition: border-color 0.12s ease, background 0.12s ease;
}

.quiz-live-option:disabled {
    cursor: default;
    opacity: 0.6;
}

.quiz-live-option__marker {
    flex: 0 0 auto;
    width: 20px;
    height: 20px;
    border: 2px solid rgba(255, 255, 255, 0.35);
    border-radius: 50%;
}

.quiz-live-option--selected {
    border-color: var(--mud-palette-primary, #7c6cff);
    background: rgba(124, 108, 255, 0.16);
}

.quiz-live-option--selected .quiz-live-option__marker {
    border-color: var(--mud-palette-primary, #7c6cff);
    background: var(--mud-palette-primary, #7c6cff);
}

.quiz-live-option__text {
    flex: 1 1 auto;
}

.quiz-live-ordered-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 10px;
}

.quiz-live-ordered-row__position {
    font-weight: 700;
    opacity: 0.6;
    min-width: 20px;
}

.quiz-live-ordered-row__text {
    flex: 1 1 auto;
}

.quiz-live-placeholder {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.quiz-live-placeholder__label {
    font-size: 0.85rem;
    opacity: 0.7;
}

.quiz-live-hint {
    font-size: 0.8rem;
    opacity: 0.6;
}

.quiz-live-poll {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.quiz-live-poll-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 6px 12px;
    border-radius: 8px;
    background: rgba(255, 255, 255, 0.05);
}

/* ------------------------------------------------------------------ экран вскрытия */

.quiz-live__reveal {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

/* Иконка прижата к первой строке, а не к центру блока: под заголовком может стоять вторая строка
   с выбранным вариантом, и по центру двух строк галочка встала бы напротив пустого места. */
.quiz-live__reveal-banner {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 10px 14px;
    border-radius: 10px;
    font-weight: 600;
}

.quiz-live__reveal-banner-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

/* Ответ зрителя приходит из базы и бывает длинным — «Клото + The Призрак» или свободный ввод.
   Переносим по словам, а не обрезаем: это единственное место, где человек видит свой выбор. */
.quiz-live__reveal-choice {
    font-size: 0.85rem;
    font-weight: 500;
    opacity: 0.85;
    overflow-wrap: anywhere;
}

.quiz-live__reveal-banner--correct {
    background: rgba(76, 175, 80, 0.18);
    color: #7ddc82;
}

.quiz-live__reveal-banner--wrong {
    background: rgba(244, 67, 54, 0.16);
    color: #ff8a80;
}

.quiz-live__correct {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 14px 16px;
    border-radius: 12px;
    border: 1px solid rgba(125, 220, 130, 0.4);
}

.quiz-live__correct-label {
    font-size: 0.75rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    opacity: 0.65;
}

.quiz-live__correct-value {
    font-size: 1.25rem;
    font-weight: 700;
}

.quiz-live__explanation {
    opacity: 0.8;
    line-height: 1.45;
}

.quiz-live__personal-rank {
    padding: 10px 14px;
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.05);
}

.quiz-live__final {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.quiz-live__final-title {
    text-align: center;
}

.quiz-live__offline {
    text-align: center;
    font-size: 0.8rem;
    opacity: 0.6;
}

/* ------------------------------------------------------------------ столбики распределения */

.quiz-live-buckets {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.quiz-live-bucket__head {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    font-size: 0.9rem;
}

.quiz-live-bucket__label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.quiz-live-bucket__count {
    font-variant-numeric: tabular-nums;
    opacity: 0.7;
}

.quiz-live-bucket__track {
    height: 8px;
    border-radius: 4px;
    background: rgba(255, 255, 255, 0.08);
    overflow: hidden;
}

.quiz-live-bucket__fill {
    height: 100%;
    background: rgba(255, 255, 255, 0.28);
}

.quiz-live-bucket--correct .quiz-live-bucket__fill {
    background: #4caf50;
}

.quiz-live-bucket--correct .quiz-live-bucket__label {
    font-weight: 700;
    color: #7ddc82;
}

/* ------------------------------------------------------------------ таблица топа */

.quiz-live-board {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
    counter-reset: none;
}

.quiz-live-board__row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 12px;
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.04);
}

.quiz-live-board__row--top {
    background: rgba(255, 255, 255, 0.1);
    font-size: 1.15rem;
    font-weight: 600;
}

.quiz-live-board__row--top1 {
    background: rgba(255, 196, 0, 0.18);
}

.quiz-live-board__row--top2 {
    background: rgba(198, 198, 198, 0.16);
}

.quiz-live-board__row--top3 {
    background: rgba(205, 127, 50, 0.16);
}

.quiz-live-board__place {
    min-width: 28px;
    font-variant-numeric: tabular-nums;
    opacity: 0.7;
}

.quiz-live-board__avatar {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    object-fit: cover;
    flex: 0 0 auto;
}

.quiz-live-board__avatar--empty {
    background: rgba(255, 255, 255, 0.1);
}

.quiz-live-board__name {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.quiz-live-board__score {
    font-variant-numeric: tabular-nums;
    font-weight: 700;
}

.quiz-live-board__empty {
    opacity: 0.6;
    text-align: center;
    padding: 12px;
}

/* ------------------------------------------------------------------ пульт админа */

.quiz-live-admin {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 16px;
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 14px;
    background: rgba(255, 255, 255, 0.03);
}

.quiz-live-admin__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.quiz-live-admin__title {
    display: flex;
    align-items: center;
    gap: 12px;
}

.quiz-live-admin__status {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
    font-size: 0.9rem;
}

.quiz-live-admin__badge {
    padding: 2px 10px;
    border-radius: 999px;
    background: rgba(124, 108, 255, 0.22);
    font-weight: 700;
    font-size: 0.75rem;
    letter-spacing: 0.06em;
}

.quiz-live-admin__badge--done {
    background: rgba(76, 175, 80, 0.22);
}

.quiz-live-admin__timer,
.quiz-live-admin__answers {
    font-variant-numeric: tabular-nums;
}

/* Пороги те же, что у зрителя и на TV: админ решает, когда вскрывать, и красные секунды ему нужнее всех. */
.quiz-live-admin__timer--warning {
    color: #ffb547;
}

.quiz-live-admin__timer--danger {
    color: #ff6b6b;
    font-weight: 700;
}

.quiz-live-admin__timer--out {
    opacity: 0.55;
}

.quiz-live-admin__current {
    font-size: 1.05rem;
    font-weight: 600;
}

.quiz-live-admin__buttons {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.quiz-live-admin__note {
    font-size: 0.8rem;
    opacity: 0.65;
    line-height: 1.4;
}

.quiz-live-admin__script {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-height: 320px;
    overflow-y: auto;
}

.quiz-live-admin__script-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 8px;
    border-radius: 6px;
    font-size: 0.85rem;
}

.quiz-live-admin__script-row--current {
    background: rgba(124, 108, 255, 0.16);
}

.quiz-live-admin__script-mark {
    min-width: 14px;
}

.quiz-live-admin__script-number {
    min-width: 26px;
    opacity: 0.6;
}

.quiz-live-admin__script-text {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.quiz-live-admin__script-limit,
.quiz-live-admin__script-state {
    opacity: 0.6;
    white-space: nowrap;
}

/* ------------------------------------------------------------------ TV-экран для OBS

   Жёсткий холст 1920×1080 без адаптива: Browser Source работает с фиксированным разрешением,
   и скроллбар в кадре недопустим. Всё, что не влезает, обязано схлопываться (столбики — до топ-5,
   таблица — до топ-10), а не прокручиваться. */

/* Вьюпорт прибит к окну и режет всё за краями. position: fixed важен вдвойне: элемент выпадает
   из потока документа, поэтому body не получает высоту в 1080px и страница не скроллится ни при каком
   размере окна — ни локально, ни в Browser Source. */
.quiz-tv-viewport {
    position: fixed;
    inset: 0;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #0f1018;
}

/* Размеры холста НЕ трогаем: 1920×1080 — это то, что получит OBS. В окно он вписывается
   масштабированием (quizLive.fitCanvas), поэтому локальный предпросмотр показывает ровно тот же кадр. */
/* Сцена с глубиной: два цветных пятна за кадром и приподнятая карточка вопроса поверх них.

   Пятна нарисованы радиальными градиентами, а не размытыми div'ами: filter: blur(120px) на слое
   размером в пол-экрана Browser Source считает на КАЖДОМ кадре композитинга, и на слабой машине
   оператора это стоит дороже, чем вся остальная страница вместе взятая. Картинка та же, цена нулевая.

   В градиентах намеренно нет ключевого слова transparent: оно раскрывается в rgba(0, 0, 0, 0),
   и переход к нему тянет цвет через серый — на тёмном фоне это видно грязным ореолом. */
.quiz-tv {
    position: relative;
    flex: 0 0 auto;
    width: 1920px;
    height: 1080px;
    overflow: hidden;
    background:
        radial-gradient(760px 760px at -40px -160px, rgba(74, 59, 214, 0.45), rgba(74, 59, 214, 0) 70%),
        radial-gradient(680px 680px at calc(100% + 80px) calc(100% + 120px), rgba(31, 122, 107, 0.42), rgba(31, 122, 107, 0) 70%),
        #0f1018;
    color: #f4f4f8;
    font-size: 28px;
    transform-origin: center center;
}

.quiz-tv__stage {
    display: flex;
    flex-direction: column;
    height: 100%;
    padding: 64px 70px 70px;
    box-sizing: border-box;
}

.quiz-tv__center,
.quiz-tv__final {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 32px;
    height: 100%;
    text-align: center;
}

/* Экран ожидания: шапка с названием, счётчиком и QR, под ней облако имён во всю ширину кадра.
   QR стоит в шапке фиксированного размера — зритель, который целится в него камерой, не должен
   поймать перекомпоновку в момент, когда кто-то зашёл и облако подросло. */
.quiz-tv__intro {
    display: flex;
    flex-direction: column;
    gap: 32px;
    height: 100%;
}

.quiz-tv__intro-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 56px;
    flex: 0 0 auto;
}

.quiz-tv__intro-headings {
    display: flex;
    flex-direction: column;
    gap: 22px;
    min-width: 0;
    height: 100%;
    justify-content: space-between;
}

.quiz-tv__crowd-head {
    display: flex;
    align-items: baseline;
    gap: 18px;
    flex: 0 0 auto;
}

.quiz-tv__crowd-count {
    font-size: 88px;
    font-weight: 800;
    line-height: 1;
    color: #6ee7a0;
    font-variant-numeric: tabular-nums;
}

.quiz-tv__crowd-label {
    font-size: 26px;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: #a2a7bb;
}

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

   Строки выровнены по центру, а не по левому краю: рваный правый край при флаговом наборе читается
   как недовёрстанный список, а два мягких края дают силуэт облака. По вертикали имена центрируются
   внутри строки, а не стоят на общей базовой линии, — именно это отличает облако тегов от абзаца
   с разным кеглем. */
.quiz-tv__crowd {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    /* Пока имён мало — а это первые минуты разминки, самый долгий кадр экрана ожидания, —
       две строчки, прибитые к верху полупустого кадра, читаются как недогрузившаяся страница.
       safe center центрирует облако, пока оно влезает, и сам переходит к верхнему краю, когда
       перестаёт, — иначе при центрировании срезало бы и первую строку тоже. Два объявления подряд —
       страховка под CEF в OBS: если ключевое слово safe там не знают, строка отбрасывается
       целиком и остаётся старое поведение. */
    align-content: flex-start;
    align-content: safe center;
    justify-content: center;
    /* Основной горизонтальный воздух задаёт не gap, а собственный padding имени: он пропорционален
       кеглю, а при общем значении мелкие имена тонут в пустоте, а крупные слипаются. Четыре пикселя
       колоночного gap — просто нижний порог для двух соседних имён самой мелкой ступени: без него
       они читаются одним словом. */
    gap: 8px 4px;
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
    /* Нижний край растворяется, а не режет строку пополам. Сколько имён поместится, заранее неизвестно —
       это зависит от их длины, — поэтому последняя строка почти всегда оказывается обрезанной, и без
       растворения выглядит поломанной вёрсткой. Когда имён мало, зона растворения просто пуста:
       имена прижаты к верху (align-content: flex-start). */
    -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 120px), transparent 100%);
    mask-image: linear-gradient(to bottom, #000 calc(100% - 120px), transparent 100%);
}

/* Имя собирается из двух независимых наборов переменных: ступень кегля (--s…) и оттенок (--t…).
   Разделены они ради того, чтобы размер и цвет не коррелировали: в настоящем облаке тегов крупное
   имя не обязано быть зелёным, иначе цвет выглядит шкалой и зритель начинает искать в нём смысл. */
.quiz-tv__crowd-name {
    --crowd-size: 44px;
    --crowd-weight: 600;
    --crowd-fade: 0.85;
    --crowd-track: 0;
    --crowd-ink: #f4f4f8;

    max-width: 640px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    /* Поток смешанного кегля даёт ровную плотность только при единичном интерлиньяже: иначе высота
       строки скачет вслед за самым крупным именем в ней. */
    line-height: 1;
    padding: 0 calc(var(--crowd-size) * 0.22);
    font-size: var(--crowd-size);
    font-weight: var(--crowd-weight);
    letter-spacing: var(--crowd-track);
    color: var(--crowd-ink);
    opacity: var(--crowd-fade);
    /* Подложка у кадра не плоская: два радиальных градиента поднимают углы до яркости, на которой
       полупрозрачный текст начинает мылиться. Мягкая тень возвращает именам контраст в любом углу. */
    text-shadow: 0 2px 14px rgba(8, 9, 16, 0.55);
    animation: quiz-tv-crowd-in 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
}

/* Шесть ступеней кегля вместо четырёх: четыре читаются как четыре разряда списка, шесть — как фактура.
   Ступень выбирается по самому имени (BuildCrowdNameClass), поэтому у человека она не прыгает от
   обновления к обновлению. Прозрачность и трекинг идут вместе с кеглем: мелкие имена отступают
   в глубину и слегка разряжаются, крупные стоят плотно и впереди. */
.quiz-tv__crowd-name--s1 {
    --crowd-size: 30px;
    --crowd-weight: 500;
    --crowd-fade: 0.62;
    --crowd-track: 0.02em;
}

.quiz-tv__crowd-name--s2 {
    --crowd-size: 38px;
    --crowd-weight: 500;
    --crowd-fade: 0.72;
    --crowd-track: 0.01em;
}

.quiz-tv__crowd-name--s3 {
    --crowd-size: 48px;
    --crowd-weight: 600;
    --crowd-fade: 0.82;
}

.quiz-tv__crowd-name--s4 {
    --crowd-size: 58px;
    --crowd-weight: 700;
    --crowd-fade: 0.9;
    --crowd-track: -0.005em;
}

.quiz-tv__crowd-name--s5 {
    --crowd-size: 70px;
    --crowd-weight: 700;
    --crowd-fade: 0.96;
    --crowd-track: -0.01em;
}

.quiz-tv__crowd-name--s6 {
    --crowd-size: 84px;
    --crowd-weight: 800;
    --crowd-fade: 1;
    --crowd-track: -0.015em;
}

/* Шесть оттенков из той же палитры, что и остальные экраны. Половина из них — нейтральные серо-белые,
   и это не экономия: когда все восемьдесят имён цветные, кадр превращается в рябь и перестаёт
   читаться с десяти метров. Акценты взяты светлыми версиями брендовых цветов — насыщенные на тёмном
   фоне теряют штрих буквы после даунскейла в 720p. */
.quiz-tv__crowd-name--t1 {
    --crowd-ink: #ffffff;
}

.quiz-tv__crowd-name--t2 {
    --crowd-ink: #dfe3f2;
}

.quiz-tv__crowd-name--t3 {
    --crowd-ink: #b9c0d8;
}

.quiz-tv__crowd-name--t4 {
    --crowd-ink: #9fe6a3;
}

.quiz-tv__crowd-name--t5 {
    --crowd-ink: #a99cff;
}

.quiz-tv__crowd-name--t6 {
    --crowd-ink: #ffc978;
}

/* Новое имя проявляется, а не возникает: в эфире это единственное движение на экране ожидания,
   и именно оно показывает, что зал набирается прямо сейчас.

   Конечный кадр доводит непрозрачность до --crowd-fade, а не до единицы: анимация с fill-mode: both
   перебивает opacity из правила, и с жёсткой единицей ступенчатая глубина облака схлопнулась бы
   в плоскую после первой же перерисовки. */
@keyframes quiz-tv-crowd-in {
    from { opacity: 0; transform: scale(0.86) translateY(10px); }
    to { opacity: var(--crowd-fade); transform: scale(1) translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
    .quiz-tv__crowd-name {
        animation: none;
    }
}

.quiz-tv__title {
    font-size: 72px;
    font-weight: 800;
    line-height: 1.1;
}

.quiz-tv__rules {
    display: flex;
    flex-direction: column;
    gap: 10px;
    font-size: 32px;
    opacity: 0.8;
}

/* Тот же приподнятый объект, что и карточка вопроса: экран ожидания и экран вопроса должны
   читаться как одна сцена, иначе переход между ними выглядит сменой источника в OBS. */
.quiz-tv__join {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    flex: 0 0 auto;
    padding: 20px 22px;
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 22px;
    background: rgba(23, 25, 38, 0.82);
    box-shadow: 0 40px 80px rgba(0, 0, 0, 0.45);
}

/* 240 пикселей на холсте — это 160 в кадре 720p после даунскейла, запас по модулям для ссылки такой
   длины остаётся приличный. Дальше уменьшать нельзя: начнётся угадывание камерой с третьего раза. */
.quiz-tv__qr {
    width: 180px;
    height: 180px;
    background: #ffffff;
    padding: 10px;
    border-radius: 10px;
}

.quiz-tv__link {
    font-size: 24px;
    letter-spacing: 0.01em;
}

.quiz-tv__question-screen {
    display: flex;
    flex-direction: column;
    gap: 40px;
    height: 100%;
}

/* Три колонки, а не space-between: на вскрытии таймер из строки уходит, и при раскладке по краям
   счётчик ответивших уехал бы в середину кадра. Явная третья колонка держит его на месте всегда.

   Прозрачности на всей строке нет намеренно: таймер лежит внутри и наследовал бы её вместе
   с подписями — приглушать нужно подписи, а не прибор. */
.quiz-tv__meta {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    align-items: center;
    gap: 32px;
    flex: 0 0 auto;
    font-size: 24px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: #a2a7bb;
}

.quiz-tv__answered {
    grid-column: 3;
    justify-self: end;
}

/* Карточка — единственный приподнятый объект в кадре, поэтому тень и рамка тратятся только здесь.
   Самый длинный вопрос набора («Кто из участников текущего Mafia World Championship 2026…») плюс шесть
   вариантов обязаны помещаться сюда без переполнения — это и есть проверочный материал вёрстки. */
.quiz-tv__question {
    flex: 0 0 auto;
    padding: 52px 64px;
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 28px;
    background: rgba(23, 25, 38, 0.82);
    box-shadow: 0 50px 90px rgba(0, 0, 0, 0.45);
    font-size: 58px;
    font-weight: 700;
    line-height: 1.18;
    letter-spacing: -0.01em;
}

/* Жетоны прижаты к нижнему краю: между карточкой и ими остаётся воздух, который и создаёт глубину.
   Число колонок задаёт разметка (BuildOptionsClass) — модификаторы ниже только исполняют решение. */
.quiz-tv__options {
    display: grid;
    gap: 20px;
    margin-top: auto;
    flex: 0 0 auto;
}

.quiz-tv__options--cols1 {
    grid-template-columns: minmax(0, 1fr);
}

.quiz-tv__options--cols2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

.quiz-tv__options--cols3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}

.quiz-tv__options--cols4 {
    grid-template-columns: repeat(4, minmax(0, 1fr));
}

/* Текст переносится, а не обрезается многоточием: имена игроков приезжают из базы и бывают длиннее
   колонки, а потерянная в эфире фамилия — это вопрос, на который зритель не может ответить. */
.quiz-tv__option {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 96px;
    padding: 20px 34px;
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.09);
    font-size: 34px;
    font-weight: 600;
    line-height: 1.15;
    text-align: center;
}

.quiz-tv__option--placeholder {
    border-style: dashed;
    border-color: rgba(160, 148, 255, 0.45);
    background: rgba(124, 108, 255, 0.12);
    font-style: italic;
}

/* Прибор, а не заголовок: в этой сцене крупный отсчёт спорил бы с карточкой вопроса за внимание.
   Пороги (10 и 5 секунд) приходят модификаторами из QuizLiveTimer и здесь только раскрашиваются. */
.quiz-tv__timer {
    justify-self: center;
    padding: 8px 30px;
    border: 2px solid rgba(255, 255, 255, 0.18);
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.06);
    color: #ffffff;
    font-size: 52px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0;
    line-height: 1.1;
}

.quiz-tv__timer--warning {
    border-color: rgba(255, 181, 71, 0.55);
    background: rgba(255, 181, 71, 0.12);
    color: #ffb547;
}

.quiz-tv__timer--danger {
    border-color: rgba(255, 107, 107, 0.65);
    background: rgba(255, 107, 107, 0.14);
    color: #ff6b6b;
}

.quiz-tv__timer--out {
    opacity: 0.45;
}

.quiz-tv__closed {
    flex: 0 0 auto;
    margin-top: 24px;
    font-size: 40px;
    text-align: center;
    color: #a2a7bb;
    letter-spacing: 0.04em;
}

/* ------------------------------------------------------------------ TV: вопрос вскрыт

   Полосы распределения во всю ширину сверху, под ними список лидеров «тройка и хвост»: первые три места
   плашками, остальные — одной строкой в четыре колонки.

   Высоту делит flex, а не проценты: список и шапка занимают столько, сколько занимают, а полосы забирают
   ВЕСЬ остаток и делят его между собой поровну. Поэтому кадр сходится и с пояснением, и без него,
   и с пятью полосами, и с семью — на холсте, который не прокручивается, это единственный способ
   не считать высоты руками под каждый вопрос. */
.quiz-tv__reveal {
    display: flex;
    flex-direction: column;
    gap: 24px;
    flex: 1 1 auto;
    min-height: 0;
}

.quiz-tv__reveal-head {
    display: flex;
    align-items: baseline;
    gap: 32px;
    flex: 0 0 auto;
}

/* Вопрос набран мельче, чем на экране ответа: там он главный объект кадра, здесь — напоминание,
   о чём шла речь. Две строки — потолок: третья уходит из высоты полос, а не из пустого места. */
.quiz-tv__reveal-question {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    flex: 1 1 auto;
    font-size: 42px;
    font-weight: 700;
    line-height: 1.16;
}

.quiz-tv__reveal-stat {
    flex: 0 0 auto;
    font-size: 26px;
    color: #a2a7bb;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.quiz-tv__reveal-answer {
    flex: 0 0 auto;
    font-size: 32px;
    font-weight: 700;
    color: #6ee7a0;
}

/* Подпись-разделитель между зонами кадра: линия дотягивается до правого края сама. */
.quiz-tv__sep {
    display: flex;
    align-items: center;
    gap: 24px;
    flex: 0 0 auto;
    font-size: 20px;
    font-weight: 700;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: #8d92a6;
}

.quiz-tv__sep::after {
    content: "";
    flex: 1 1 auto;
    height: 1px;
    background: rgba(255, 255, 255, 0.12);
}

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

   Жёсткое ограничение в три строки принципиально: холст 1920×1080 не скроллится, а текст приходит
   из админки и длину никто не проверяет. Каждая строка пояснения отнимает высоту у полос, которые
   делят остаток кадра, — без клампа пояснение на пять строк сплющило бы их до нечитаемых сорока
   пикселей. Лучше обрезать хвост фразы, чем полкадра. Browser Source — Chromium, -webkit-line-clamp там есть. */
.quiz-tv__explanation {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    flex: 0 0 auto;
    max-width: 1500px;
    font-size: 28px;
    line-height: 1.35;
    color: #c5c9d6;
    border-left: 4px solid rgba(110, 231, 160, 0.5);
    padding-left: 22px;
}

/* ---- полосы распределения на TV: заливка уходит ПОД текст, а не под него отдельной дорожкой ----

   Разметка QuizLiveBuckets общая с телефоном, где подпись стоит над тонкой дорожкой. Здесь дорожка
   растягивается на всю плашку абсолютом и становится фоном строки, а подпись ложится поверх.
   Так один компонент даёт два разных кадра без параметра «я на телевизоре». */
.quiz-tv__reveal .quiz-live-buckets {
    flex: 1 1 auto;
    gap: 10px;
    min-height: 0;
}

.quiz-tv__reveal .quiz-live-bucket {
    position: relative;
    display: flex;
    align-items: center;
    flex: 1 1 0;
    min-height: 0;
    padding: 0 30px;
    border-radius: 14px;
    background: rgba(255, 255, 255, 0.05);
    overflow: hidden;
}

.quiz-tv__reveal .quiz-live-bucket__track {
    position: absolute;
    inset: 0;
    height: auto;
    border-radius: 0;
    background: none;
}

.quiz-tv__reveal .quiz-live-bucket__fill {
    background: rgba(255, 255, 255, 0.12);
}

.quiz-tv__reveal .quiz-live-bucket__head {
    position: relative;
    flex: 1 1 auto;
    align-items: baseline;
    justify-content: flex-start;
    gap: 20px;
    font-size: 32px;
}

.quiz-tv__reveal .quiz-live-bucket__label {
    flex: 1 1 auto;
    min-width: 0;
    font-weight: 600;
}

.quiz-tv__reveal .quiz-live-bucket__share {
    flex: 0 0 auto;
    font-size: 26px;
    color: #a2a7bb;
    font-variant-numeric: tabular-nums;
}

.quiz-tv__reveal .quiz-live-bucket__count {
    flex: 0 0 auto;
    width: 130px;
    text-align: right;
    opacity: 1;
}

.quiz-tv__reveal .quiz-live-bucket--correct {
    background: rgba(110, 231, 160, 0.14);
}

.quiz-tv__reveal .quiz-live-bucket--correct .quiz-live-bucket__fill {
    background: rgba(110, 231, 160, 0.34);
}

.quiz-tv__reveal .quiz-live-bucket--correct .quiz-live-bucket__label,
.quiz-tv__reveal .quiz-live-bucket--correct .quiz-live-bucket__count {
    color: #eafff1;
    font-weight: 800;
}

.quiz-tv__reveal .quiz-live-bucket--correct .quiz-live-bucket__share {
    color: #b6f0cd;
}

/* ---- список лидеров на TV ----

   Базовые размеры компонента заданы в rem, то есть от корня документа, а не от 28px холста:
   на 1920×1080 таблица приезжала бы четырнадцатым кеглем. Здесь она возвращается к масштабу кадра —
   и на вскрытии, и на итоговом экране. */
.quiz-tv .quiz-live-board {
    gap: 8px;
}

.quiz-tv .quiz-live-board__row {
    gap: 18px;
    padding: 10px 20px;
    border-radius: 14px;
    font-size: 30px;
}

.quiz-tv .quiz-live-board__place {
    min-width: 44px;
    font-variant-numeric: tabular-nums;
}

.quiz-tv .quiz-live-board__avatar {
    width: 56px;
    height: 56px;
}

.quiz-tv .quiz-live-board__accuracy {
    flex: 0 0 auto;
    font-size: 24px;
    color: #a2a7bb;
    font-variant-numeric: tabular-nums;
}

.quiz-tv .quiz-live-board__score {
    color: #ffb23f;
    font-weight: 800;
}

.quiz-tv .quiz-live-board__empty {
    font-size: 30px;
}

/* «Тройка и хвост»: первые три места — плашки во всю ширину, места с четвёртого по десятое идут
   одной строкой в четыре колонки. Раскладка держится на том, что --top достаётся ровно трём первым
   строкам, а сетка сама разливает остаток по колонкам: сколько бы мест ни приехало, хвост не порвётся. */
.quiz-tv__reveal .quiz-live-board {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 8px 40px;
    flex: 0 0 auto;
    align-content: start;
    margin: 0;
}

.quiz-tv__reveal .quiz-live-board__row--top {
    grid-column: 1 / -1;
    border: 1px solid rgba(255, 255, 255, 0.1);
    background: rgba(255, 255, 255, 0.06);
    padding: 10px 28px;
    font-size: 38px;
    font-weight: 600;
}

.quiz-tv__reveal .quiz-live-board__row--top .quiz-live-board__avatar {
    width: 60px;
    height: 60px;
}

.quiz-tv__reveal .quiz-live-board__row--top .quiz-live-board__score {
    width: 150px;
    text-align: right;
}

.quiz-tv__reveal .quiz-live-board__row--top1 {
    border-color: rgba(255, 178, 63, 0.5);
    background: rgba(255, 178, 63, 0.1);
}

.quiz-tv__reveal .quiz-live-board__row--top1 .quiz-live-board__place {
    color: #ffb23f;
    opacity: 1;
}

.quiz-tv__reveal .quiz-live-board__row:not(.quiz-live-board__row--top) {
    gap: 12px;
    padding: 0;
    background: none;
    font-size: 25px;
    color: #c5c9d6;
}

.quiz-tv__reveal .quiz-live-board__row:not(.quiz-live-board__row--top) .quiz-live-board__place {
    min-width: 32px;
    font-size: 21px;
}

/* В хвосте остаются только место, имя и очки: аватар в 25-м кегле превращается в цветную точку,
   а точность без подписи читается как второй счёт. */
.quiz-tv__reveal .quiz-live-board__row:not(.quiz-live-board__row--top) .quiz-live-board__avatar,
.quiz-tv__reveal .quiz-live-board__row:not(.quiz-live-board__row--top) .quiz-live-board__accuracy {
    display: none;
}

/* Неброский индикатор связи: крупный баннер «ошибка» в эфире хуже застывшей картинки,
   но замереть совсем молча тоже нельзя — оператор должен понять, что источник надо перезагрузить. */
.quiz-tv__pulse {
    position: absolute;
    right: 18px;
    bottom: 18px;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: rgba(125, 220, 130, 0.55);
}

.quiz-tv__pulse--offline {
    background: #ff6b6b;
    animation: quiz-tv-pulse 1.2s ease-in-out infinite;
}

@keyframes quiz-tv-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.25; }
}
