/* Площадка мероприятий — оформление.
 *
 * Светлая тема. Одна таблица стилей на все экраны: лендинг, вход, консоль,
 * среда, зал. Общий набор переменных и компонентов вместо похожих наборов,
 * разъезжающихся при первой правке.
 *
 * Движение здесь несёт смысл, а не украшает: элементы появляются снизу с
 * лёгким приближением, потому что так видно, ЧТО именно появилось, и глаз не
 * ищет изменение заново. Пружинная кривая (--ease-spring) на всём — от неё
 * интерфейс ощущается отзывчивым даже там, где ничего не грузится.
 *
 * Сцена зала остаётся тёмной: видео на белом режет глаз, и внимание уходит с
 * говорящего на рамку вокруг.
 */

:root {
    /* Светлая палитра. Фон не чисто белый: на нём карточки читаются как
       поверхности, а не как дыры. */
    --bg:        #f6f7fb;
    --surface:   #ffffff;
    --surface-2: #f2f4f9;
    --line:      #e4e8f0;
    --line-2:    #d3d9e6;

    --text:      #14181f;
    --text-dim:  #5a6376;
    --text-mute: #8b93a5;

    --brand:     #4361ee;
    --brand-2:   #7048e8;
    --brand-soft: #eef1fe;
    --ok:        #12996b;
    --warn:      #b7791f;
    --bad:       #d92d4b;

    --r-sm: 10px;
    --r:    16px;
    --r-lg: 24px;

    --shadow-1: 0 1px 2px rgba(20, 24, 31, .04), 0 2px 8px rgba(20, 24, 31, .04);
    --shadow-2: 0 2px 4px rgba(20, 24, 31, .04), 0 12px 32px rgba(20, 24, 31, .08);
    --shadow-3: 0 8px 16px rgba(20, 24, 31, .06), 0 24px 64px rgba(20, 24, 31, .12);

    /* Пружина, а не линейка: движение начинается быстро и мягко тормозит. */
    --ease-spring: cubic-bezier(.22, 1, .36, 1);
    --ease-out:    cubic-bezier(.16, 1, .3, 1);
    --t-fast: .16s;
    --t:      .28s;
    --t-slow: .5s;

    --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
            "Helvetica Neue", Arial, sans-serif;
}

* { box-sizing: border-box; }

/* Атрибут hidden обязан побеждать раскладку: правило с классом
   (.ev-room{display:flex}) специфичнее браузерного и его перебивает — на
   телефоне из-за этого экран входа и зал показывались одновременно. */
[hidden] { display: none !important; }

html, body { height: 100%; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font: 15px/1.6 var(--font);
    -webkit-font-smoothing: antialiased;
    overflow-x: hidden;
}

/* ── Живой фон ────────────────────────────────────────────────────────────────
 *
 * Три размытых пятна медленно плывут за содержимым. Всё на трансформациях,
 * поэтому анимация идёт на видеокарте и не трогает раскладку. Никакой
 * разметки под это не нужно — фон висит на самом body.
 */

/* Живой фон рисуется на canvas (static/js/event-fx.js): CSS-пятна на
   большом экране почти не читались, а на canvas цвета реально перетекают.
   Слой лежит под содержимым и не ловит нажатия. */
.fx-bg {
    position: fixed;
    inset: 0;
    z-index: -2;
    pointer-events: none;
    opacity: .85;
}

/* Зерно поверх фона: убирает пластиковую гладкость градиентов и даёт
   ощущение материала. Рисуется одним SVG, файлов не тянет. */
body::after {
    content: "";
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    opacity: .035;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* Человек мог попросить систему не анимировать — уважаем. */
@media (prefers-reduced-motion: reduce) {
    body::before, body::after { animation: none; }
    *, *::before, *::after {
        animation-duration: .01ms !important;
        transition-duration: .01ms !important;
    }
}

a { color: var(--brand); text-decoration: none; transition: color var(--t-fast); }
a:hover { color: var(--brand-2); }

h1, h2, h3 { margin: 0; font-weight: 680; letter-spacing: -.02em; }
h1 { font-size: 30px; line-height: 1.15; }
h2 { font-size: 20px; }
h3 { font-size: 16px; }

.ev-dim  { color: var(--text-dim); }
.ev-mute { color: var(--text-mute); font-size: 13px; }

/* ── Появление ────────────────────────────────────────────────────────────────
 *
 * Анимация на самом элементе, а не по классу: список залов рисуется
 * заново после каждой правки, и новые плитки въезжают сами, без единой
 * строчки в обработчиках.
 */

@keyframes rise {
    from { opacity: 0; transform: translate3d(0, 10px, 0) scale(.985); }
    to   { opacity: 1; transform: none; }
}

.card, .panel, .tile, .empty, .app__top {
    animation: rise var(--t-slow) var(--ease-spring) both;
}

/* Лесенкой: элементы списка появляются один за другим, и взгляд успевает
   пройти по ним сверху вниз. */
.grid > *:nth-child(1) { animation-delay: .02s; }
.grid > *:nth-child(2) { animation-delay: .06s; }
.grid > *:nth-child(3) { animation-delay: .10s; }
.grid > *:nth-child(4) { animation-delay: .14s; }
.grid > *:nth-child(5) { animation-delay: .18s; }
.grid > *:nth-child(n+6) { animation-delay: .22s; }

/* ── Кнопки ───────────────────────────────────────────────────────────────── */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 11px 18px;
    background: var(--surface);
    border: 1px solid var(--line-2);
    border-radius: var(--r-sm);
    color: var(--text);
    font: 550 14px/1 var(--font);
    cursor: pointer;
    white-space: nowrap;
    box-shadow: var(--shadow-1);
    transition: transform var(--t) var(--ease-spring),
                box-shadow var(--t) var(--ease-spring),
                background var(--t-fast), border-color var(--t-fast);
}

.btn:hover { transform: translateY(-1px); box-shadow: var(--shadow-2); text-decoration: none; }
/* Нажатие отзывается сразу: без этого кнопка кажется неживой на телефоне. */
.btn:active { transform: translateY(0) scale(.98); box-shadow: var(--shadow-1); }
.btn:disabled { opacity: .5; cursor: default; transform: none; box-shadow: none; }

.btn--primary {
    background: linear-gradient(135deg, var(--brand), var(--brand-2));
    border-color: transparent;
    color: #fff;
    box-shadow: 0 2px 6px rgba(67, 97, 238, .28), 0 8px 24px rgba(67, 97, 238, .18);
}
.btn--primary:hover { box-shadow: 0 4px 12px rgba(67, 97, 238, .34), 0 14px 36px rgba(67, 97, 238, .24); }

.btn--ghost { background: transparent; border-color: transparent; box-shadow: none; color: var(--text-dim); }
.btn--ghost:hover { background: var(--surface-2); box-shadow: none; }
.btn--danger { background: #fff1f3; border-color: #f7c3cd; color: var(--bad); }
.btn--wide { width: 100%; }
.btn--sm { padding: 8px 13px; font-size: 13px; }
.btn.is-on { border-color: var(--brand); background: var(--brand-soft); color: var(--brand); }
.btn.is-off { opacity: .5; }

/* ── Поля ─────────────────────────────────────────────────────────────────── */

.field { margin-bottom: 16px; }
.field > label, label.field-label {
    display: block;
    margin-bottom: 7px;
    color: var(--text-dim);
    font-size: 13px;
    font-weight: 550;
}

input[type="text"], input[type="email"], input[type="password"],
input[type="tel"], select, textarea {
    width: 100%;
    padding: 12px 14px;
    background: var(--surface);
    border: 1px solid var(--line-2);
    border-radius: var(--r-sm);
    color: var(--text);
    font: 15px/1.4 var(--font);
    transition: border-color var(--t-fast), box-shadow var(--t-fast);
}

input:focus, select:focus, textarea:focus {
    outline: none;
    border-color: var(--brand);
    box-shadow: 0 0 0 4px rgba(67, 97, 238, .12);
}

input::placeholder, textarea::placeholder { color: var(--text-mute); }
textarea { resize: vertical; min-height: 80px; }

.check {
    display: flex;
    gap: 10px;
    align-items: flex-start;
    margin: 16px 0;
    font-size: 14px;
    line-height: 1.5;
    cursor: pointer;
}
.check input { margin: 3px 0 0; flex: 0 0 auto; width: 17px; height: 17px; accent-color: var(--brand); }

.row { display: flex; gap: 14px; }
.row > * { flex: 1; min-width: 0; }

.msg { margin-top: 10px; font-size: 13px; min-height: 18px; transition: color var(--t-fast); }
.msg.ok  { color: var(--ok); }
.msg.bad { color: var(--bad); }

/* ── Карточка-экран ───────────────────────────────────────────────────────── */

.card {
    width: 100%;
    max-width: 440px;
    margin: 0 auto;
    padding: 36px;
    background: rgba(255, 255, 255, .82);
    backdrop-filter: blur(20px) saturate(1.4);
    -webkit-backdrop-filter: blur(20px) saturate(1.4);
    border: 1px solid rgba(255, 255, 255, .9);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-3);
}

.card--wide { max-width: 580px; }
.card__head { margin-bottom: 26px; }
.card__head p { margin: 8px 0 0; color: var(--text-dim); font-size: 15px; }

.screen {
    min-height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 40px 18px;
}

/* ── Оболочка приложения ──────────────────────────────────────────────────── */

.app { min-height: 100vh; display: flex; flex-direction: column; }

.app__top {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px 26px;
    background: rgba(255, 255, 255, .72);
    backdrop-filter: blur(18px) saturate(1.4);
    -webkit-backdrop-filter: blur(18px) saturate(1.4);
    border-bottom: 1px solid var(--line);
    position: sticky;
    top: 0;
    z-index: 20;
}

.app__brand { font-weight: 680; letter-spacing: -.02em; font-size: 16px; }
.app__who { margin-left: auto; color: var(--text-dim); font-size: 13px; }
.app__body { flex: 1; width: 100%; max-width: 1080px; margin: 0 auto; padding: 32px 24px 72px; }

.section { margin-bottom: 40px; }
.section__head { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
.section__head h2 { margin-right: auto; }

.panel {
    padding: 22px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r);
    box-shadow: var(--shadow-1);
}

.panel + .panel { margin-top: 14px; }
.panel h3 { letter-spacing: -.01em; }

.grid { display: grid; gap: 14px; }
@media (min-width: 760px) { .grid--2 { grid-template-columns: 1fr 1fr; } }

/* ── Плитка сущности ──────────────────────────────────────────────────────── */

.tile {
    padding: 20px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r);
    box-shadow: var(--shadow-1);
    transition: transform var(--t) var(--ease-spring),
                box-shadow var(--t) var(--ease-spring),
                border-color var(--t-fast);
}

.tile:hover { transform: translateY(-2px); box-shadow: var(--shadow-2); border-color: var(--line-2); }
.tile__head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 5px; }
.tile__head h3 { margin-right: auto; }
.tile__meta { color: var(--text-mute); font-size: 13px; margin-bottom: 16px; }
.tile__actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 16px; }

.pill {
    display: inline-block;
    padding: 4px 11px;
    background: var(--surface-2);
    border: 1px solid var(--line);
    border-radius: 20px;
    font-size: 12px;
    font-weight: 550;
    color: var(--text-dim);
    white-space: nowrap;
}

.pill--live { background: #e8f8f1; border-color: #bfe8d6; color: var(--ok); }
.pill--off  { background: #fdeef1; border-color: #f7ccd5; color: var(--bad); }

.empty {
    padding: 40px 24px;
    text-align: center;
    color: var(--text-mute);
    background: rgba(255, 255, 255, .6);
    border: 1px dashed var(--line-2);
    border-radius: var(--r);
    font-size: 14px;
}

/* ── Ссылка для копирования ───────────────────────────────────────────────── */

.link { margin-bottom: 12px; }
.link > span { display: block; margin-bottom: 6px; color: var(--text-mute); font-size: 12px; font-weight: 550; }
.link__box { display: flex; gap: 8px; }
.link__box input {
    flex: 1;
    min-width: 0;
    padding: 10px 13px;
    background: var(--surface-2);
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    color: var(--text-dim);
    font-size: 13px;
    cursor: pointer;
    transition: background var(--t-fast), border-color var(--t-fast);
}
.link__box input:hover { background: var(--brand-soft); border-color: var(--brand); color: var(--text); }

/* ── Таблица доступа ──────────────────────────────────────────────────────── */

.access { width: 100%; border-collapse: collapse; font-size: 14px; }
.access th {
    padding: 12px 10px;
    text-align: left;
    color: var(--text-mute);
    font-size: 12px;
    font-weight: 600;
    border-bottom: 1px solid var(--line);
    white-space: nowrap;
}
.access th.rot { text-align: center; }
.access td { padding: 13px 10px; border-bottom: 1px solid var(--line); vertical-align: middle; }
.access td.mid { text-align: center; }
.access tr { transition: background var(--t-fast); }
.access tbody tr:hover { background: var(--surface-2); }
.access tr:last-child td { border-bottom: 0; }
.access input[type="checkbox"] { width: 18px; height: 18px; cursor: pointer; accent-color: var(--brand); }
.access__name { font-weight: 600; }
.access__sub { color: var(--text-mute); font-size: 12px; }

/* ── Зал: сцена остаётся тёмной ───────────────────────────────────────────── */

.ev-room { display: flex; flex-direction: column; height: 100vh; background: #0f1116; }
/* В зале живой фон отключаем: сцена занимает весь экран, и подсветка за ней
   только жжёт батарею. */
body:has(.ev-room:not([hidden])) .fx-bg { display: none; }

.ev-head {
    display: flex; align-items: center; gap: 14px;
    padding: 13px 20px;
    background: rgba(255, 255, 255, .06);
    border-bottom: 1px solid rgba(255, 255, 255, .08);
    color: #eef1f7;
}

.ev-head__title { font-weight: 620; }
.ev-head__role { color: #9aa3b5; font-size: 13px; }
.ev-diag { margin-left: auto; font-size: 13px; color: #9aa3b5; }
.ev-diag.ok  { color: #4ad38f; }
.ev-diag.bad { color: #ff7d92; }

.ev-stage { display: flex; flex: 1; gap: 12px; padding: 12px; min-height: 0; }
.ev-main {
    flex: 1; position: relative;
    background: #000; border-radius: var(--r); overflow: hidden;
    display: flex; align-items: center; justify-content: center;
}
.ev-side { width: 224px; display: flex; flex-direction: column; gap: 10px; overflow-y: auto; }
.ev-empty { color: #6b7488; font-size: 14px; }

.tile-v {
    position: relative; background: #000;
    border-radius: 12px; overflow: hidden;
    animation: rise var(--t) var(--ease-spring) both;
}
.ev-main .tile-v { width: 100%; height: 100%; }
.ev-side .tile-v { height: 134px; flex: 0 0 auto; }
.tile-v__video, .tile-v__video video {
    width: 100%; height: 100%; object-fit: cover; display: block;
}
/* Видео обязано рисоваться ПОВЕРХ аватара: аватар лежит абсолютом, а такой
   элемент перекрывает обычный блок независимо от порядка в разметке — без
   этого включённая камера пряталась за портретом. */
.tile-v__video { position: relative; z-index: 1; }
.tile-v__name {
    position: absolute; left: 9px; bottom: 8px; z-index: 2;
    padding: 4px 9px;
    background: rgba(0, 0, 0, .55);
    backdrop-filter: blur(8px);
    border-radius: 7px;
    font-size: 12px; color: #fff;
}

.ev-bar {
    display: flex; align-items: center; gap: 10px;
    padding: 12px 18px;
    background: rgba(12, 14, 20, .72);
    border-top: 1px solid rgba(255, 255, 255, .08);
    flex-wrap: wrap;
}
.ev-bar__group { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* Разделитель между группами: одиннадцать одинаковых таблеток подряд
   читаются как список, в котором нужное ищут заново каждый раз. */
.ev-bar__sep {
    width: 1px; height: 26px; flex: 0 0 auto;
    background: rgba(255, 255, 255, .12);
}
.ev-bar__count { margin-left: auto; color: #7b8496; font-size: 13px; white-space: nowrap; }

/* Кнопка зала: значок и подпись. Значок опознаётся боковым зрением, пока
   человек смотрит на собеседника, подпись снимает догадки. */
.ctl {
    display: inline-flex; align-items: center; gap: 8px;
    height: 40px; padding: 0 14px;
    font: inherit; font-size: 13.5px; font-weight: 500; line-height: 1;
    color: #e7ebf3;
    background: rgba(255, 255, 255, .07);
    border: 1px solid rgba(255, 255, 255, .1);
    border-radius: 12px;
    cursor: pointer;
    transition: background var(--t-fast), border-color var(--t-fast),
                transform var(--t-fast), color var(--t-fast), box-shadow var(--t-fast);
}
.ctl:hover { background: rgba(255, 255, 255, .13); border-color: rgba(255, 255, 255, .2); }
.ctl:active { transform: scale(.97); }
.ctl:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.ctl[disabled] { opacity: .5; cursor: default; }
.ctl__i { width: 19px; height: 19px; flex: 0 0 auto; display: block; }
.ctl__i svg { width: 100%; height: 100%; display: block; }
.ctl__t { white-space: nowrap; }

/* Перечёркнутый значок появляется ровно тогда, когда устройство выключено:
   надпись «Микрофон» одинакова в обоих состояниях, а линия — нет. */
.ctl__slash { opacity: 0; transition: opacity var(--t-fast); }
.ctl.is-off .ctl__slash { opacity: 1; }
.ctl.is-off {
    color: #ffb3c0;
    background: rgba(217, 45, 75, .16);
    border-color: rgba(217, 45, 75, .34);
}
.ctl.is-off:hover { background: rgba(217, 45, 75, .24); }

/* Включённое состояние: экран, поднятая рука, открытая панель. */
.ctl.is-on {
    color: #0c1018;
    background: var(--brand);
    border-color: transparent;
    box-shadow: 0 8px 20px -10px var(--brand);
}
.ctl.is-on:hover { background: var(--brand); filter: brightness(1.06); }

/* Запись идёт — красная и пульсирующая: в кадре люди, и это должно быть
   видно с другого конца комнаты. */
.ctl--rec.is-on {
    color: #fff; background: #d92d4b; box-shadow: 0 8px 20px -10px #d92d4b;
    animation: recPulse 2s var(--ease-out) infinite;
}
@keyframes recPulse {
    0%, 100% { box-shadow: 0 8px 20px -10px #d92d4b; }
    50%      { box-shadow: 0 8px 26px -6px rgba(217, 45, 75, .8); }
}
@media (prefers-reduced-motion: reduce) { .ctl--rec.is-on { animation: none; } }

/* Реакции — тот же ряд, но тише: это отклик, а не управление залом. */
.ctl--react {
    background: transparent; border-color: rgba(255, 255, 255, .14);
    color: #b9c2d2; font-weight: 450;
}
.ctl--react:hover { color: #fff; background: rgba(255, 255, 255, .1); }
.ctl--react:active { transform: scale(.94); }

/* Когда ряд перестаёт помещаться, первыми теряют подписи реакции: их три,
   они рядом, и значок «палец вверх» ни с чем не путается. Переносить панель
   на вторую строку хуже — она съедает высоту сцены. */
@media (max-width: 1340px) {
    .ctl--react { padding: 0 11px; }
    .ctl--react .ctl__t { display: none; }
}
@media (max-width: 1240px) {
    .ev-bar { gap: 7px; padding: 10px 12px; }
    .ctl { height: 38px; padding: 0 11px; gap: 7px; font-size: 13px; }
    .ev-bar__count { font-size: 12px; }
}
@media (max-width: 720px) {
    /* На телефоне подписи остаются только у того, что решают на ходу:
       микрофон, камера и чат. Остальное узнаётся значком. */
    #screen .ctl__t, #hand .ctl__t, #people-open .ctl__t,
    #art-open .ctl__t, #rec .ctl__t { display: none; }
}

.dot {
    display: inline-block; width: 7px; height: 7px; margin-left: 6px;
    border-radius: 50%; background: #6f8cff; vertical-align: middle;
    animation: pulse 1.8s var(--ease-out) infinite;
}
@keyframes pulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50%      { opacity: .45; transform: scale(.8); }
}

/* Боковые панели зала. Одно место в углу — держим взаимоисключающими:
   верхняя перехватывает нажатия нижней, и «Отправить» не срабатывает вовсе. */
.dock {
    position: fixed; right: 16px; bottom: 82px;
    width: 340px; max-height: 58vh;
    display: flex; flex-direction: column;
    padding: 18px;
    background: rgba(24, 27, 35, .92);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border: 1px solid rgba(255, 255, 255, .1);
    border-radius: var(--r);
    box-shadow: 0 20px 60px rgba(0, 0, 0, .5);
    color: #eef1f7;
    z-index: 30;
    animation: rise var(--t) var(--ease-spring) both;
}

.dock--top { top: 74px; bottom: auto; max-height: 40vh; overflow-y: auto; }
.dock h2 { margin: 0 0 14px; font-size: 15px; display: flex; align-items: center; color: #eef1f7; }
.dock__x {
    margin-left: auto; background: none; border: 0;
    color: #6b7488; font-size: 20px; line-height: 1; cursor: pointer;
    transition: color var(--t-fast);
}
.dock__x:hover { color: #eef1f7; }
.dock input { background: rgba(255, 255, 255, .07); border-color: rgba(255, 255, 255, .14); color: #eef1f7; }
.dock input::placeholder { color: #6b7488; }
.dock .btn { box-shadow: none; }

.chat__lines {
    flex: 1; overflow-y: auto; margin: 0 -4px 12px; padding: 0 4px;
    display: flex; flex-direction: column; gap: 8px;
    scrollbar-width: thin; scrollbar-color: rgba(255, 255, 255, .18) transparent;
}
.chat__lines::-webkit-scrollbar { width: 6px; }
.chat__lines::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, .16); border-radius: 3px;
}
.chat__empty {
    margin: auto 0; padding: 18px 4px; text-align: center;
    color: #6b7488; font-size: 13px; line-height: 1.5;
}

/* Реплика — облаком, а не строкой: в строках чужое и своё различаются только
   жирным именем, и на телефоне разговор читается как один абзац. */
.chat__line {
    max-width: 86%; align-self: flex-start;
    padding: 9px 12px;
    background: rgba(255, 255, 255, .07);
    border: 1px solid rgba(255, 255, 255, .07);
    border-radius: 14px 14px 14px 5px;
    font-size: 14px; line-height: 1.45; color: #e7ebf3;
    word-break: break-word;
    animation: rise .24s var(--ease-spring) both;
}
.chat__line b {
    display: block; margin-bottom: 3px;
    color: #93aaff; font-size: 12px; font-weight: 600; letter-spacing: .01em;
}
.chat__line--own {
    align-self: flex-end;
    background: rgba(111, 140, 255, .18);
    border-color: rgba(111, 140, 255, .3);
    border-radius: 14px 14px 5px 14px;
}
.chat__line--own b { color: #b9c6ff; }
/* Вопрос ведущему видно отдельно: в вебинаре их поток надо разбирать. */
.chat__line.q { border-left: 2px solid #6f8cff; }
.chat__line.sys {
    align-self: center; max-width: 100%;
    background: none; border: 0; padding: 2px 0;
    color: #6b7488; font-size: 12.5px; font-style: normal; text-align: center;
}
.chat__line.sys b { display: none; }

.chat__send { display: flex; gap: 8px; align-items: center; }
.chat__send input {
    flex: 1; min-width: 0; padding: 11px 14px; font-size: 14px; border-radius: 12px;
}
/* Круглая кнопка со стрелкой: подпись «Отправить» занимала треть панели и
   повторяла то, что уже говорит поле ввода. */
.chat__go {
    width: 40px; height: 40px; flex: 0 0 auto;
    display: inline-flex; align-items: center; justify-content: center;
    border: 0; border-radius: 12px; cursor: pointer;
    background: var(--brand); color: #0c1018;
    transition: transform var(--t-fast), filter var(--t-fast);
}
.chat__go svg { width: 19px; height: 19px; }
.chat__go:hover { filter: brightness(1.08); }
.chat__go:active { transform: scale(.94); }
.chat__go:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

.person {
    display: flex; align-items: center; gap: 10px;
    padding: 9px 0;
    border-bottom: 1px solid rgba(255, 255, 255, .08);
    font-size: 14px;
}
.person:last-child { border-bottom: 0; }
.person i { color: #6b7488; font-size: 12px; font-style: normal; }
.person .btn { margin-left: auto; background: rgba(255, 255, 255, .09); border-color: rgba(255, 255, 255, .14); color: #eef1f7; }

/* ── Кабинет ──────────────────────────────────────────────────────────────── */

.cab { display: flex; gap: 32px; align-items: flex-start; }
.cab__photo { width: 170px; flex: 0 0 auto; text-align: center; }
.cab__fields { flex: 1; min-width: 0; }

.ava {
    width: 148px; height: 148px; margin: 0 auto 14px;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--brand-soft), #f3ecff) center/cover no-repeat;
    border: 1px solid var(--line);
    display: flex; align-items: center; justify-content: center;
    font-size: 50px; font-weight: 620;
    color: var(--brand);
    box-shadow: var(--shadow-1);
    transition: transform var(--t) var(--ease-spring);
}
.ava:hover { transform: scale(1.03); }
.ava.has-photo { color: transparent; }

.filepick span {
    display: inline-block; padding: 9px 15px;
    /* Цвет текста задан явно: на тёмной теме мероприятия страница делает
       текст белым, и подпись пропадала на светлой кнопке. */
    background: var(--surface); color: var(--text); border: 1px solid var(--line-2);
    border-radius: var(--r-sm); font-size: 13px; font-weight: 550; cursor: pointer;
    box-shadow: var(--shadow-1);
    transition: transform var(--t) var(--ease-spring), box-shadow var(--t) var(--ease-spring);
}
.filepick span:hover { transform: translateY(-1px); box-shadow: var(--shadow-2); }

/* ── Телефон ──────────────────────────────────────────────────────────────── */

@media (max-width: 760px) {
    h1 { font-size: 25px; }
    .app__body { padding: 22px 16px 56px; }
    .app__top { padding: 12px 16px; }
    .screen { padding: 0; align-items: stretch; }
    .card { max-width: none; min-height: 100vh; border: 0; border-radius: 0; padding: 28px 20px; backdrop-filter: none; background: var(--surface); }
    .row { flex-direction: column; gap: 0; }
    .cab { flex-direction: column; }
    .cab__photo { width: 100%; }
    .ev-stage { flex-direction: column; }
    .ev-side { width: 100%; flex-direction: row; height: 100px; }
    .ev-side .tile-v { height: 100px; width: 140px; }
    .dock { left: 16px; right: 16px; width: auto; }
    .access { font-size: 13px; }
    .access th, .access td { padding: 10px 6px; }
    /* Липкая шапка с размытием — самая дорогая вещь при прокрутке: браузер
       пересчитывает размытие подложки на каждый кадр. На телефоне меняем на
       плотный фон, разница видна только в спокойном состоянии. */
    .app__top { backdrop-filter: none; -webkit-backdrop-filter: none;
                background: rgba(255, 255, 255, .96); }
    /* Зерно — ещё один слой во всю высоту поверх содержимого. На плотном
       экране телефона его не читают, а прокрутке оно стоит кадров. */
    body::after { display: none; }
    /* Фон растягиваем из уменьшенного буфера, поэтому просим сглаживание:
       иначе на границах пятен видны ступени. */
    .fx-bg { opacity: .8; }
}

/* Смена экрана консоли: содержимое въезжает сбоку, а не подменяется рывком.
   Направление вправо-влево читается как «шаг вглубь». */
@keyframes screen-in {
    from { opacity: 0; transform: translate3d(14px, 0, 0); }
    to   { opacity: 1; transform: none; }
}

.screen-in { animation: screen-in var(--t) var(--ease-spring) both; }

/* ── Изюм ─────────────────────────────────────────────────────────────────── */

/* Градиентный заголовок: одна деталь, по которой продукт узнаётся. Ставим
   только на главные заголовки экранов, иначе приём стирается. */
.card__head h1,
.hero h1 {
    background: linear-gradient(120deg, #1a1f2b 0%, var(--brand) 55%, var(--brand-2) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

/* Свет за курсором. Координаты приходят из event-fx.js в переменных,
   рисование целиком здесь — так подсветка не дёргает раскладку. */
.tile, .panel, .card { position: relative; overflow: hidden; }

.tile::before, .panel::before, .card::before {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    opacity: 0;
    transition: opacity var(--t) var(--ease-out);
    background: radial-gradient(320px circle at var(--mx, 50%) var(--my, 50%),
                rgba(67, 97, 238, .10), transparent 65%);
}

.tile:hover::before, .panel:hover::before, .card:hover::before { opacity: 1; }

/* Градиентный кант на наведении — тонкая рамка из двух цветов, собранная
   маской. Обычная граница так не умеет. */
.tile::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    padding: 1px;
    background: linear-gradient(135deg, var(--brand), var(--brand-2), #ff9ecd);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    mask-composite: exclude;
    opacity: 0;
    transition: opacity var(--t) var(--ease-out);
    pointer-events: none;
}

.tile:hover::after { opacity: .55; }

/* Ссылка мигает при копировании: организатор копирует их десятками, и без
   отклика непонятно, сработало ли. */
.link__box input.is-copied {
    background: #e9f7f0;
    border-color: #9ad9bd;
    color: var(--ok);
}

.toast {
    position: fixed;
    left: 50%;
    bottom: 32px;
    transform: translate(-50%, 20px);
    padding: 12px 20px;
    background: rgba(20, 24, 31, .92);
    backdrop-filter: blur(14px);
    color: #fff;
    border-radius: 999px;
    font-size: 14px;
    font-weight: 550;
    box-shadow: var(--shadow-3);
    opacity: 0;
    pointer-events: none;
    z-index: 100;
    transition: opacity var(--t) var(--ease-spring), transform var(--t) var(--ease-spring);
}

.toast.is-on { opacity: 1; transform: translate(-50%, 0); }

/* Первый экран лендинга: крупная типографика вместо карточки-коробки. */
.hero { max-width: 620px; margin: 0 auto; text-align: center; padding: 8vh 20px 6vh; }
.hero h1 { font-size: clamp(34px, 6vw, 56px); line-height: 1.05; margin-bottom: 18px; }
.hero__sub { font-size: clamp(16px, 2.2vw, 19px); color: var(--text-dim); margin: 0 auto 32px; max-width: 34em; }
.hero__cta { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }
.hero__note { margin-top: 40px; color: var(--text-mute); font-size: 14px; }

.hero .btn { padding: 14px 26px; font-size: 15px; }

/* Метка режима зала окрашена по смыслу: вебинар, сцена и зал, встреча
   различаются с одного взгляда, без чтения. */
.pill--broadcast { background: #fff2e6; border-color: #ffd6b0; color: #a85c17; }
.pill--hybrid    { background: var(--brand-soft); border-color: #c9d3ff; color: var(--brand); }
.pill--equal     { background: #eafaf3; border-color: #b9e8d3; color: var(--ok); }

/* ── Игры площадки ────────────────────────────────────────────────────────────
 *
 * Витрина живёт на общей странице мероприятия, поэтому строится из тех же
 * плиток, что и залы: человек не должен догадываться, что игры пришли из
 * другого места. Отдельно только страница самой игры — там нужна рамка,
 * которая не мешает игре и не даёт про неё забыть.
 */

.games { margin-top: 34px; }
.games__h { font-size: 19px; margin: 0 0 4px; }
.games__sub { margin: 0 0 16px; }

.game__about { margin: 8px 0 0; color: var(--text-dim); font-size: 14px; }
.game__top { margin: 8px 0 0; font-size: 13px; }

/* Страница игры: игра занимает всё, что осталось от рамки. */
.play {
    min-height: 100vh;
    display: grid;
    grid-template-columns: 1fr 300px;
    grid-template-rows: auto 1fr;
    gap: 18px;
    padding: 16px 20px 20px;
    max-width: 1240px;
    margin: 0 auto;
}

.play__top {
    grid-column: 1 / -1;
    display: flex; align-items: center; gap: 16px;
}

.play__hint { color: var(--text-mute); font-size: 13px; }
.play__score { margin-left: auto; color: var(--text-dim); font-size: 15px; }
.play__score b { color: var(--text); font-size: 18px; }

.play__frame {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r);
    box-shadow: var(--shadow-2);
    overflow: hidden;
    /* Игры рисуют себя от высоты окна, поэтому рамке нужна своя высота, а не
       содержимое: иначе кадр схлопывается в ноль. */
    min-height: 70vh;
}

.play__frame iframe { display: block; width: 100%; height: 100%; min-height: 70vh; border: 0; }

.play__side { display: flex; flex-direction: column; gap: 14px; }
.play__h { font-size: 15px; margin: 0 0 10px; }

.board { margin: 0; padding: 0; list-style: none; counter-reset: mesto; }
.board li {
    display: flex; align-items: center; gap: 8px;
    padding: 7px 0;
    border-bottom: 1px solid var(--line);
    font-size: 14px;
}
.board li:last-child { border-bottom: 0; }
.board li span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.board li b { margin-left: auto; }

@media (max-width: 900px) {
    /* На телефоне рамка уходит вниз: экран нужен игре, а не таблице. */
    .play { grid-template-columns: 1fr; padding: 12px; gap: 12px; }
    .play__frame, .play__frame iframe { min-height: 78vh; }
}

@media (max-width: 560px) {
    /* Подсказка вставала в шапке в три строки и выдавливала счёт. Игра и
       сама показывает, что делать, поэтому в узкой шапке она лишняя. */
    .play__hint { display: none; }
}

/* Метка записи в зале. Красная точка мигает — неподвижную принимают за
   значок, а не за состояние. При выключенном движении остаётся заливка. */
.ev-rec {
    display: inline-flex; align-items: center; gap: 7px;
    padding: 5px 11px;
    background: rgba(217, 45, 75, .14);
    color: #ff9db0;
    border-radius: 999px;
    font-size: 13px; font-weight: 600;
}
.ev-rec i {
    width: 8px; height: 8px; border-radius: 50%;
    background: #ff4d6a;
    animation: rec-pulse 1.6s ease-in-out infinite;
}
@keyframes rec-pulse { 0%, 100% { opacity: 1 } 50% { opacity: .25 } }
@media (prefers-reduced-motion: reduce) { .ev-rec i { animation: none } }

/* Список записей в кабинете. */
.recs { width: 100%; border-collapse: collapse; font-size: 14px; }
.recs th, .recs td { text-align: left; padding: 10px 8px; border-bottom: 1px solid var(--line); }
.recs th { color: var(--text-mute); font-weight: 600; font-size: 13px; }
.recs .live { color: var(--bad); font-weight: 600; }

/* ── Оформление мероприятия ───────────────────────────────────────────────────
 *
 * Фон ставит организатор: сплошной цвет, градиент или картинка. Живой фон на
 * canvas при этом гасится — два фона одновременно превращаются в кашу.
 */

.theme { background-attachment: fixed; background-size: cover; }
.theme .fx-bg, .theme body::after { display: none; }

/* Светлый текст поверх тёмного фона. Карточки становятся стеклянными: на
   фотографии белая плашка выглядит наклейкой и закрывает то, ради чего фон
   и ставили. */
.theme--light { color: #f4f6fb; }
.theme--light h1, .theme--light h2, .theme--light h3 { color: #fff; }
.theme--light .ev-dim, .theme--light .ev-mute { color: rgba(255, 255, 255, .78); }
/* Текст внутри карточек наследовал приглушённый серый, рассчитанный на
   белый лист: на тёмном стекле он превращался в неразличимую надпись. */
.theme--light .tile p, .theme--light .card p,
.theme--light .game__about, .theme--light .tile__meta { color: rgba(255, 255, 255, .82); }
.theme--light .games__sub, .theme--light .game__top { color: rgba(255, 255, 255, .72); }
.theme--light .card {
    background: rgba(20, 24, 31, .46);
    border-color: rgba(255, 255, 255, .16);
    backdrop-filter: blur(18px) saturate(1.2);
    -webkit-backdrop-filter: blur(18px) saturate(1.2);
    color: #f4f6fb;
}
.theme--light .tile {
    background: rgba(20, 24, 31, .42);
    border-color: rgba(255, 255, 255, .16);
    color: #f4f6fb;
}
.theme--light .tile h3 { color: #fff; }
.theme--light .pill { background: rgba(255, 255, 255, .16); color: #fff; }
.theme--light .empty { color: rgba(255, 255, 255, .72); border-color: rgba(255, 255, 255, .18); }
.theme--light a { color: #cdd7ff; }

/* Карточка зала со своим фоном: текст поверх картинки читается только с
   вуалью, поэтому она встроена в саму карточку. */
.tile--art {
    position: relative;
    border: 0;
    color: #fff;
    overflow: hidden;
    background-size: cover;
    background-position: center;
}
.tile--art::before {
    content: "";
    position: absolute; inset: 0;
    /* Вуаль плотная намеренно: тема зала может быть светлой, и белые буквы
       на светлом градиенте не читаются. Плотность подобрана так, чтобы фон
       оставался узнаваемым, а текст читался на любом из них. */
    background: linear-gradient(180deg, rgba(10, 12, 18, .42) 0%, rgba(10, 12, 18, .74) 100%);
    pointer-events: none;
}
.tile--art > * { position: relative; z-index: 1; }
.tile--art h3 { color: #fff; }
.tile--art .pill { background: rgba(255, 255, 255, .22); color: #fff; }
.tile--art .btn { background: rgba(255, 255, 255, .92); color: #14181f; box-shadow: none; }
.tile--art .btn--primary { background: #fff; color: #14181f; }

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

.pomosh__lines {
    max-height: 320px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-bottom: 14px;
}

.pomosh__hint { color: var(--text-mute); font-size: 14px; }

.pomosh__line {
    max-width: 82%;
    padding: 10px 14px;
    border-radius: 14px;
    font-size: 14.5px;
    line-height: 1.5;
    white-space: pre-wrap;
    animation: rise var(--t) var(--ease-spring) both;
}
.pomosh__line--me { align-self: flex-end; background: var(--brand); color: #fff; }
.pomosh__line--it { align-self: flex-start; background: var(--surface-2); color: var(--text); }
.pomosh__line--wait { align-self: flex-start; color: var(--text-mute); font-size: 13px; }

.pomosh__send { display: flex; gap: 10px; }
.pomosh__send input { flex: 1; }

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

/* Кружок предпросмотра стоит в строке полей, а `.row > *` тянет своих детей
   на всю ширину: без явного запрета аватар растягивался в полосу. */
.ava--sm {
    width: 64px; height: 64px; margin: 0; flex: 0 0 auto;
    font-size: 24px; border-radius: 50%;
    background-size: cover; background-position: center;
}

.access__who { display: flex; align-items: center; gap: 11px; }
.access__ava {
    width: 38px; height: 38px; flex: 0 0 auto;
    border-radius: 50%; object-fit: cover;
    background: var(--brand-soft); border: 1px solid var(--line);
}
.access__ava--letter {
    display: flex; align-items: center; justify-content: center;
    font-weight: 620; color: var(--brand); font-size: 15px;
}

.person__ava {
    width: 30px; height: 30px; flex: 0 0 auto;
    border-radius: 50%; object-fit: cover;
    background: rgba(255, 255, 255, .12);
}
.person__ava--letter {
    display: flex; align-items: center; justify-content: center;
    font-size: 13px; font-weight: 620; color: #cdd7ff;
}

/* Аватар на плитке лежит ПОД видео: выключил камеру — плитка перестаёт быть
   чёрным прямоугольником и остаётся лицом человека. */
.tile-v__ava {
    position: absolute; inset: 0; margin: auto;
    width: 92px; height: 92px;
    border-radius: 50%; object-fit: cover;
    background: #1b2030;
}
.tile-v__ava--letter {
    display: flex; align-items: center; justify-content: center;
    font-size: 34px; font-weight: 620; color: #93aaff;
}
.tile-v.is-muted .tile-v__video { display: none; }
/* В ленте плитка ниже главной: крупный аватар в ней обрезается по краям. */
.ev-side .tile-v__ava { width: 68px; height: 68px; font-size: 26px; }
.tile-v__name { display: flex; align-items: center; gap: 7px; }
.tile-v__dot { width: 18px; height: 18px; border-radius: 50%; object-fit: cover; }

/* ── Зал под оформлением мероприятия ──────────────────────────────────────────
 *
 * Фон ложится ВОКРУГ сцены: сама сцена остаётся тёмной, потому что видео на
 * белом режет глаз. Панели становятся плотнее — светлый текст должен читаться
 * и поверх светлой темы.
 */

.ev-themed .ev-room { background: transparent; }
.ev-themed .ev-head,
.ev-themed .ev-bar {
    background: rgba(10, 12, 18, .68);
    backdrop-filter: blur(16px) saturate(1.2);
    -webkit-backdrop-filter: blur(16px) saturate(1.2);
    border-color: rgba(255, 255, 255, .12);
}
.ev-themed .ev-stage { padding: 18px; }
.ev-themed .ev-main { box-shadow: 0 24px 70px rgba(0, 0, 0, .45); }
.ev-themed .dock { background: rgba(10, 12, 18, .82); }

/* ── Артефакт в зале ──────────────────────────────────────────────────────────
 *
 * Вещается адрес, а не картинка: каждый открывает поверхность у себя. Кадр
 * стоит в песочнице, поэтому доступа к нашему домену у чужого HTML нет.
 */

.ev-art { position: absolute; inset: 0; background: #fff; }
.ev-art iframe { width: 100%; height: 100%; border: 0; display: block; }
/* Зал смотрит, ведущий работает: у остальных кадр не перехватывает нажатия. */
.ev-art__lock { position: absolute; inset: 0; background: transparent; }
.ev-art__title {
    position: absolute; left: 12px; top: 12px;
    padding: 5px 11px; border-radius: 8px;
    background: rgba(10, 12, 18, .62);
    backdrop-filter: blur(8px);
    color: #fff; font-size: 12px; pointer-events: none;
}

/* Раскладка видео вокруг артефакта. Три случая, и они разные по смыслу:
   доклад с инфографикой, обсуждение вокруг таблицы, общая игра. */
.ev-stage--art .ev-main { background: #fff; }
/* Лента в углу считает своё место от сцены, а не от окна. */
.ev-stage { position: relative; }

.ev-stage--corner .ev-side {
    position: absolute; right: 26px; bottom: 96px;
    width: 190px; z-index: 4; overflow: visible;
}
.ev-stage--corner .ev-side .tile-v {
    height: 118px;
    box-shadow: 0 12px 34px rgba(0, 0, 0, .5);
}
/* В углу — только один: ряд плиток поверх артефакта закрывает то, ради чего
   его и показали. */
.ev-stage--corner .ev-side .tile-v:not(:first-child) { display: none; }

.ev-stage--hidden .ev-side { display: none; }

@media (max-width: 760px) {
    /* На телефоне лента уезжает под артефакт: сбоку для неё места нет. */
    .ev-stage--art { flex-direction: column; }
    .ev-stage--art .ev-side { width: auto; flex-direction: row; height: 104px; }
    .ev-stage--corner .ev-side {
        position: absolute; right: 12px; bottom: 88px; width: 118px; height: auto;
    }
    .ev-stage--corner .ev-side .tile-v { height: 84px; width: 118px; }
}

/* Кто входит по именной ссылке — имя показано, а не спрошено заново. */
.gate-who { display: flex; align-items: center; gap: 12px; }
.gate-who b { font-size: 16px; }

/* ── Отклик зала ──────────────────────────────────────────────────────────────
 *
 * Три реакции и всплывающая подпись. Длинный список эмоций люди не разбирают,
 * а итогам мероприятия нужны ровно «зашло», «полезно» и «непонятно».
 */

.ev-react { display: inline-flex; gap: 8px; margin-left: 6px; flex-wrap: wrap; }

.ev-reacts {
    position: fixed; right: 22px; bottom: 92px; z-index: 6;
    display: flex; flex-direction: column-reverse; gap: 6px;
    pointer-events: none;
}
.ev-react__fly {
    padding: 6px 12px; border-radius: 999px;
    background: rgba(10, 12, 18, .72);
    backdrop-filter: blur(8px);
    color: #eef1f7; font-size: 13px; white-space: nowrap;
    animation: react-fly 2.6s ease-out both;
}
@keyframes react-fly {
    0%   { opacity: 0; transform: translateY(10px) scale(.96) }
    12%  { opacity: 1; transform: translateY(0) scale(1) }
    75%  { opacity: 1 }
    100% { opacity: 0; transform: translateY(-14px) }
}
@media (prefers-reduced-motion: reduce) {
    .ev-react__fly { animation: none; }
}

/* На телефоне подписи реакций съедают панель: оставляем их значками-словами
   в один ряд, а лишнее прячем под общий перенос. */
@media (max-width: 760px) {
    .ev-react { flex-wrap: wrap; }
    .ev-reacts { right: 10px; bottom: 120px; }
}

/* ── Итоги мероприятия в кабинете ────────────────────────────────────────────── */

.itogi { white-space: pre-wrap; line-height: 1.6; font-size: 15px; }
.itogi h4 { margin: 18px 0 6px; font-size: 14px; letter-spacing: .04em;
            text-transform: uppercase; color: var(--text-mute); }
.itogi p { margin: 0 0 10px; }

.fakty { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 18px; }
.fakt {
    flex: 1 1 150px; padding: 14px 16px; border-radius: var(--r-sm);
    background: var(--surface-2); border: 1px solid var(--line);
}
.fakt b { display: block; font-size: 26px; line-height: 1.1; color: var(--brand); }
.fakt span { color: var(--text-mute); font-size: 13px; }

/* Кто открыл ссылку среды: лицо рядом с именем. Аватар ставит организатор
   заранее, и человек должен увидеть его раньше, чем войдёт в зал. */
.whoami { display: flex; align-items: center; gap: 12px; margin: 0 0 18px; }
.whoami__ava {
    width: 44px; height: 44px; flex: 0 0 auto; border-radius: 50%;
    background: var(--brand-soft) center/cover no-repeat;
    border: 1px solid var(--line);
    display: flex; align-items: center; justify-content: center;
    font-size: 18px; font-weight: 650; color: var(--brand);
}

/* Строка ведущего в таблице доступа: он в списке первый и не редактируется —
   доступ себе он не выдаёт. */
.access__me { background: rgba(111, 140, 255, .05); }
.access__me input[disabled] { opacity: .55; cursor: default; }
.access__ya {
    display: inline-block; margin-left: 6px; padding: 1px 7px;
    border-radius: 999px; font-size: 11px; font-weight: 600;
    color: var(--brand); background: var(--brand-soft); vertical-align: middle;
}

/* Оформление: выбор темы и то, что сейчас стоит фоном, рядом. */
.th-room__row { display: flex; align-items: center; gap: 10px; }
.th-room__row select { flex: 1; min-width: 0; }
.th-fon {
    width: 76px; height: 42px; flex: 0 0 auto;
    border-radius: 9px; border: 1px solid var(--line);
    background-size: cover; background-position: center;
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .35);
}

/* Режим записи: страницу открыл браузер-писец. В файл должно попасть то, что
   видит человек в зале, — сцена и люди, — а не панель управления, которую
   этому браузеру всё равно нечем нажимать. */
.ev-zapis .ev-bar,
.ev-zapis .ev-head,
.ev-zapis .dock,
.ev-zapis #gate { display: none !important; }
.ev-zapis .ev-stage { padding: 0; }
.ev-zapis .ev-room { height: 100vh; }

/* Разделы мероприятия одной строкой. Кабинет — длинная страница, и раздел,
   о котором не знаешь, найти можно только прокруткой. */
.razdely {
    display: flex; flex-wrap: wrap; gap: 6px;
    margin: 4px 0 18px; padding: 6px;
    background: var(--surface-2, rgba(120, 120, 160, .07));
    border: 1px solid var(--line); border-radius: 12px;
}
.razdely a {
    padding: 7px 13px; border-radius: 8px;
    font-size: 13.5px; font-weight: 500; color: var(--text-mute);
    text-decoration: none; white-space: nowrap;
    transition: background var(--t-fast), color var(--t-fast);
}
.razdely a:hover { background: var(--brand-soft); color: var(--brand); }
html { scroll-behavior: smooth; }
[id^="r-"] { scroll-margin-top: 18px; }

/* Кнопка записи в переходном состоянии: медиа-сервер поднимает и дописывает
   файл секундами, и всё это время нажимать её нечего. */
.ctl.is-waiting { opacity: .75; cursor: progress; }
.ctl.is-waiting .ctl__i { animation: pulse 1.4s var(--ease-out) infinite; }

/* Участник без картинки. Он в зале есть, и зал обязан это показывать:
   пустое место читается как «не пришла», а это другая беда. */
.tile-v--tih { background: rgba(255, 255, 255, .05); }
.tile-v__tiho {
    position: absolute; left: 50%; bottom: 34%;
    transform: translateX(-50%);
    padding: 4px 10px; border-radius: 999px;
    background: rgba(0, 0, 0, .45); backdrop-filter: blur(6px);
    font-size: 11.5px; color: #cfd6e4; white-space: nowrap; z-index: 2;
}

/* Отказ устройства в зале. Человек должен узнать, что его не видно, от зала,
   а не от собеседников через пять минут. */
.ev-beda {
    display: flex; align-items: center; gap: 12px;
    margin: 10px 16px 0; padding: 11px 14px;
    background: rgba(217, 45, 75, .16); border: 1px solid rgba(217, 45, 75, .38);
    border-radius: 12px; color: #ffd0d8; font-size: 13.5px; line-height: 1.45;
}
.ev-beda .btn { flex: 0 0 auto; }
.ev-beda__x {
    margin-left: auto; background: none; border: 0; color: #ffd0d8;
    font-size: 20px; line-height: 1; cursor: pointer; opacity: .7;
}
.ev-beda__x:hover { opacity: 1; }

/* Расшифровка встречи в кабинете: её читают глазами целиком, поэтому
   моноширинный столбик и своя прокрутка, а не полотно на весь экран. */
.rasshifrovka { margin-top: 18px; }
.rasshifrovka h3 { font-size: 15px; margin: 0 0 10px; }
.rasshifrovka pre {
    margin: 0; max-height: 420px; overflow: auto;
    padding: 14px 16px; border-radius: 12px;
    background: var(--surface-2, rgba(120, 120, 160, .07));
    border: 1px solid var(--line);
    font: 13px/1.6 ui-monospace, Menlo, monospace;
    white-space: pre-wrap; word-break: break-word;
}
