/* meet405 — стили. Один раз вырезаны из app.css chat405 по СЕЛЕКТОРАМ, дальше
 * файл живёт руками.
 *
 * ⚑ Оставлены правила, чьи классы встречаются в разметке и коде этого
 * приложения (плюс сброс, токены темы, шрифты и анимации). Из 5664 строк
 * мессенджера осталась примерно пятая часть: чат-лист, лента сообщений,
 * композер, стикеры, админка и правая колонка сюда не приехали.
 *
 * 🔴 ⛔ ЧЕМ ЭТА РЕЗКА ОПАСНА, на живом примере. Инструмент оставлял правило,
 * если в его селекторе есть используемый класс ИЛИ это селектор по элементу.
 * Глобальное `[hidden] { display: none !important }` — ни то, ни другое, и оно
 * выпало. На проде 26.08 это выглядело так: человек входит через 405, сессия
 * заводится, /api/me отвечает 200, приложение работает — и показывает экран
 * входа, потому что ОБЕ панели нарисованы одна под другой. Ни одной ошибки
 * нигде.
 *
 * Мораль не про этот файл, а про приём: вырезание по селекторам молча теряет
 * правила, у которых нет ни класса, ни имени элемента. Если понадобится
 * повторить — сначала выписать такие правила отдельно, потом резать.
 */

/* 🔴 Атрибут `hidden` обязан РЕАЛЬНО скрывать. Браузерная таблица говорит
   [hidden]{display:none}, но ЛЮБОЕ авторское правило со своим display бьёт её —
   а он есть почти у всего (у .meet-login и .meet-app это flex, у .field тоже).
   Отказ молчаливый и каждый раз одинаковый: код ставит `hidden`, тест проверяет
   `el.hidden === true` и проходит, а штука стоит на экране.
   В chat405 это стоило трёх разных сообщений за один день; здесь — одного
   «после входа снова вход». Одно правило вместо того, чтобы каждый раз помнить
   про пару; частные `[hidden]`-правила ниже теперь избыточны, но безвредны. */
[hidden] { display: none !important; }
*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  overflow: hidden; /* the app manages its own internal scroll regions */
}
h1, p, ul, li, form { margin: 0; padding: 0; list-style: none; }
button {
  font: inherit;
  color: inherit;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
}
input, textarea {
  font: inherit;
  color: inherit;
}
img, svg { display: block; }
a { color: inherit; }
:root {
  color-scheme: dark;

  --font-sans: 'Open Sans', 'Segoe UI', system-ui, -apple-system, sans-serif; /* tdesktop ships Open Sans — the text texture is half of why it looked foreign */

  --bg-app: #0e1621;
  --bg-sidebar: #17212b;
  --bg-thread: #1c2b26;
  /* Обои чата: четыре цвета из ConstructDefault(), приглушённые под ночь —
     ярко-зелёная стена под тёмными пузырями читалась бы как чужая. */
  --chat-wallpaper:
    radial-gradient(78% 78% at 18% 12%, #233a30 0%, rgba(35, 58, 48, 0) 72%),
    radial-gradient(78% 78% at 84% 16%, #1d3b31 0%, rgba(29, 59, 49, 0) 72%),
    radial-gradient(80% 80% at 12% 88%, #223526 0%, rgba(34, 53, 38, 0) 74%),
    radial-gradient(86% 86% at 88% 84%, #1a2f28 0%, rgba(26, 47, 40, 0) 74%);
  --chat-wallpaper-pattern: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22260%22%20height%3D%22260%22%20viewBox%3D%220%200%20260%20260%22%3E%3Cg%20fill%3D%22none%22%20stroke%3D%22%23ffffff%22%20stroke-width%3D%222.4%22%20stroke-linecap%3D%22round%22%20opacity%3D%220.06%22%3E%3Ccircle%20cx%3D%2238%22%20cy%3D%2242%22%20r%3D%2219%22%2F%3E%3Ccircle%20cx%3D%22232%22%20cy%3D%2270%22%20r%3D%2211%22%2F%3E%3Ccircle%20cx%3D%22128%22%20cy%3D%22166%22%20r%3D%2227%22%2F%3E%3Ccircle%20cx%3D%2260%22%20cy%3D%22228%22%20r%3D%2214%22%2F%3E%3Cpath%20d%3D%22M132%2016%20a26%2026%200%200%201%2044%2020%22%2F%3E%3Cpath%20d%3D%22M196%20196%20a22%2022%200%200%200%20-38%2016%22%2F%3E%3Cpath%20d%3D%22M14%20128%20a20%2020%200%200%201%2030%20-10%22%2F%3E%3Cpath%20d%3D%22M162%2096%20q12%20-12%2024%200%20t24%200%22%2F%3E%3Cpath%20d%3D%22M28%20168%20q10%2010%2020%200%20t20%200%22%2F%3E%3Cpath%20d%3D%22M92%2044%20l16%20-16%22%2F%3E%3Cpath%20d%3D%22M100%2052%20l16%20-16%22%2F%3E%3Cpath%20d%3D%22M214%20140%20l14%2014%22%2F%3E%3Cpath%20d%3D%22M222%20132%20l14%2014%22%2F%3E%3Cpath%20d%3D%22M188%2060%20h16%20M196%2052%20v16%22%2F%3E%3Cpath%20d%3D%22M74%20122%20h14%20M81%20115%20v14%22%2F%3E%3Cpath%20d%3D%22M240%20214%20h14%20M247%20207%20v14%22%2F%3E%3Crect%20x%3D%2286%22%20y%3D%22196%22%20width%3D%2226%22%20height%3D%2226%22%20rx%3D%228%22%2F%3E%3Crect%20x%3D%22176%22%20y%3D%22240%22%20width%3D%2220%22%20height%3D%2220%22%20rx%3D%226%22%2F%3E%3C%2Fg%3E%3Cg%20fill%3D%22%23ffffff%22%20opacity%3D%220.06%22%3E%3Ccircle%20cx%3D%22166%22%20cy%3D%2246%22%20r%3D%223.5%22%2F%3E%3Ccircle%20cx%3D%2222%22%20cy%3D%2296%22%20r%3D%223%22%2F%3E%3Ccircle%20cx%3D%22252%22%20cy%3D%22118%22%20r%3D%223%22%2F%3E%3Ccircle%20cx%3D%22110%22%20cy%3D%2292%22%20r%3D%223%22%2F%3E%3Ccircle%20cx%3D%2246%22%20cy%3D%22152%22%20r%3D%223.5%22%2F%3E%3Ccircle%20cx%3D%22204%22%20cy%3D%22168%22%20r%3D%223%22%2F%3E%3Ccircle%20cx%3D%22148%22%20cy%3D%22232%22%20r%3D%223.5%22%2F%3E%3Ccircle%20cx%3D%2296%22%20cy%3D%22258%22%20r%3D%223%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");
  --bg-panel: #17212b;
  --bg-elevated: #1f2b38;
  --bg-hover: #1c2733;
  --bg-active: #2b5278;
  --bg-input: #242f3d;

  --border-subtle: #1e2933;
  --border-strong: #2b3947;

  --text-primary: #e9edef;
  --text-secondary: #8296a8;
  --text-tertiary: #5d707f;
  --text-on-accent: #ffffff;

  --accent: #4ea4f5;
  --accent-strong: #2b96e8;
  /* The info column's action tiles. tdesktop paints them with the accent at
     infoProfileTopBarActionButtonBgOpacity = 0.16 rather than with a grey, so
     the row of them reads as one control strip instead of four buttons. */
  --accent-soft: rgba(78, 164, 245, 0.16);
  /* activeButtonSecondaryFg — the count inside FORWARD 3 / DELETE 3, which
     tdesktop draws dimmer than the label (lib_ui colors.palette says so in as
     many words: "selected messages counter in forward / delete buttons"). */
  --accent-btn-count: #9abfe7;

  --bubble-own-bg: #2b5278;
  --bubble-own-text: #eaf3ff;
  --bubble-other-bg: #182533; /* tdesktop night incoming */
  --bubble-other-text: #e5e9ec;
  --bubble-quote-bg: rgba(255, 255, 255, 0.08);

  --unread-badge-bg: #4082bc; /* dialogsUnreadBg night */
  --unread-badge-text: #ffffff;
  --unread-badge-muted-bg: #35424e;
  --unread-badge-muted-text: #8296a8;

  --tick-sent-color: #8296a8;
  /* historyOutIconFg #6bbfff: tdesktop uses ONE colour for the single and the
     double tick — sent vs read differ by COUNT, not colour. Our two-colour
     scheme was invented. historySendingOutIconFg is the pending clock. */
  --tick-read-color: #6bbfff;
  --tick-own-sent: #6bbfff;
  --flash-overlay: rgba(255, 255, 255, 0.16);
  --tick-clock: #70a4d2;
  --msg-time-in: #6d7f8f;   /* msgInDateFg */
  --msg-time-out: #7da8d3;  /* msgOutDateFg */

  /* A SELECTED message. Telegram repaints the bubble rather than washing the
     row, and in the night theme msgInBgSelected and msgOutBgSelected are the
     SAME blue — a selection reads down a mixed conversation at a glance
     because both directions land on one colour. */
  --bubble-selected-bg: #2e70a5;      /* msgInBgSelected */
  --bubble-own-selected-bg: #2e70a5;  /* msgOutBgSelected */
  --msg-time-selected: #ffffff;       /* msgInDateFgSelected */
  --msg-time-own-selected: #ffffff;   /* msgOutDateFgSelected */
  --tick-selected: #ffffff;           /* historyOutIconFgSelected */
  --select-overlay: #3585d44c;        /* msgSelectOverlay, for media */
  /* msgSelectionCheck: a 2px windowBg ring over msgServiceBg, filled with
     boxTextFgGood when checked and the check drawn in windowBg. */
  --check-ring: #17212b;              /* windowBg */
  --check-ring-bg: #213040d5;         /* msgServiceBg */
  --check-checked-bg: #5598db;        /* boxTextFgGood, night */
  --check-checked-fg: #17212b;        /* overviewCheckFgActive = windowBg */

  --danger: #f2555a;
  --divider-unread-color: #4ea4f5;
  --presence-online: #43b581;

  --scrollbar-thumb: #2b3947;

  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 16px;
  --radius-bubble: 16px; /* tdesktop bubbleRadiusLarge */

  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;

  --shadow-panel: 0 12px 32px rgba(0, 0, 0, 0.45);
  --sidebar-width: 300px;
}
:root[data-theme="light"] {
  color-scheme: light;

  --bg-app: #eef2f5;
  --bg-sidebar: #ffffff;
  --bg-thread: #a8c69a; /* база под градиент обоев */
  /* Обои чата ровно из первоисточника (data_wall_paper.cpp,
     WallPaper::ConstructDefault): rgb(219,221,187) / rgb(107,165,135) /
     rgb(213,216,141) / rgb(136,184,132), узор интенсивности 50. */
  --chat-wallpaper:
    radial-gradient(72% 72% at 16% 12%, #dbddbb 0%, rgba(219, 221, 187, 0) 70%),
    radial-gradient(72% 72% at 86% 18%, #6ba587 0%, rgba(107, 165, 135, 0) 70%),
    radial-gradient(74% 74% at 12% 86%, #d5d88d 0%, rgba(213, 216, 141, 0) 72%),
    radial-gradient(80% 80% at 90% 88%, #88b884 0%, rgba(136, 184, 132, 0) 74%);
  --chat-wallpaper-pattern: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22260%22%20height%3D%22260%22%20viewBox%3D%220%200%20260%20260%22%3E%3Cg%20fill%3D%22none%22%20stroke%3D%22%23335c42%22%20stroke-width%3D%222.4%22%20stroke-linecap%3D%22round%22%20opacity%3D%220.14%22%3E%3Ccircle%20cx%3D%2238%22%20cy%3D%2242%22%20r%3D%2219%22%2F%3E%3Ccircle%20cx%3D%22232%22%20cy%3D%2270%22%20r%3D%2211%22%2F%3E%3Ccircle%20cx%3D%22128%22%20cy%3D%22166%22%20r%3D%2227%22%2F%3E%3Ccircle%20cx%3D%2260%22%20cy%3D%22228%22%20r%3D%2214%22%2F%3E%3Cpath%20d%3D%22M132%2016%20a26%2026%200%200%201%2044%2020%22%2F%3E%3Cpath%20d%3D%22M196%20196%20a22%2022%200%200%200%20-38%2016%22%2F%3E%3Cpath%20d%3D%22M14%20128%20a20%2020%200%200%201%2030%20-10%22%2F%3E%3Cpath%20d%3D%22M162%2096%20q12%20-12%2024%200%20t24%200%22%2F%3E%3Cpath%20d%3D%22M28%20168%20q10%2010%2020%200%20t20%200%22%2F%3E%3Cpath%20d%3D%22M92%2044%20l16%20-16%22%2F%3E%3Cpath%20d%3D%22M100%2052%20l16%20-16%22%2F%3E%3Cpath%20d%3D%22M214%20140%20l14%2014%22%2F%3E%3Cpath%20d%3D%22M222%20132%20l14%2014%22%2F%3E%3Cpath%20d%3D%22M188%2060%20h16%20M196%2052%20v16%22%2F%3E%3Cpath%20d%3D%22M74%20122%20h14%20M81%20115%20v14%22%2F%3E%3Cpath%20d%3D%22M240%20214%20h14%20M247%20207%20v14%22%2F%3E%3Crect%20x%3D%2286%22%20y%3D%22196%22%20width%3D%2226%22%20height%3D%2226%22%20rx%3D%228%22%2F%3E%3Crect%20x%3D%22176%22%20y%3D%22240%22%20width%3D%2220%22%20height%3D%2220%22%20rx%3D%226%22%2F%3E%3C%2Fg%3E%3Cg%20fill%3D%22%23335c42%22%20opacity%3D%220.14%22%3E%3Ccircle%20cx%3D%22166%22%20cy%3D%2246%22%20r%3D%223.5%22%2F%3E%3Ccircle%20cx%3D%2222%22%20cy%3D%2296%22%20r%3D%223%22%2F%3E%3Ccircle%20cx%3D%22252%22%20cy%3D%22118%22%20r%3D%223%22%2F%3E%3Ccircle%20cx%3D%22110%22%20cy%3D%2292%22%20r%3D%223%22%2F%3E%3Ccircle%20cx%3D%2246%22%20cy%3D%22152%22%20r%3D%223.5%22%2F%3E%3Ccircle%20cx%3D%22204%22%20cy%3D%22168%22%20r%3D%223%22%2F%3E%3Ccircle%20cx%3D%22148%22%20cy%3D%22232%22%20r%3D%223.5%22%2F%3E%3Ccircle%20cx%3D%2296%22%20cy%3D%22258%22%20r%3D%223%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");
  --bg-panel: #ffffff;
  --bg-elevated: #f3f5f7;
  --bg-hover: #f2f4f6;
  --bg-active: #419fd9; /* tdesktop day: the active chat row is SOLID blue with white text */
  --bg-input: #eef1f4;

  --border-subtle: #e4e8ec;
  --border-strong: #d5dbe1;

  --text-primary: #17212b;
  --text-secondary: #6d7883;
  --text-tertiary: #98a1a9;
  --text-on-accent: #ffffff;

  --accent: #3390ec;
  --accent-strong: #2077cf;
  --accent-soft: rgba(51, 144, 236, 0.12);
  --accent-btn-count: #cceeff;

  /* THE Telegram day signature: outgoing is pale GREEN, not blue. The blue
     bubble was the single biggest "this is not Telegram" tell in the light
     theme — every other messenger is blue; Telegram day is #effdde with
     green ticks. */
  --bubble-own-bg: #effdde;
  --bubble-own-text: #141414;
  --bubble-other-bg: #ffffff;
  --bubble-other-text: #1a232c;
  --bubble-quote-bg: rgba(17, 51, 85, 0.06);

  --unread-badge-bg: #40a7e3; /* dialogsUnreadBg day = windowBgActive */
  --unread-badge-text: #ffffff;
  --unread-badge-muted-bg: #d7dce1;
  --unread-badge-muted-text: #6d7883;

  --tick-sent-color: #9aa4ac;
  --tick-read-color: #57b84c; /* historyOutIconFg — one colour for 1 and 2 ticks */
  --tick-own-sent: #57b84c;
  /* msgSelectOverlay: the wash tdesktop paints over a jumped-to bubble. Dark
     on a light theme, light on a dark one — it must read on the pale green
     outgoing bubble AND on white. */
  --flash-overlay: rgba(17, 51, 85, 0.14);
  --tick-clock: #98d292;
  --msg-time-in: #a0acb6;
  --msg-time-out: #6db566;

  /* Day, and here the two directions genuinely differ: bluish for incoming,
     teal for outgoing, and the checked circle is GREEN (boxTextFgGood
     #4ab44a) rather than the night theme's blue. */
  --bubble-selected-bg: #c2dcf2;      /* msgInBgSelected */
  --bubble-own-selected-bg: #b7dbdb;  /* msgOutBgSelected */
  --msg-time-selected: #6a9cc5;       /* msgInDateFgSelected */
  --msg-time-own-selected: #56b2a6;   /* msgOutDateFgSelected */
  --tick-selected: #45a3aa;           /* historyOutIconFgSelected */
  --select-overlay: #358cd44c;        /* msgSelectOverlay */
  --check-ring: #ffffff;              /* windowBg */
  --check-ring-bg: #517c417f;         /* msgServiceBg */
  --check-checked-bg: #4ab44a;        /* boxTextFgGood, day */
  --check-checked-fg: #ffffff;        /* overviewCheckFgActive = windowBg */

  --danger: #e0393e;
  --divider-unread-color: #2077cf;
  --presence-online: #2fa860;

  --scrollbar-thumb: #d1d7dc;

  --shadow-panel: 0 12px 32px rgba(20, 30, 40, 0.16);
}
body {
  background: var(--bg-app);
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.4;
  -webkit-font-smoothing: antialiased;
}
.icon {
  width: 20px;
  height: 20px;
  flex: 0 0 auto;
}
* { scrollbar-width: thin; scrollbar-color: var(--scrollbar-thumb) transparent; }
*::-webkit-scrollbar { width: 8px; height: 8px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: var(--scrollbar-thumb);
  border-radius: 8px;
  border: 2px solid transparent;
  background-clip: padding-box;
}
.icon-btn:focus-visible, .theme-toggle:focus-visible, button:focus-visible, input:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.avatar-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border-radius: inherit;
}
.avatar {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  overflow: hidden;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  font-size: 15px;
  letter-spacing: 0.02em;
  color: #ffffff;
  background: linear-gradient(160deg, hsl(var(--avatar-hue, 210) 62% 52%), hsl(var(--avatar-hue, 210) 62% 38%));
}
.avatar--saved .icon { width: 55%; height: 55%; color: inherit; }
.avatar--channel .icon { color: inherit; width: 22px; height: 22px; }
.avatar--lg { width: 72px; height: 72px; font-size: 24px; }
.menu-item .icon { color: var(--text-secondary); flex: 0 0 auto; }
.menu-item-danger, .menu-item-danger .icon { color: var(--danger, #e5534b); }
.row-ticks .icon { width: 15px; height: 10px; }
.row-ticks--clock .icon { width: 11px; height: 11px; }
.chat-row--archive .chat-row-archive-icon .icon { width: 22px; height: 22px; }
.thread-header-identity .avatar { width: 40px; height: 40px; font-size: 13.5px; }
@keyframes typing-bounce {
  0%, 60%, 100% { transform: translateY(0); opacity: 0.5; }
  30% { transform: translateY(-3px); opacity: 1; }
}
.ticks .icon { width: 15px; height: 10px; }
@keyframes bubble-flash {
  0%   { box-shadow: inset 0 0 0 400px transparent; }
  12%  { box-shadow: inset 0 0 0 400px var(--flash-overlay); }
  100% { box-shadow: inset 0 0 0 400px transparent; }
}
.msg-action-btn .icon { width: 15px; height: 15px; }
.file-download .icon { width: 16px; height: 16px; }
.send-btn .icon { width: 18px; height: 18px; }
.info-tile .icon { width: 23px; height: 23px; }
.info-row .icon { width: 22px; height: 22px; flex: 0 0 auto; color: var(--text-secondary); }
.info-row--danger .info-row-value, .info-row--danger .icon { color: var(--danger); }
.btn {
  height: 40px;
  padding: 0 var(--space-5);
  border-radius: var(--radius-md);
  font-weight: 600;
  font-size: 14px;
  width: 100%;
}
.btn--primary { background: var(--accent); color: #fff; }
.btn--primary:hover { background: var(--accent-strong); }
.btn--danger {
  margin-top: var(--space-5);
  background: transparent;
  color: var(--danger);
  border: 1px solid var(--danger);
}
.btn--danger:hover { background: rgba(242, 85, 90, 0.1); }
.message-check .icon { width: 12px; height: 12px; stroke-width: 3; }
.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  /* Without this the default `stretch` makes every dialog as tall as the
     overlay, and max-height then clamps it — which is why "Forward to…" with
     two rows in it, "New poll" and "New group" were all exactly the same
     height with half the window empty. A Telegram box is as tall as what is
     in it; max-height still caps the ones that genuinely are long, and their
     inner list keeps scrolling. */
  align-items: flex-start;
  padding-top: 12vh;
}
.modal-overlay[hidden] { display: none; }
.modal {
  width: 480px;
  max-width: calc(100vw - 48px);
  max-height: 70vh;
  background: var(--bg-panel);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-panel);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.modal-header .icon { color: var(--text-tertiary); }
.modal-search-input {
  flex: 1 1 auto;
  min-width: 0;
  height: 36px;
  background: var(--bg-input);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  padding: 0 var(--space-3);
  color: var(--text-primary);
  font-size: 14px;
}
.modal-search-input:focus { outline: none; border-color: var(--accent); }
.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 12.5px;
  color: var(--text-secondary);
  font-weight: 600;
}
.field input {
  height: 40px;
  background: var(--bg-input);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  padding: 0 var(--space-3);
  color: var(--text-primary);
  font-size: 14px;
}
.field input:focus { outline: none; border-color: var(--accent); }
.field input::placeholder { color: var(--text-tertiary); }
.field select, .field textarea {
  background: var(--bg-input);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-3);
  color: var(--text-primary);
  font-size: 14px;
  font-family: inherit;
}
.field select { height: 40px; }
.field textarea { resize: vertical; min-height: 72px; }
.field select:focus, .field textarea:focus { outline: none; border-color: var(--accent); }
@media (max-width: 1000px) {
  :root { --sidebar-width: 280px; }
}
.lightbox-nav .icon { width: 22px; height: 22px; }
.lightbox-next .icon { transform: rotate(180deg); }
.emoji-panel-search .icon { width: 15px; height: 15px; color: var(--text-tertiary); flex: 0 0 auto; }
.pinned-bar-close .icon { width: 14px; height: 14px; }
.audio-bar-btn .icon { width: 14px; height: 14px; }
.audio-bar-close .icon { width: 14px; height: 14px; }
.admin-tab-btn .icon { flex: 0 0 auto; }
.settings-avatar-row .btn { width: auto; padding: 0 var(--space-4); height: 34px; }
.admin-pager-next .icon { transform: rotate(180deg); }
.admin-confirm-overlay, .admin-secret-overlay, .admin-form-overlay { z-index: 250; padding-top: 16vh; }
.admin-confirm-modal, .admin-secret-modal, .admin-form-modal { padding: var(--space-5); max-height: 80vh; overflow-y: auto; gap: var(--space-3); display: flex; flex-direction: column; width: 420px; }
.admin-confirm-title { font-size: 16px; font-weight: 700; }
.admin-form { display: flex; flex-direction: column; gap: var(--space-3); }
.admin-field { gap: 6px; }
.admin-form-error,
.settings-2fa-error { font-size: 12.5px; font-weight: 600; color: var(--danger); }
.admin-form-actions { display: flex; gap: var(--space-3); justify-content: flex-end; }
.admin-form-actions .btn { width: auto; padding: 0 var(--space-5); }
.new-chat-hint {
  font-size: 12.5px;
  color: var(--text-secondary);
  line-height: 1.5;
  background: var(--bg-elevated);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
}
.new-chat-chip-remove .icon { width: 12px; height: 12px; }
.admin-audit-back .icon { width: 16px; height: 16px; }
@media (max-width: 900px) {
  .admin-confirm-modal, .admin-secret-modal, .admin-form-modal, .admin-csv-modal { width: 100%; max-width: calc(100vw - 32px); }
}
.voice-play .icon { width: 16px; height: 16px; }
.voice-play .icon { transform: rotate(0deg); }
@keyframes recording-pulse { 50% { opacity: 0.25; } }
.call-overlay {
  position: fixed; inset: 0; z-index: 60;
  background: var(--bg-app);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--space-3);
  /* Nothing in a call may paint outside the window: whatever else goes wrong
     with sizing, the controls stay the last row ON the screen. */
  overflow: hidden;
}
.call-actions { flex: none; }
.call-share-stage, .call-grid { min-height: 0; }
.call-status { font-size: 14px; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.call-actions { display: flex; gap: var(--space-4); margin-top: var(--space-2); }
.call-btn {
  width: 56px; height: 56px; border-radius: 50%; border: none; cursor: pointer;
  background: var(--bg-elevated); color: var(--text-primary);
  display: flex; align-items: center; justify-content: center;
}
.call-btn .icon { width: 22px; height: 22px; }
.call-btn--off { background: var(--text-tertiary); color: var(--bg-app); }
.call-btn--end { background: var(--danger); color: #fff; }
/* Колонки сетки по data-count ушли (W4-18): форму считает tileGrid Jitsi
   (call-layout.js), размеры — CSS-переменные оверлея (секция скина ниже). */
.call-grid {
  display: grid;
  gap: var(--space-2);
  width: min(92vw, 960px);
  grid-template-columns: 1fr;
}
.call-tile {
  position: relative;
  aspect-ratio: 4 / 3;
  /* Серая, как у Jitsi (Thumbnail: backgroundColor ui02 #292929), не чёрная. */
  background: #292929;
  border-radius: var(--radius-md);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}
.call-tile-video { width: 100%; height: 100%; object-fit: cover; display: block; }
.call-tile-avatar { position: absolute; }
/* Камера выключена — видео прозрачно (syncTilePlaceholder): иначе вокруг
   аватара виден застывший последний кадр. */
.call-tile--novideo .call-tile-video { opacity: 0; }
/* «Видео прервано» (12.10.2026): чужая камера принимается, а кадров нет —
   аватар (call-tile--novideo) и подпись под ним. Аватар чуть выше центра:
   на низкой плитке (150 px) подпись иначе ложится на имя. В плёнке места нет
   (кружок 40 px и имя) — там подсказка (title) и значок связи «Lost». */
.call-tile--stalled .call-tile-avatar { transform: translateY(-14px); }
.call-tile-stalled,
.j-stage-tile-stalled,
.j-stage-stalled {
  position: absolute; left: 50%; transform: translateX(-50%);
  max-width: calc(100% - 16px); box-sizing: border-box;
  padding: 2px 8px; border-radius: 3px;
  background: rgba(0, 0, 0, 0.6); color: #fff;
  font-size: 12px; line-height: 16px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  pointer-events: none;
}
.call-tile-stalled { top: calc(50% + 28px); }
.j-filmstrip .call-tile-stalled { display: none; }
.j-filmstrip .call-tile--stalled .call-tile-avatar { transform: none; }
.call-tile-name {
  position: absolute;
  left: var(--space-2);
  bottom: var(--space-2);
  padding: 2px 8px;
  border-radius: var(--radius-sm);
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 13px;
  max-width: calc(100% - var(--space-4));
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Зеркало своей камеры (W4-15, localFlipX Jitsi — по умолчанию да, Д12: и в
   экономии) — ОДИН класс на своей плитке, своей сцене, превью входа и превью
   гостя; ставит его mirrorOn() (call-settings.js): «Flip» / «Mirror my video»
   снимают, задняя камера и шара — никогда. */
.j-mirror { transform: scaleX(-1); }
.call-tile--speaking { outline: 3px solid var(--accent); outline-offset: -3px; }
.call-tile-hand {
  position: absolute;
  top: var(--space-2);
  right: var(--space-2);
  font-size: 20px;
  line-height: 1;
  padding: 4px 6px;
  border-radius: var(--radius-sm);
  background: rgba(0, 0, 0, 0.55);
}
.call-tile-hand[hidden] { display: none; }
.call-tile--hand { outline: 2px solid #f0b429; outline-offset: -2px; }
.call-tile--speaking.call-tile--hand { outline-color: var(--accent); }
/* ---- перерыв в брейклисте (13.10.2026, связь breaklist ↔ small-talk) ----
   «☕ Брейк 7 / 15 мин» — над подписью, той же плашкой, что подпись (visual-parity (39));
   сверх лимита — красное «+3 мин» и красная рамка. В панели участников — строкой под именем. */
.call-tile-break {
  position: absolute; left: 4px; bottom: 32px; z-index: 2;
  display: flex; align-items: center; gap: 6px;
  max-width: calc(100% - 8px); box-sizing: border-box;
  padding: 2px 6px; border-radius: 4px;
  background: rgba(0, 0, 0, 0.7); color: #fff;
  font-size: 12px; line-height: 16px; font-weight: 600;
  white-space: nowrap; overflow: hidden; pointer-events: none;
}
.call-tile-break[hidden] { display: none; }
.call-tile-break-text { overflow: hidden; text-overflow: ellipsis; }
.call-tile-break-over { flex: none; color: var(--danger); }
.call-tile-break--over { box-shadow: inset 0 0 0 1px var(--danger); }
.j-filmstrip .call-tile-break { bottom: 26px; padding: 1px 5px; font-size: 11px; line-height: 14px; }
.j-pane-row-break { display: block; font-size: 12px; font-weight: 600; color: #F8AE1A; }
.j-pane-row-break[hidden] { display: none; }
.j-pane-row-break-over { margin-left: 6px; color: var(--danger); }

/* ---- уровень звука и выключенный микрофон на плитке — как в Jitsi (29.09.2026) ----
   Пять точек в правом верхнем углу: центральная загорается первой, края —
   последними (dotOpacities в audio-levels.js). Погашенный индикатор не виден
   вовсе — в тишине угол плитки чистый. Поднятая рука стоит там же — точки
   уступают ей место слева. */
.call-tile-level {
  position: absolute;
  top: var(--space-2);
  right: var(--space-2);
  z-index: 3;
  display: none;
  align-items: center;
  gap: 2px;
  height: 20px;
  padding: 0 6px;
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.6);
  pointer-events: none;
}
.call-tile-level--on { display: flex; }
.call-tile-level i {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: #44A5FF;
  opacity: 0;
  transition: opacity .2s ease-in-out;
}
.call-tile--hand .call-tile-level { right: calc(var(--space-2) + 40px); }
.call-tile-muted { display: inline-flex; vertical-align: -2px; margin-right: 4px; }
.call-tile-muted[hidden] { display: none; }
.call-tile-muted .icon { width: 14px; height: 14px; color: #fff; }
/* Значок модератора — за микрофоном, перед именем (12.10.2026, ModeratorIndicator
   Jitsi в StatusIndicators.tsx; IconModerator — тот же спрайт, что у вкладки
   Moderator окна «Settings»). Скрыт атрибутом hidden — его держит глобальное
   [hidden] { display: none !important } в шапке файла, своё display: inline-flex
   его не перебивает; частного [hidden]-правила не нужно (ревью 12.10.2026). */
.call-tile-mod { display: inline-flex; vertical-align: -2px; margin-right: 4px; }
.call-tile-mod .icon { width: 14px; height: 14px; color: #fff; }
.call-share-stage {
  position: relative;
  width: min(92vw, 960px);
  max-height: 52vh;
  background: #000;
  border-radius: var(--radius-md);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}
.call-share-stage[hidden] { display: none; }
.call-share-video {
  width: 100%;
  max-height: 52vh;
  /* `contain`, never `cover`: a screen is text, and cropping the edges off a
     terminal or a slide is worse than letterboxing it. */
  object-fit: contain;
  display: block;
}
.call-share-full {
  position: absolute;
  top: var(--space-2);
  right: var(--space-2);
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border-radius: var(--radius-md);
  color: #fff;
  background: rgba(0, 0, 0, 0.55);
  opacity: 0;
  transition: opacity 120ms ease;
}
/* Показ экрана давно живёт на сцене .j-stage, а не в .call-share-stage: с
   одним старым селектором кнопка оставалась прозрачной навсегда (сверка с
   Jitsi, 30.09.2026). */
.call-share-stage:hover .call-share-full,
.j-stage:hover .call-share-full,
.call-share-full:focus-visible { opacity: 1; }
.call-share-full:hover { background: rgba(0, 0, 0, 0.75); }
.call-share-full .icon { width: 18px; height: 18px; }
.call-overlay:fullscreen { padding: 0; justify-content: center; }
.call-overlay:fullscreen .call-share-stage {
  width: 100vw;
  max-height: calc(100vh - 140px);
  border-radius: 0;
}
.call-overlay:fullscreen .call-share-video { max-height: calc(100vh - 140px); }
.screen-pick-modal { width: min(880px, 92vw); }
.screen-pick-body { max-height: 60vh; overflow-y: auto; margin: var(--space-4) 0; }
.screen-pick-section {
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-secondary);
  margin: var(--space-4) 0 var(--space-2);
}
.screen-pick-section:first-child { margin-top: 0; }
.screen-pick-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: var(--space-3);
}
.screen-pick-item {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-2);
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  text-align: left;
  width: 100%;
}
.screen-pick-item:hover, .screen-pick-item:focus-visible {
  background: var(--bg-hover);
  border-color: var(--border-strong);
}
.screen-pick-thumb {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: contain;
  background: #000;
  border-radius: var(--radius-sm);
  display: block;
}
.screen-pick-thumb--empty {
  display: grid;
  place-items: center;
  font-size: 12px;
  color: var(--text-secondary);
  background: var(--bg-input);
}
.screen-pick-label { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
.screen-pick-icon { width: 16px; height: 16px; flex: none; }
.screen-pick-name {
  font-size: 13px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.call-share-stage:not([hidden]) ~ .call-grid {
  display: flex;
  flex-wrap: nowrap;
  justify-content: center;
  height: 22vh;
  max-height: 22vh;
  overflow-x: auto;
  overflow-y: hidden;
}
.call-share-stage:not([hidden]) ~ .call-grid .call-tile {
  aspect-ratio: 16 / 9;
  height: 100%;
  flex: 0 0 auto;
}
.call-btn--on { background: var(--accent); color: #fff; }
.settings-notif-row .btn[hidden] { display: none; }
.btn--outline {
  width: auto;
  padding: 0 var(--space-5);
  background: var(--bg-input);
  border: 1px solid var(--border-strong);
}
.btn--outline:hover { background: var(--bg-hover); }
.btn--outline:disabled { opacity: 0.6; cursor: default; }
.call-btn--recording { background: var(--danger); color: #fff; }
/* .call-toast — теперь уведомление в стопке слева внизу (волна 2), см. .call-notice. */
.info-media-photo-fallback .icon { width: 28px; height: 28px; }
.info-media-play .icon { width: 12px; height: 12px; }
.ticks--clock .icon { width: 12px; height: 12px; }
.send-files-remove .icon { width: 11px; height: 11px; }
.send-files-checkbox .icon { width: 12px; height: 12px; color: #fff; }
.send-files-emoji .icon { width: 18px; height: 18px; }
.send-files-actions .btn { width: auto; padding: 6px 16px; }
.send-files-row .icon { flex: none; color: var(--accent); }
.menu-readby .icon { flex: none; width: 14px; height: 14px; margin-top: 1px; }
.scheduled-chip .icon { width: 15px; height: 15px; flex: none; }
.poll-option-mark .icon { width: 14px; height: 14px; color: var(--accent); }
.settings-2fa-secret .btn { width: auto; flex: none; }
.chat-row-menu .menu-item .icon { width: 20px; height: 20px; flex: 0 0 20px; }
.modal-overlay .btn,
.admin-form-overlay .btn,
.admin-confirm-overlay .btn,
.admin-secret-overlay .btn {
  height: 34px;
  padding: 0 var(--space-4);
  background: transparent;
  border: none;
  color: var(--accent);
  font-size: 14px;
  font-weight: 600;
}
.modal-overlay .btn:hover,
.admin-form-overlay .btn:hover,
.admin-confirm-overlay .btn:hover,
.admin-secret-overlay .btn:hover { background: var(--bg-hover); }
.modal-overlay .btn--danger,
.admin-form-overlay .btn--danger,
.admin-confirm-overlay .btn--danger,
.admin-secret-overlay .btn--danger { color: var(--danger); background: transparent; }
.panel-pin .icon { width: 15px; height: 15px; }
.catalogue-actions .btn { width: auto; padding: 6px 14px; }
.catalogue-chosen-remove .icon { width: 10px; height: 10px; }
.settings-form .admin-form-actions { justify-content: flex-end; }
.manage-photo-cam .icon { width: 12px; height: 12px; }
@keyframes kb-spin { to { transform: rotate(360deg); } }
.confirm-overlay { z-index: 200; }
.confirm-box {
  width: 340px;
  max-width: calc(100vw - 32px);
  background: var(--bg-panel);
  border-radius: 12px;
  box-shadow: 0 16px 48px rgba(0, 0, 0, .45);
  padding: 18px 20px 10px;
}
.confirm-head { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.confirm-avatar { width: 40px; height: 40px; flex: 0 0 auto; font-size: 15px; }
.confirm-title { font-size: 16px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.confirm-text { font-size: 14px; line-height: 1.45; color: var(--text-primary); white-space: pre-line; }
.confirm-check-row {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  margin-top: 14px; font-size: 14px; color: var(--text-primary);
}
.confirm-check {
  width: 20px; height: 20px; flex: 0 0 auto; border-radius: 4px;
  border: 2px solid var(--border-strong); display: grid; place-items: center;
  color: transparent;
}
.confirm-check-row--on .confirm-check { background: var(--accent); border-color: var(--accent); color: #fff; }
.confirm-check .icon { width: 13px; height: 13px; }
.confirm-actions { display: flex; justify-content: flex-end; gap: 4px; margin-top: 16px; }
.confirm-btn {
  width: auto; padding: 9px 16px; background: transparent;
  color: var(--accent); font-size: 14px; font-weight: 600;
}
.confirm-btn:hover { background: var(--bg-hover); }
.confirm-overlay .confirm-btn--danger { color: var(--danger); }
.confirm-overlay .confirm-btn { font-size: 14px; height: auto; padding: 9px 16px; }
/* Главный экран: панель действий, фильтры и ТАБЛИЦА комнат.
 *
 * ⚑ 31.08.2026 карточки заменены строками — комнат у человека бывает порядка
 * тысячи (почему именно так, написано в шапке public/js/ui/rooms.js). Отсюда
 * всё в этом блоке: строка в 40 px вместо карточки в 76, колонки постоянной
 * ширины, чтобы глаз шёл вниз по одной вертикали, разделители вместо отступов
 * и СВОЯ область прокрутки у таблицы — заголовок, поиск и счётчик не должны
 * уезжать вверх, пока листают тысячу строк.
 */
.rooms-body {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5) var(--space-6) var(--space-6);
}
.rooms-toolbar { display: flex; align-items: center; gap: var(--space-4); flex-wrap: wrap; flex: 0 0 auto; }
.rooms-title {
  margin: 0; flex: 1 1 auto; min-width: 0;
  display: flex; align-items: baseline; gap: var(--space-2);
  font-size: 20px; font-weight: 700;
}
.rooms-count { font-size: 13px; font-weight: 400; color: var(--text-tertiary); }
.rooms-toolbar-actions { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.rooms-code-input { width: 160px; }
.rooms-btn { width: auto; padding: 0 var(--space-4); height: 38px; white-space: nowrap; }
/* У .btn нет своего фона вовсе: в плотной строке «просто текст» не читается
   как то, на что можно нажать. */
.rooms-btn:not(.btn--primary) { background: var(--bg-input); border: 1px solid var(--border-strong); }
.rooms-btn:not(.btn--primary):hover { background: var(--bg-hover); }
.rooms-btn--sm { height: 32px; padding: 0 12px; font-size: 13px; }
.rooms-btn--go, .rooms-btn--go:not(.btn--primary) {
  background: var(--accent-soft); border-color: transparent; color: var(--accent);
}
.rooms-btn--go:not(.btn--primary):hover { background: rgba(78, 164, 245, 0.24); }
/* Отзыв ссылки стоит в том же ряду, что и «открыть»: тихим до наведения на
   него самого, чтобы разрушительное действие не выглядело как соседнее. */
.rooms-btn--danger, .rooms-btn--danger:not(.btn--primary) {
  margin-top: 0; background: transparent; border: 1px solid transparent; color: var(--danger);
}
.rooms-btn--danger:not(.btn--primary):hover { background: rgba(242, 85, 90, 0.1); border-color: var(--danger); }

.rooms-filters { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; flex: 0 0 auto; }
.rooms-search {
  flex: 0 1 340px; min-width: 180px; height: 36px;
  background: var(--bg-input);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  padding: 0 var(--space-3);
  color: var(--text-primary);
  font-size: 14px;
}
.rooms-search::placeholder { color: var(--text-tertiary); }
.rooms-search:focus { outline: none; border-color: var(--accent); }
.rooms-chips { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.rooms-chip {
  height: 28px; padding: 0 12px; border-radius: 14px;
  font-size: 12.5px; font-weight: 600; color: var(--text-secondary);
}
.rooms-chip:hover { background: var(--bg-hover); }
.rooms-chip--on { background: var(--accent-soft); color: var(--accent); }

.rooms-table {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: var(--bg-panel);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.rooms-thead, .rooms-row { display: flex; align-items: center; gap: var(--space-4); padding: 0 var(--space-4); }
.rooms-thead {
  flex: 0 0 auto;
  height: 32px;
  border-bottom: 1px solid var(--border-subtle);
  color: var(--text-tertiary);
  font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
}
.rooms-col-name { flex: 1 1 auto; min-width: 0; }
.rooms-col-code { flex: 0 0 120px; }
.rooms-col-link { flex: 0 0 104px; }
.rooms-col-access { flex: 0 0 104px; }
.rooms-col-tail { flex: 0 0 300px; }
.rooms-thead .rooms-col-tail { text-align: right; }
.rooms-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
/* Заголовок группы липкий: пролистав триста строк, человек обязан видеть, ЧТО
   он листает, — иначе «идут сейчас» и «все комнаты» различимы только по цвету
   строки. */
.rooms-group {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  height: 28px;
  padding: 0 var(--space-4);
  background: var(--bg-app);
  border-bottom: 1px solid var(--border-subtle);
  color: var(--text-secondary);
  font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
}
.rooms-group-n { color: var(--text-tertiary); }
.rooms-row {
  height: 40px;
  border-bottom: 1px solid var(--border-subtle);
  color: var(--text-secondary);
  font-size: 12.5px;
}
.rooms-row:hover, .rooms-row--open { background: var(--bg-hover); }
.rooms-row--live { background: rgba(78, 164, 245, 0.08); }
.rooms-row--live:hover { background: rgba(78, 164, 245, 0.14); }
.rooms-row-name { display: flex; align-items: center; gap: 9px; }
.rooms-row-title {
  font-size: 14px; font-weight: 600; color: var(--text-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rooms-row--dead .rooms-row-title { color: var(--text-secondary); }
.rooms-dot {
  width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto;
  background: var(--presence-online);
  box-shadow: 0 0 0 3px rgba(67, 181, 129, 0.18);
}
/* Место под точку занято ВСЕГДА: иначе названия комнат стоят на двух разных
   вертикалях — с идущей встречей и без, — и колонка перестаёт читаться
   сверху вниз. */
.rooms-dot--off { background: transparent; box-shadow: none; }
.rooms-row-code {
  font-family: var(--font-mono, ui-monospace, Consolas, monospace);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rooms-row-link { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rooms-row--dead .rooms-row-link { color: var(--danger); font-weight: 600; }
.rooms-row-access { white-space: nowrap; }
/* Кто может войти по ссылке — единственное на строке, что стоит цвета: это
   ответ на «а не пустит ли она постороннего». */
.rooms-row-access--guests { color: #f0b429; font-weight: 600; }
.rooms-row-tail { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-2); }
.rooms-row-slot { position: relative; flex: 1 1 auto; min-width: 0; display: flex; align-items: center; justify-content: flex-end; }
.rooms-row-when { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rooms-row-when--live { color: var(--presence-online); font-weight: 600; }
/* Действия занимают место «последней встречи» и появляются на наведении.
   ⚑ visibility, а не display: место под них занято всегда, поэтому строки не
   дёргаются, когда мышь идёт вниз по списку. */
.rooms-row-actions {
  position: absolute; right: 0; top: 50%; transform: translateY(-50%);
  display: flex; align-items: center; gap: 6px;
  visibility: hidden;
}
/* ⚑ Подмена «последней встречи» действиями — ТОЛЬКО там, где мышь есть. На
   тач-экране :hover срабатывает от касания и залипает: строка, по которой
   ткнули, теряла бы дату и показывала ряд кнопок, в который человек не целился.
   Там вместо ряда — одна кнопка «⋯» и лист снизу. */
@media (hover: hover) {
  .rooms-row:hover .rooms-row-when,
  .rooms-row:focus-within .rooms-row-when { visibility: hidden; }
  .rooms-row:hover .rooms-row-actions,
  .rooms-row:focus-within .rooms-row-actions { visibility: visible; }
}
/* «Войти» у идущей встречи видно ВСЕГДА и она стоит вне подменяемой ячейки:
   это единственное действие, ради которого на этот экран приходят срочно. */
.rooms-row-join { flex: 0 0 auto; }
.rooms-sentinel { height: 1px; }
.rooms-empty { color: var(--text-tertiary); font-size: 13px; padding: var(--space-4); }
.rooms-foot {
  flex: 0 0 auto;
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  height: 36px;
  padding: 0 var(--space-4);
  border-top: 1px solid var(--border-subtle);
  background: var(--bg-app);
  color: var(--text-tertiary);
  font-size: 12px;
}

/* Того, что ниже, на широком экране с мышью нет вовсе: вторая строка под
   названием, кнопка «⋯», нижняя панель. Появляются они только там, где нужны, —
   см. два медиазапроса в конце файла. */
.rooms-row-lines { min-width: 0; display: flex; flex-direction: column; justify-content: center; gap: 3px; }
.rooms-row-sub { display: none; }
.rooms-row-more { display: none; }
.rooms-bar { display: none; }

/* Нижний лист: всё, что не помещается в строку на телефоне.
   ⚑ Не confirmBox: тот спрашивает «да/нет» по центру экрана, а здесь нужен
   список действий у нижнего края, куда достаёт большой палец. */
.rooms-sheet-overlay {
  position: fixed;
  inset: 0;
  z-index: 110;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: flex-end;
  justify-content: center;
}
.rooms-sheet {
  width: min(520px, 100%);
  max-height: 80vh;
  overflow-y: auto;
  background: var(--bg-panel);
  border-top: 1px solid var(--border-strong);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  box-shadow: 0 -12px 32px rgba(0, 0, 0, 0.45);
  display: flex;
  flex-direction: column;
  /* Вырез под жест «домой» на телефоне: без этого последняя строка листа
     оказывается ровно под полосой, которой закрывают приложение. */
  padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
}
.rooms-sheet-grip { width: 36px; height: 4px; border-radius: 2px; background: var(--border-strong); margin: 8px auto 4px; }
.rooms-sheet-head {
  padding: 8px var(--space-5) 14px;
  display: flex; flex-direction: column; gap: 4px;
  border-bottom: 1px solid var(--border-subtle);
}
.rooms-sheet-title { font-size: 16px; font-weight: 700; }
.rooms-sheet-sub { font-family: var(--font-mono, ui-monospace, Consolas, monospace); font-size: 13px; color: var(--text-secondary); }
/* 56 px: строка листа — это цель для пальца, а не для курсора. */
.rooms-sheet-item {
  height: 56px;
  padding: 0 var(--space-5);
  display: flex;
  align-items: center;
  font-size: 15.5px;
  text-align: left;
  color: var(--text-primary);
}
.rooms-sheet-item:hover { background: var(--bg-hover); }
.rooms-sheet-item--go { color: var(--accent); font-weight: 600; }
.rooms-sheet-item--danger { color: var(--danger); }
.rooms-sheet-sep { height: 1px; margin: 6px var(--space-5); background: var(--border-subtle); }
.rooms-sheet-form { display: flex; gap: var(--space-2); padding: var(--space-4) var(--space-5) var(--space-2); }
.rooms-sheet-input {
  flex: 1 1 auto;
  min-width: 0;
  height: 48px;
  background: var(--bg-input);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  padding: 0 var(--space-3);
  color: var(--text-primary);
  /* 🔴 16px, а не 15: Safari на айфоне ЗУМИТ страницу на фокусе в поле с
     меньшим шрифтом, и человек проваливается в увеличенный экран, из которого
     потом выбирается руками. */
  font-size: 16px;
}
.rooms-sheet-input:focus { outline: none; border-color: var(--accent); }
.rooms-sheet-go { width: auto; flex: 0 0 auto; height: 48px; padding: 0 var(--space-5); }

/* Тач без мыши (телефон, планшет, тач-ноутбук): ряд кнопок на наведении
   недостижим, поэтому его нет, а есть «⋯». */
@media (hover: none) {
  .rooms-row-actions { display: none; }
  .rooms-row-more { display: flex; }
}

/* Телефон. Колонок нет — вместо них вторая строка под названием; заголовок с
   его кнопками уезжает вниз, под большой палец. */
@media (max-width: 760px) {
  .meet-head { height: 52px; padding: 0 16px; }
  /* Имя не нужно: кто вошёл, говорит кружок, а место на 375 px дорогое. */
  .meet-me { display: none; }
  .meet-main > .rooms-body { padding: 0; gap: 0; }

  .rooms-toolbar { display: none; }
  .rooms-filters {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
    padding: 12px 16px 10px;
    border-bottom: 1px solid var(--border-subtle);
  }
  .rooms-search { flex: 0 0 auto; max-width: none; height: 40px; font-size: 16px; }
  /* Фильтры прокручиваются вбок, а не переносятся: перенос съедает вторую
     строку экрана ради четырёх слов. */
  .rooms-chips { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  .rooms-chips::-webkit-scrollbar { display: none; }
  .rooms-chip { flex: 0 0 auto; height: 32px; padding: 0 14px; font-size: 13px; }
  .rooms-entry { padding: 12px 16px 0; }

  .rooms-table { border: none; border-radius: 0; background: transparent; }
  .rooms-thead { display: none; }
  /* Счётчик внизу — десктопная мебель: числа и так стоят в заголовках групп. */
  .rooms-foot { display: none; }
  .rooms-col-code, .rooms-col-link, .rooms-col-access { display: none; }
  .rooms-row-when { display: none; }

  .rooms-row { height: 64px; gap: 12px; padding: 0 4px 0 16px; }
  .rooms-row-title { font-size: 15.5px; }
  .rooms-row-sub {
    display: block;
    font-size: 13px;
    color: var(--text-secondary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .rooms-row-sub--live { color: var(--presence-online); font-weight: 600; }
  /* Мёртвая ссылка красная и во второй строке тоже: на широком экране это
     отдельная колонка, и терять её цвет при переходе на телефон — значит
     терять единственное, что об этой комнате нужно знать. */
  .rooms-row-sub-dead { color: var(--danger); font-weight: 600; }
  .rooms-col-tail { flex: 0 0 auto; gap: 4px; }
  .rooms-row-slot { position: static; flex: 0 0 auto; }
  .rooms-row-more { width: 44px; height: 44px; border-radius: 22px; color: var(--text-secondary); align-items: center; justify-content: center; flex: 0 0 auto; }
  .rooms-row-more .icon { width: 20px; height: 20px; }
  .rooms-row-join { height: 40px; border-radius: 20px; padding: 0 18px; font-size: 14px; }
  .rooms-history { padding: var(--space-3) 16px; }

  .rooms-bar {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: 0 0 auto;
    padding: 10px 16px calc(10px + env(safe-area-inset-bottom, 0px));
    background: var(--bg-panel);
    border-top: 1px solid var(--border-subtle);
  }
  .rooms-bar-code { width: auto; flex: 0 0 auto; height: 48px; padding: 0 18px; border-radius: 12px; background: var(--bg-input); border: 1px solid var(--border-strong); font-size: 15px; }
  .rooms-bar-new { flex: 1 1 auto; height: 48px; border-radius: 12px; font-size: 15px; }
}
.rooms-entry { flex: 0 0 auto; }
.rooms-entry-card {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4);
  border: 1px solid var(--accent);
  border-radius: var(--radius-md);
  background: var(--accent-soft);
}
.rooms-entry-main { flex: 1 1 auto; min-width: 0; }
.rooms-entry-name { font-weight: 700; font-size: 16px; }
.rooms-entry-people {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: 6px;
  color: var(--text-secondary);
  font-size: 13px;
}
.rooms-entry-empty { color: var(--text-tertiary); }
.rooms-entry-loading { color: var(--text-secondary); font-size: 13px; }
.rooms-entry-dead {
  padding: var(--space-4);
  border: 1px solid var(--danger);
  border-radius: var(--radius-md);
  color: var(--danger);
  font-size: 13.5px;
}
.rooms-stack { display: flex; }
.rooms-stack-avatar {
  width: 26px; height: 26px; font-size: 11px;
  border: 2px solid var(--bg-app);
  margin-left: -8px;
}
.rooms-stack-avatar:first-child { margin-left: 0; }
.rooms-options { display: flex; flex-direction: column; gap: var(--space-2); margin: var(--space-3) 0; }
.rooms-option {
  display: flex;
  gap: var(--space-3);
  width: 100%;
  text-align: left;
  padding: 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: transparent;
  height: auto;
}
.rooms-option--on { border-color: var(--accent); background: var(--accent-soft); }
.rooms-radio {
  width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid var(--text-tertiary);
  flex: 0 0 auto;
  margin-top: 2px;
}
.rooms-option--on .rooms-radio { border-color: var(--accent); box-shadow: inset 0 0 0 3px var(--accent); }
.rooms-option-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.rooms-option-title { font-weight: 600; font-size: 13.5px; color: var(--text-primary); }
.rooms-option-hint { color: var(--text-secondary); font-size: 12.5px; line-height: 1.45; white-space: normal; }
.rooms-form-note { color: var(--text-tertiary); font-size: 12px; line-height: 1.45; margin-bottom: var(--space-2); }
.rooms-toast {
  position: fixed;
  left: 50%;
  bottom: 28px;
  transform: translateX(-50%);
  z-index: 200;
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-panel);
  padding: 10px 16px;
  font-size: 13.5px;
}
.call-room-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--text-primary);
}
.call-lobby {
  /* Floated over the tiles rather than stacked above them, and that is a fix,
     not a preference: as a flex child it grew the overlay's column until the
     controls at the bottom — Remove among them — sat outside the viewport.
     Every computed style was correct and the button could not be clicked,
     which is the failure that looks like nothing at all. */
  position: absolute;
  top: var(--space-3);
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
  width: min(90vw, 420px);
  max-height: 40vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.call-lobby[hidden] { display: none; }
.call-lobby-card {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 10px 14px;
  border-radius: var(--radius-md);
  background: var(--bg-elevated);
  border: 1px solid #f0b429; /* the same amber the raised-hand outline uses: "needs a person" */
  box-shadow: var(--shadow-panel);
}
.call-lobby-card--in { border-color: var(--border-strong); }
.call-lobby-main { flex: 1 1 auto; min-width: 0; }
.call-lobby-name { font-weight: 600; font-size: 13.5px; }
.call-lobby-sub { color: var(--text-secondary); font-size: 12px; margin-top: 2px; }
.call-lobby-actions { display: flex; gap: var(--space-2); flex: 0 0 auto; }
.call-lobby-btn { width: auto; height: 32px; padding: 0 12px; font-size: 13px; }
.call-tile-guest {
  margin-left: 6px;
  padding: 1px 5px;
  border-radius: 4px;
  background: #f0b429;
  color: #20160a;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.02em;
}
.guest-page {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--bg-app);
  color: var(--text-primary);
}
.guest-bar {
  flex: 0 0 auto;
  height: 52px;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 0 var(--space-5);
  border-bottom: 1px solid var(--border-subtle);
  background: var(--bg-panel);
  font-weight: 700;
}
.guest-room-name { color: var(--text-secondary); font-weight: 400; }
.guest-body {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 44px;
  flex-wrap: wrap;
  padding: var(--space-6);
}
.guest-preview {
  position: relative;
  width: min(90vw, 520px);
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-md);
  background: #0a0f15;
  border: 1px solid var(--border-strong);
  overflow: hidden;
}
.guest-preview-video {
  width: 100%; height: 100%; object-fit: cover; display: block;
  /* your own camera, mirrored, as every video app does — .j-mirror (W4-15),
     the same rule as the meeting's own tile ("Flip" turns both off) */
}
.guest-preview-placeholder {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  color: var(--text-tertiary); font-size: 13px;
}
.guest-preview-placeholder[hidden] { display: none; }
.guest-preview-bar {
  position: absolute; left: 0; right: 0; bottom: 12px;
  display: flex; justify-content: center; gap: var(--space-3);
}
/* Строка про устройства над кнопками превью: «микрофон недоступен — можно
   войти слушателем» / «браузер спрашивает микрофон». Та же роль, что у
   j-prejoin-ok у сотрудника. */
.guest-preview-note {
  position: absolute; left: 12px; right: 12px; bottom: 60px;
  text-align: center; color: var(--text-secondary); font-size: 12.5px; line-height: 1.4;
  text-shadow: 0 1px 2px rgba(0,0,0,.8);
}
.guest-preview-note--warn { color: #f0b429; }
.guest-preview-note[hidden] { display: none; }
.guest-side { width: min(90vw, 340px); }
.guest-title { font-size: 22px; margin: 0 0 6px; }
.guest-sub { color: var(--text-secondary); font-size: 13.5px; margin: 0 0 20px; line-height: 1.5; }
.guest-label { display: block; color: var(--text-secondary); font-size: 12.5px; margin-bottom: 6px; }
.guest-form[hidden], .guest-waiting[hidden], .guest-dead[hidden] { display: none; }
.guest-join-btn { width: 100%; justify-content: center; height: 44px; margin-top: var(--space-3); }
.guest-note { color: var(--text-tertiary); font-size: 12px; line-height: 1.5; margin-top: var(--space-3); }
.guest-waiting {
  display: flex; align-items: center; gap: var(--space-3);
  color: var(--text-secondary); font-size: 13.5px;
}
.guest-spinner {
  width: 18px; height: 18px; flex: 0 0 auto;
  border-radius: 50%;
  border: 2px solid var(--border-strong);
  border-top-color: var(--accent);
  animation: guest-spin 0.9s linear infinite;
}
@keyframes guest-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .guest-spinner { animation: none; }
}
.guest-dead {
  padding: var(--space-4);
  border: 1px solid var(--danger);
  border-radius: var(--radius-md);
  color: var(--danger);
  font-size: 13.5px;
}
.guest-employee { margin-top: var(--space-6); color: var(--text-tertiary); font-size: 12.5px; }
.guest-employee a { color: var(--accent); }
.rooms-guests-row { display: flex; align-items: flex-start; gap: var(--space-3); margin: var(--space-3) 0 var(--space-2); }
.rooms-switch {
  width: 38px; height: 22px; flex: 0 0 auto; margin-top: 2px;
  border-radius: 11px; background: var(--border-strong);
  position: relative; padding: 0; border: none;
}
.rooms-switch-knob {
  position: absolute; top: 3px; left: 3px;
  width: 16px; height: 16px; border-radius: 50%;
  background: #8fa3b5;
  transition: left 0.12s ease, background 0.12s ease;
}
.rooms-switch--on { background: var(--accent); }
.rooms-switch--on .rooms-switch-knob { left: 19px; background: #fff; }
/* История встреч комнаты. Раскрывается СЛЕДУЮЩЕЙ строкой под своей комнатой, а
   не внутри неё: строка — это одна линия из пяти колонок, и вложенный список
   встреч растянул бы колонки всех соседей. */
.rooms-history {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border-subtle);
  background: var(--bg-app);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.rooms-history-loading { color: var(--text-secondary); font-size: 12.5px; }
.rooms-meeting {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  background: var(--bg-input);
}
.rooms-meeting-when {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: 12.5px;
  font-weight: 600;
}
.rooms-meeting-dur { color: var(--text-secondary); font-weight: 400; }
.rooms-meeting-guests {
  color: #f0b429;
  font-weight: 700;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.rooms-meeting-who {
  color: var(--text-secondary);
  font-size: 12.5px;
  /* A long roster must not stretch the card sideways. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rooms-meeting-audio { width: 100%; max-width: 420px; margin-top: 4px; }
/* Сетка лиц: 16:9, и не во всю ширину списка — это запись прошедшей встречи, а
   не сама встреча. */
.rooms-meeting-video {
  width: 100%; max-width: 420px; margin-top: 4px;
  aspect-ratio: 16 / 9; background: #000;
  border-radius: var(--radius-sm);
}
.rooms-meeting-wip { color: var(--text-secondary); font-size: 12px; }
.rooms-meeting-norec { color: var(--danger); font-size: 12px; }

/* ---------------------------------------------------------------------------
 * Оболочка meet405
 *
 * Единственное, что здесь дописано руками поверх вырезанного из chat405:
 * шапка приложения, экран входа и полоса «нет связи». Всё остальное — комнаты,
 * встреча, гостевая страница, коробка подтверждения, пикер экрана — приехало
 * со своими стилями и не трогалось.
 * ------------------------------------------------------------------------- */

.meet-body {
  margin: 0;
  background: var(--bg-app);
  color: var(--text-primary);
  font-family: var(--font-sans);
}

/* Высота ОКНА, а не «не меньше окна»: список комнат прокручивается внутри
   себя, и чтобы у него была своя область прокрутки, у оболочки должна быть
   конечная высота. */
.meet-app {
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.meet-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 20px;
  height: 56px;
  background: var(--bg-sidebar);
  border-bottom: 1px solid var(--border-subtle);
  flex: 0 0 auto;
}

.meet-brand {
  font-size: 17px;
  font-weight: 600;
  letter-spacing: 0.2px;
  color: var(--text-primary);
}

.meet-head-spacer { flex: 1 1 auto; }

.meet-me {
  font-size: 14px;
  color: var(--text-secondary);
  max-width: 240px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 🔴 width: auto ОБЯЗАТЕЛЕН. У .btn ширина 100% — она нужна кнопке в форме и
   разрушительна в шапке: кнопка «Выйти» получала базой всю ширину строки,
   ужималась флексом до середины и стояла посреди пустой шапки, а имя человека
   при этом обрезалось до «Mat…». Ровно это и было видно на проде. */
.meet-signout, .meet-upgrade { width: auto; flex: 0 0 auto; }
.meet-signout { padding: 6px 14px; font-size: 13px; }

/* Кто вошёл: кружок с инициалами и имя. Тот же кружок, что в ростере встречи, —
   один человек выглядит одинаково везде, где он назван. */
.meet-who { display: flex; align-items: center; gap: 9px; min-width: 0; flex: 0 1 auto; }
.meet-avatar { width: 28px; height: 28px; font-size: 11px; }

/* Прокручивается не главная область, а таблица внутри неё: заголовок, поиск и
   счётчик обязаны стоять на месте, пока листают тысячу строк. */
.meet-main {
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
  display: flex;
  justify-content: center;
}

/* Предел ширины: пять колонок, растянутые на 27 дюймов, читаются хуже, а не
   лучше — глазу нечем связать имя комнаты с её последней встречей. */
.meet-main > .rooms-body { width: 100%; max-width: 1200px; }

/* Вход. Одна кнопка — пароля у этого приложения нет вовсе. */
.meet-login {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.meet-login-card {
  width: min(360px, 100%);
  text-align: center;
  background: var(--bg-panel);
  border: 1px solid var(--border-subtle);
  border-radius: 14px;
  padding: 36px 28px;
}

.meet-login-card .meet-brand { font-size: 24px; display: block; margin-bottom: 6px; }

.meet-login-sub {
  margin: 0 0 24px;
  color: var(--text-secondary);
  font-size: 14px;
}

.meet-login-btn {
  display: inline-block;
  text-decoration: none;
  padding: 10px 22px;
}

/* Причина неудачного входа. Красным и словами: молча показанная кнопка «Войти»
   после отказа — это круг, в котором человек жмёт одно и то же. */
.meet-login-note {
  margin: 18px 0 0;
  font-size: 13px;
  color: #e8737a;
  line-height: 1.45;
}

.meet-offline {
  position: fixed;
  left: 50%;
  bottom: 18px;
  transform: translateX(-50%);
  z-index: 60;
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong);
  color: var(--text-primary);
  border-radius: 999px;
  padding: 8px 18px;
  font-size: 13px;
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.45);
}

/* Быстрое создание встречи без входа (26.08.2026). Второй путь на экране входа,
   и он СВЕРХУ: это то, зачем сюда чаще всего приходят. */
.meet-quick {
  display: flex;
  flex-direction: column;
  gap: 10px;
  text-align: left;
}

.meet-quick-label {
  font-size: 12px;
  color: var(--text-secondary);
}

.meet-quick-hint {
  margin: 0;
  font-size: 12px;
  color: var(--text-tertiary);
  text-align: center;
}

/* Разделитель «or»: линия, разорванная словом. Без него две кнопки подряд
   читаются как «одна из них главная, а вторая непонятно зачем». */
.meet-or {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 18px 0 14px;
  color: var(--text-tertiary);
  font-size: 12px;
}

.meet-or::before,
.meet-or::after {
  content: '';
  flex: 1 1 auto;
  height: 1px;
  background: var(--border-strong);
}

.meet-upgrade { padding: 6px 14px; font-size: 13px; text-decoration: none; }

/* Выбор устройств во встрече (27.08.2026).
 *
 * Борис на первой живой встрече: «не хватает возможности выбрать источник
 * звука, видео». Панель всплывает НАД строкой кнопок и внутри оверлея — не
 * отдельным экраном: её открывают ровно тогда, когда идёт разговор, и уходить
 * из него ради настроек нельзя. */
.call-devices {
  position: absolute;
  left: 50%;
  bottom: 92px;
  transform: translateX(-50%);
  /* Над стопкой уведомлений (80, во время встречи она в оверлее). */
  z-index: 90;
  min-width: 260px;
  max-width: min(360px, 90vw);
  /* Устройств может быть много — список скроллится сам, а не растёт за экран. */
  max-height: min(60vh, 420px);
  overflow-y: auto;
  padding: 8px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong);
  border-radius: 12px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.55);
}

.call-devices-label {
  padding: 10px 10px 4px;
  font-size: 11px;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.call-devices-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 10px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--text-primary);
  font: inherit;
  font-size: 13px;
  text-align: left;
  cursor: pointer;
  /* Длинное имя устройства («Микрофон (Realtek(R) Audio)») не должно ломать
     ширину панели: оно переносится, а не растягивает список. */
  overflow-wrap: anywhere;
}

.call-devices-item:hover { background: var(--bg-hover); }
.call-devices-item--on { color: var(--accent); }

/* Галочка занимает своё место ВСЕГДА, даже когда её нет: иначе выбранная
   строка прыгает вбок относительно остальных. */
.call-devices-check {
  flex: 0 0 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.call-devices-check .icon { width: 14px; height: 14px; }

/* ---- меню звука как в Jitsi (29.09.2026): шкала у микрофона, «Test» у динамика ---- */
.call-devices-name { flex: 1 1 auto; min-width: 0; }
.call-devices-meter {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: flex-end;
  gap: 2px;
  height: 14px;
  margin-left: 8px;
}
.call-devices-meter i {
  width: 3px;
  border-radius: 1px;
  background: rgba(255, 255, 255, 0.18);
}
.call-devices-meter i.on { background: #31B76A; }
.call-devices-row { display: flex; align-items: center; gap: 4px; }
.call-devices-row .call-devices-item { flex: 1 1 auto; min-width: 0; }
.call-devices-test {
  flex: 0 0 auto;
  margin-right: 6px;
  padding: 4px 10px;
  border: 0;
  border-radius: 6px;
  background: var(--bg-active);
  color: #fff;
  font: inherit;
  font-size: 12px;
  cursor: pointer;
}
.call-devices-test:hover { background: var(--accent-strong); }
/* Как в Jitsi: «Test» появляется при наведении на строку динамика (и с
   клавиатуры); на сенсорных экранах наведения нет — там виден всегда. */
@media (hover: hover) {
  .call-devices-row .call-devices-test { opacity: 0; transition: opacity .12s; }
  .call-devices-row:hover .call-devices-test,
  .call-devices-row:focus-within .call-devices-test { opacity: 1; }
}

/* ---- уведомления как в Jitsi (30.09.2026) ----
   Стопка в левом нижнем углу над кнопками (по центру снизу она ложилась на
   микрофон и «выйти»): заголовок, описание, действия, крестик. Цветная полоса
   слева — тип, как у Jitsi (normal — синяя, warning — жёлтая). */
.call-notices {
  position: fixed;
  left: 20px;
  bottom: 96px;
  z-index: 80;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: min(400px, calc(100vw - 40px));
  pointer-events: none;
}
.call-notice {
  pointer-events: auto;
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 12px 12px 12px 14px;
  border-radius: 6px;
  border-left: 4px solid #4687ED;
  background: #1f2a38;
  color: #fff;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
  font-size: 14px;
  line-height: 1.4;
}
.call-notice--warning { border-left-color: #F8AE1A; }
.call-notice-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.call-notice-title { font-weight: 600; overflow-wrap: anywhere; }
.call-notice-desc { color: #C2C2C2; font-size: 13px; overflow-wrap: anywhere; }
.call-notice-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 4px; }
.call-notice-btn {
  padding: 0;
  border: 0;
  background: transparent;
  color: #6ea2ff;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
.call-notice-btn:hover, .call-notice-btn:focus-visible { text-decoration: underline; }
.call-notice-close {
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: #C2C2C2;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
}
.call-notice-close:hover { background: rgba(255, 255, 255, 0.08); color: #fff; }

/* 🔴 Плитки не смеют накрывать кнопки.
 *
 * Найдено тестом 27.08.2026: у .call-tile aspect-ratio 4/3, а ширина приходит
 * от сетки (min(92vw, 960px)) — значит ВЫСОТА выводится из ширины и на неё
 * ничто не смотрит. Один участник = плитка 960×720, две строки = 1440, и всё
 * это рисуется поверх строки кнопок: до микрофона, камеры и «выйти» физически
 * не дотянуться.
 *
 * ⚑ Приехало из chat405, где групповой звонок в одиночестве длился секунду и
 * никто не замечал. Здесь ПЕРВЫЙ вошедший в комнату всегда один — и часто ждёт,
 * пока постучатся, — поэтому случай стал обычным, а не краевым.
 *
 * С W4-18 потолков по data-count нет: размер плитки считает tileGrid Jitsi от
 * высоты окна (call-layout.js), ряды влезают по построению, а тулбар лежит
 * ПОВЕРХ сетки (z-index 20), как у Jitsi, — кнопки досягаемы при любой форме
 * (rooms.pw: «в центре кнопки — сама кнопка»). */
.call-grid { max-height: 100%; align-content: center; }
.call-tile { min-height: 0; }

/* Когда кто-то показывает экран, сетка уже сжата до 22vh полосой выше —
   собственный потолок плиток здесь только мешал бы. */
.call-share-stage:not([hidden]) ~ .call-grid .call-tile { max-height: 100%; }

/* ============================================================================
 * СКИН JITSI — 100% сходство (Борис, 27.08.2026: «нужно 100% сходство»).
 *
 * Каждое значение ниже СНЯТО, а не придумано: с живого alpha.jitsi.net
 * (текущий master, computed styles) и meet.jit.si, плюс токены из
 * jitsi/jitsi-meet tokens.json. Рядом с правилом — откуда оно.
 *
 * ⚑ Секция идёт ПОСЛЕ старых правил и побеждает каскадом при той же
 * специфичности. Иконки — фирменные SVG Jitsi (Apache-2.0), заливка, не линия.
 * ========================================================================== */

.call-overlay {
  background: #040404;                 /* largeVideoBg, замер */
  color: #F1F1F1;                      /* базовый текст Jitsi — НЕ чистый белый */
  justify-content: flex-start;
  gap: 0;
}

/* Иконки-заливка: у .icon больше нет обводки. fill сидит на самом символе. */
.icon { stroke: none; fill: currentColor; }

/* ---- тулбар: контейнер #141414, r6, p6, двойная тень; снизу 16px ---- */
.call-actions {
  position: absolute;
  left: 50%; bottom: 16px; transform: translateX(-50%);
  margin: 0;
  background: #141414;
  border-radius: 6px;
  padding: 6px;
  gap: 0;                              /* кнопки впритык, как в замере */
  box-shadow: rgba(0,0,0,.25) 0 2px 8px 4px, rgba(0,0,0,.15) 0 0 0 1px;
  z-index: 20;
}
.call-btn {
  width: 48px; height: 48px;
  border-radius: 3px;                  /* замер: кнопки r3, контейнер r6 */
  background: transparent;
  color: #fff;
}
.call-btn:hover { background: #3D3D3D; }        /* hover05 */
.call-btn .icon { width: 24px; height: 24px; }  /* замер: svg 24×24 */
.call-btn--off { background: transparent; color: #fff; }
.call-btn--on  { background: #525252; color: #fff; }   /* toggled: surface05 */
.call-btn--end {
  background: #CB2233;                 /* замер hangup */
  border-radius: 3px; width: 48px; height: 48px;
  margin-left: 0;
}
/* Выход — как css/_toolbars.scss:106-122 Jitsi: hover #E04757, нажатие #A21B29. */
.call-btn--end:hover { background: #E04757; }
.call-btn--end:active { background: #A21B29; }

/* Пара иконок в одной кнопке: вкл/выкл переключается классом, не перерисовкой. */
.call-btn .icon--on  { display: block; }
.call-btn .icon--off { display: none; }
.call-btn--off .icon--on  { display: none; }
.call-btn--off .icon--off { display: block; }

/* Шеврон над кнопкой — как в Jitsi: маленький ^ у верхней кромки тулбара. */
.t-wrap { position: relative; }
.t-chev {
  position: absolute; top: -10px; right: 2px;
  width: 20px; height: 16px; border: 0; border-radius: 3px;
  background: #141414; color: #fff;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; padding: 0;
}
.t-chev:hover { background: #3D3D3D; }
.t-chev .icon { width: 12px; height: 12px; }
.t-chev--open { background: #525252; }

/* Счётчик участников: белый кружок с тёмной цифрой, как в замере. */
.t-count {
  position: absolute; top: -8px; right: 2px;
  min-width: 16px; height: 16px; border-radius: 8px; padding: 0 4px;
  background: #fff; color: #040404;
  font-size: 11px; font-weight: 600; line-height: 16px; text-align: center;
}

/* ---- имя комнаты + таймер сверху по центру (замер: y=20, h=28) ---- */
.j-subject {
  position: absolute; top: 20px; left: 50%; transform: translateX(-50%);
  display: flex; align-items: stretch; height: 28px;
  border-radius: 3px; overflow: hidden; z-index: 15;
  font-size: 14px;
  /* С W4-18 сетка во всю высоту, и шапка лежит поверх верхних плиток (как у
     Jitsi) — над «⋯» плитки, стоящей у центра. Тема и таймер — надписи: мышь
     сквозь них, к плитке; ловят только кнопки (счётчик рук, число участников).
     У Jitsi шапка ловит мышь целиком (отступление: нажать там всё равно нечего). */
  pointer-events: none;
}
.j-subject button { pointer-events: auto; }
.j-subject-name {
  background: rgba(0,0,0,.6); color: #fff;
  display: flex; align-items: center; padding: 0 12px;
  max-width: 40vw; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.j-subject-timer {
  background: #000; color: #fff;
  display: flex; align-items: center; padding: 0 8px;
  font-size: 12px; font-variant-numeric: tabular-nums;
}
/* ---- сцена (вид «говорящий») + правая плёнка миниатюр ----
   Плёнка 140 px (замер) = 120 + 11 + 9 ручки (getVerticalViewMaxWidth Jitsi);
   с W4-17 её тянут мышью — ширина на экране в --strip-outer (group-call.js
   paintGeometry). Сцена ей уступает при любой ширине: у Jitsi до 180 плёнка
   лежит поверх сцены, а раздвигает с 180 (LargeVideo.web.tsx:279, 333), —
   у нас сцена кончается у плёнки всегда, как было по замеру (отступление). */
.j-stage {
  position: absolute; inset: 0; right: var(--strip-outer, 140px);
  display: flex; align-items: center; justify-content: center;
}
.j-stage video { width: 100%; height: 100%; object-fit: contain; display: block; }
/* Экран на сцене — на ВСЮ сцену, как у Jitsi (computeDesktopVideoSize:
   contain в пределах большого видео). Потолок 52vh у .call-share-video остался
   от старой полосы шары над сеткой: на сцене он сжимал экран в окошко по
   центру с чёрными полями вокруг (жалоба 02.10.2026). */
.j-stage .call-share-video,
.call-overlay:fullscreen .j-stage .call-share-video { max-height: none; }
/* Камера на сцене вписана как у Jitsi (W5-21, VIDEO_LAYOUT_FIT 'both', потолок
   обрезки 1,3): ширину и высоту в px ставит fitStage (group-call.js), лишнее
   уходит за край сцены. Шара остаётся contain. */
.j-stage { overflow: hidden; }
.j-stage video.j-stage-fit { flex: none; max-width: none; position: relative; }
/* Экран двумя копиями (13.10.2026): дешёвая копия — ПОД полной, на всю сцену;
   полная — над ней (position: relative ставит её в тот же слой, порядок — по
   DOM, копия раньше) и прозрачна, пока у неё нет кадра (j-stage-wait).
   srcObject у полной не меняется — без мелькания чёрного на пересадке. */
.j-stage video.j-stage-low { position: absolute; inset: 0; }
.j-stage video.call-share-video:not(.j-stage-low) { position: relative; }
.j-stage video.j-stage-wait { opacity: 0; }
/* Размытая подложка полей (LargeVideoBackground Jitsi): холст 300×150 без
   атрибутов размера, растянутый на сцену, под blur(40px). Под видео: стоит
   первой в сцене, а вписанное видео — position: relative. */
.j-stage-bg { position: absolute; inset: 0; overflow: hidden; filter: blur(40px); pointer-events: none; }
.j-stage-bg[hidden] { display: none; }
.j-stage-bg canvas { display: block; min-width: 100%; min-height: 100%; }
/* Доска (волна 6, WB3): редактор на всю сцену, светлый — как у Jitsi. */
/* Сверху — место под шапку встречи (имя комнаты, таймер): иначе она ложится
   на панель инструментов редактора. */
.j-whiteboard { position: absolute; inset: 56px var(--strip-outer, 140px) 0 0; background: #fff; color: #040404; }
/* Сцена идёт под плёнкой (как у Jitsi), а у редактора справа свои кнопки
   (библиотека, справка) — доска кончается у плёнки; плёнка спрятана — до края. */
.call-overlay--nostrip .j-whiteboard { right: 0; }
.j-stage-item[data-item="whiteboard"] { background: #fff; }
.j-whiteboard-note { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; padding: 16px; text-align: center; font-size: 14px; line-height: 20px; color: #525252; }
.j-whiteboard-note--error { color: #CB2233; }
.j-whiteboard-dialog-text { margin: 0; font-size: 14px; line-height: 20px; }
/* Общее видео (волна 6, SV2): плеер на всю сцену; у зрителя плеер YouTube
   не нажимается — управляет владелец (controls=0 и pointer-events). */
.j-shared-video { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; background: #000; }
.j-shared-video-el, .j-shared-video iframe { width: 100%; height: 100%; border: 0; display: block; }
.j-shared-video video { object-fit: contain; }
.j-shared-video--youtube:not(.j-shared-video--owner) iframe { pointer-events: none; }
.j-shared-video-field { display: flex; flex-direction: column; gap: 8px; }
.j-shared-video-label { font-size: 14px; line-height: 20px; color: #fff; }
.j-shared-video-dialog .call-dialog-input { width: 100%; box-sizing: border-box; }
.j-shared-video-error { margin-top: 8px; font-size: 12px; line-height: 16px; color: #E04757; }
.j-shared-video-error[hidden] { display: none; }
/* Псевдоучастники сцены (волна 6, ST1): доска и общее видео. Контейнер на
   всю сцену — содержимое ставит модуль; плитка в плёнке — как миниатюра. */
.j-stage-item { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; background: #040404; }
.j-stage-item[hidden] { display: none; }
.j-item-tile { cursor: pointer; background: #292929; }
.j-filmstrip .j-item-tile {
  width: var(--strip-tile-w, 122px); height: var(--strip-tile-h, 71px); flex: 0 0 var(--strip-tile-h, 71px);
  border-radius: 4px;
}
.call-overlay--strip-grid .j-filmstrip .j-item-tile { flex: 0 0 auto; margin: 2px; }
.j-item-tile-thumb { width: 100%; height: 100%; object-fit: cover; display: block; }
.j-item-tile-thumb[hidden], .j-item-tile-card[hidden] { display: none; }
.j-item-tile-card { display: flex; align-items: center; justify-content: center; color: #C2C2C2; }
.j-item-tile-card .icon { width: 24px; height: 24px; }
.j-filmstrip .j-item-tile .call-tile-name { left: 50%; transform: translateX(-50%); bottom: 4px; }
.j-item-tile:hover { background: #3D3D3D; }
.j-item-tile:focus-visible { outline: 0; box-shadow: inset 0 0 0 2px #D7E3F9; }
.j-item-tile.call-tile--pinned { box-shadow: inset 0 0 0 2px #4687ED; }
/* Сцена из нескольких (W5-23, «Pin to stage» до шести): сетка плиток 16:9 в
   пределах сцены — размер плитки и ширину сетки считает layoutStageGrid
   (call-stage.js stageGridLayout), здесь — только перенос строк и вид плитки. */
.j-stage-grid {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center; align-content: center;
  gap: 8px; padding: 8px; box-sizing: border-box; width: 100%; height: 100%;
}
.j-stage-grid[hidden] { display: none; }
.j-stage-tile {
  position: relative; flex: none; width: var(--stage-tile-w, 320px); height: var(--stage-tile-h, 180px);
  background: #292929; border-radius: 6px; overflow: hidden; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.j-stage .j-stage-tile video { width: 100%; height: 100%; object-fit: cover; }
.j-stage-tile video[hidden], .j-stage-tile .avatar[hidden] { display: none; }
.j-stage-tile-avatar { width: 96px; height: 96px; border-radius: 50%; font-size: 36px; }
.j-stage-tile-name { left: 8px; bottom: 8px; }
.j-stage-tile--pinned { box-shadow: inset 0 0 0 2px #4687ED; }
.j-stage .avatar--stage {
  width: 200px; height: 200px; border-radius: 50%;   /* замер: аватар 200 */
  font-size: 64px;
}
/* «Видео прервано» на сцене и в плитке сцены-сетки (12.10.2026) — подпись под
   аватаром (общий вид — у .call-tile-stalled выше). Плитка сетки бывает
   180 px: аватар 96 чуть выше центра, иначе подпись ложится на имя. */
.j-stage-tile--stalled .j-stage-tile-avatar { transform: translateY(-14px); }
.j-stage-tile-stalled { top: calc(50% + 40px); }
.j-stage-stalled { top: calc(50% + 112px); font-size: 14px; line-height: 20px; padding: 2px 12px; }
.j-stage-tile-stalled[hidden], .j-stage-stalled[hidden] { display: none; }
/* Поток на застое элемент НЕ отпускает (ревью 12.10.2026): первый новый кадр
   сразу в нём, и после снятия флага сцена не чёрная до следующего кадра. Видео
   прозрачно, как у плитки (call-tile--novideo), и вне вёрстки: сцена и плитка
   сетки — flex по центру, иначе видео 100% ширины сдвинуло бы аватар.
   opacity, а не display:none — невидимое muted-autoplay видео Chrome ставит
   на паузу. Мышь сквозь: двойной клик по аватару сцену не разворачивал и до. */
.j-stage.j-stage--stalled video.call-stage-video,
.j-stage-tile--stalled video.j-stage-tile-video {
  position: absolute; inset: 0; opacity: 0; pointer-events: none;
}
/* Плашка имени на сцене (W4-11) — StageParticipantNameLabel + DisplayNameBadge
   Jitsi: по центру внизу, над тулбаром — bottom 88 px при видимом тулбаре,
   40 при спрятанном (getVideospaceFloatingElementsBottomSpacing: spacing(12)
   и spacing(6) по шкале [0,4,8,16,…,88] — не 96/48, критика §2.1); 12 px над
   нашим тулбаром (16 + 48 + 2×6). rgba(0,0,0,.6), r3, max-width 50%, отступ
   2px 16px; шрифт — от высоты окна, как scaleFontProperty: 10 px при ≤300,
   16 px при ≥960 (строка 16→22), линейно между. Мышь сквозь: под плашкой
   видео сцены (двойной клик — полный экран). */
.j-stage-name {
  position: absolute; left: 50%; bottom: 88px; transform: translateX(-50%);
  max-width: 50%; box-sizing: border-box;
  background: rgba(0,0,0,.6); color: #fff; border-radius: 3px;
  padding: 2px 16px;
  font-size: clamp(10px, calc(10px + (100vh - 300px) * 6 / 660), 16px);
  line-height: clamp(16px, calc(16px + (100vh - 300px) * 6 / 660), 22px);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  pointer-events: none; z-index: 1;
  /* Над тулбаром: при показе — 0.15s с задержкой 0.15s, при скрытии — 0.24s
     сразу (getTransitionParamsForElementsAboveToolbox Jitsi). */
  transition: bottom .15s ease-in .15s, opacity .3s ease-in;
}
.j-stage-name[hidden] { display: none; }
/* Крючок автоскрытия тулбара (W4-12 поставит класс на оверлей): плашка
   опускается к 40 px, плашка ШАРЫ гаснет — её Jitsi показывает, только пока
   виден тулбар. */
.call-overlay--toolbar-hidden .j-stage-name { bottom: 40px; transition: bottom .24s ease-in, opacity .24s ease-in; }
.call-overlay--toolbar-hidden .j-stage-name--share { opacity: 0; }

/* ---- автоскрытие тулбара и шапки (W4-12) ----
   Класс ставит group-call.js (setToolbarVisible) через 4000 мс покоя, как
   у Jitsi. Тулбар: .new-toolbox Jitsi уезжает вниз на 96 px (bottom: −2×48,
   transition bottom .3s ease-in, css/_toolbars.scss). У нас — transform (только
   композитор, без раскладки на каждом кадре — RDP) и не меньше своей высоты +
   16 px отступа: на ≤500 px (заплатка W4-0) кнопки в два ряда, и 96 px их не
   убрали бы. Кнопки в фокусе остаются (Tab в спрятанный тулбар его покажет).
   Сетка плиток (inset 60/90) этим классом не трогается — плитки не меняют
   размер, подписки те же (§1.7 п.3). В экономии переходов нет: «ни одного
   перехода в оверлее» из секции экономии ниже по файлу побеждает каскадом. */
.call-overlay .call-actions { transition: transform .3s ease-in; }
.call-overlay--toolbar-hidden .call-actions { transform: translate(-50%, max(96px, calc(100% + 16px))); }
/* Шапка — ConferenceInfo Jitsi: блок autoHide (тема, таймер, число
   участников) гаснет (.subject: opacity .6s ease-in-out) и схлопывается
   (hideSubject / showSubject: max-width за .6s ease-out — так при видимом
   счётчике рук тот встаёт по центру); счётчик рук (alwaysVisible) остаётся.
   Спрятанный блок не ловит мышь: кнопка числа участников под ним — не цель. */
.j-subject-auto {
  display: flex; align-items: stretch; overflow: hidden;
  max-width: 100vw; opacity: 1;
  transition: opacity .6s ease-in-out, max-width .6s ease-out;
}
.call-overlay--toolbar-hidden .j-subject-auto { opacity: 0; max-width: 0; pointer-events: none; }
.call-overlay--toolbar-hidden .j-subject-auto button { pointer-events: none; }
/* Режим 1-на-1 (W4-12, .hide-videos Jitsi — opacity 0 у .remote-videos): вдвоём
   при спрятанном тулбаре чужая миниатюра в плёнке не видна — собеседник на
   сцене. Узел и его <video> остаются (ширина та же, подписка та же). */
.j-filmstrip--hide-videos .call-tile:not(.call-tile--self) { visibility: hidden; }
/* Плёнка — ОКНО из шести миниатюр (плюс своя), не прокрутка (план C4):
   overflow-y:auto держал бы в DOM полсотни <video>, а прокрученные за край
   всё равно декодируют. Листается ▲▼ пейджером под ней (.j-pager--strip),
   снизу под него оставлено место. С W4-17 ширину тянут мышью (ручка у левой
   кромки): ширина на экране — --strip-outer (120 → 140), слева поле под
   ручку (--strip-handle: 9, на сенсорном 21), миниатюра — --strip-tile-w/h
   (122×71 при 120, шире — в той же пропорции). Сколько миниатюр на странице —
   сколько ВИДНО по высоте (stripLayout): срезанная по краю не принимается. */
.j-filmstrip {
  position: absolute; top: 0; right: 0; bottom: 72px; width: var(--strip-outer, 140px);
  display: flex; flex-direction: column; align-items: center;
  padding: 9px 9px 9px var(--strip-handle, 9px); gap: 8px; overflow: hidden; z-index: 10;
}
/* Миниатюра: 122×71, r4 — замер. Переиспользует .call-tile, чтобы тесты и
   подсветки работали в обоих видах без второго набора классов. */
.j-filmstrip .call-tile {
  width: var(--strip-tile-w, 122px); height: var(--strip-tile-h, 71px); flex: 0 0 var(--strip-tile-h, 71px);
  aspect-ratio: auto; max-height: none;
  border-radius: 4px;
}
.j-filmstrip .call-tile-name {
  left: 50%; transform: translateX(-50%); bottom: 4px;
  font-size: 12px; font-weight: 600; padding: 0 6px;
  max-width: calc(var(--strip-tile-w, 122px) - 8px); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.j-filmstrip .call-tile-avatar { width: 40px; height: 40px; font-size: 15px; }
/* Шире 300 — миниатюры сеткой в несколько колонок (FILMSTRIP_GRID_BREAKPOINT,
   showGridInVerticalView Jitsi): форма — tileGrid от ширины плёнки, поля 2 px
   у каждой миниатюры (TILE_*_MARGIN 4), справа — без поля и без +11 (как
   у Jitsi: в сетке плёнка = ширина + ручка). */
.call-overlay--strip-grid .j-filmstrip {
  flex-direction: row; flex-wrap: wrap; align-content: flex-start; align-items: flex-start; justify-content: center;
  gap: 0; padding: 7px 0 7px var(--strip-handle, 9px);
}
.call-overlay--strip-grid .j-filmstrip .call-tile { flex: 0 0 auto; margin: 2px; }
/* Ручка ширины плёнки (W4-17) — dragHandleContainer + dragHandle Jitsi
   (Filmstrip.tsx:220-266): полоса во всю высоту у левой кромки, курсор
   col-resize, внутри — черта 3×100, r1, #C2C2C2 (icon02), под мышью и пока
   тянут — белая (icon01). Видна при наведении на плёнку и пока тянут; на
   сенсорном экране — всегда (и шире на 6 с каждой стороны). Спрятанная
   (visibility) мышь не ловит. touch-action: none — палец тянет ручку, а не
   страницу. */
.j-strip-resize {
  position: absolute; top: 0; bottom: 0; left: 0; width: var(--strip-handle, 9px);
  display: flex; align-items: center; justify-content: center;
  cursor: col-resize; touch-action: none; visibility: hidden; z-index: 12;
}
.j-strip-resize[hidden] { display: none; }
.j-drag-handle { width: 3px; height: 100px; border-radius: 1px; background: #C2C2C2; flex: none; }
.j-filmstrip:is(:hover, :focus-within) .j-strip-resize,
.j-strip-resize.j-resize--active { visibility: visible; }
.j-strip-resize:hover .j-drag-handle,
.j-resize--active .j-drag-handle { background: #fff; }
/* Стрелка «Toggle filmstrip» (W4-13) — Filmstrip.tsx Jitsi:93-135: 32×24, r4,
   rgba(51,51,51,.5), повёрнута на −90° (вертикальная плёнка), у левой кромки
   плёнки по центру её высоты: left = кромка − 30 px, то есть right = ширина
   плёнки − 2 (после поворота видимая коробка 24×32 стоит в 2 px от кромки).
   Видна при наведении на плёнку и на себя (opacity .3s), при фокусе с
   клавиатуры и всегда — при спрятанной плёнке; тогда она у правого края окна. */
.j-strip-toggle {
  position: absolute; right: calc(var(--strip-outer, 140px) - 2px); top: calc((100% - 72px) / 2 - 12px);
  width: 32px; height: 24px; padding: 0; border: 0; border-radius: 4px;
  background: rgba(51,51,51,.5); color: #fff; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transform: rotate(-90deg); opacity: 0; transition: opacity .3s; z-index: 11;
}
.j-strip-toggle .icon { width: 24px; height: 24px; }
.j-strip-toggle:hover, .j-strip-toggle:focus-visible { background: #292929; }
.j-filmstrip:hover + .j-strip-toggle,
.j-strip-toggle:hover, .j-strip-toggle:focus-visible,
.call-overlay--nostrip .j-strip-toggle { opacity: 1; }
/* Плёнка спрятана: миниатюр нет (group-call.js их снимает — не нарисовано,
   не подписано), сцена на всю ширину, стрелка у правого края. */
.call-overlay--nostrip .j-filmstrip { display: none; }
.call-overlay--nostrip .j-stage { right: 0; }
.call-overlay--nostrip .j-strip-toggle { right: -2px; }
.call-overlay--tiles .j-strip-toggle { display: none; }
/* В виде «плиткой» сцена и плёнка уходят, сетка остаётся прежней. */
.call-overlay--tiles .j-stage,
.call-overlay--tiles .j-filmstrip { display: none; }
.call-overlay:not(.call-overlay--tiles) .call-grid { display: none; }
/* Сетка «плитка» (W4-18) — форма Jitsi (tileGrid, call-layout.js): вся
   высота оверлея (tileGrid сам вычитает 14 — по 7 сверху и снизу), ширина —
   область видео без чата и панели; блок плиток шириной ровно колонки × (плитка
   + 4) — --grid-w — стоит по центру (left/right + width + margin auto), ряды
   — по центру по высоте. Тулбар и шапка — ПОВЕРХ сетки, как у Jitsi
   (критика §3.3, вариант А): отступы 60/90 волны 1 ушли, автоскрытие тулбара
   сетку по-прежнему не двигает. */
.call-overlay--tiles .call-grid {
  position: absolute; top: 0; bottom: 0; left: 0; right: 0;
  width: var(--grid-w, auto); max-width: none; margin: 0 auto;
  display: flex; flex-wrap: wrap; align-content: center; justify-content: center;
  gap: 0; padding: 0;
}
/* Лента вместо страниц (08.10.2026, вариант A — как у Jitsi): все плитки в
   сетке, лишние ряды — прокруткой. Ряды не влезают — справа тонкая полоса
   (ширину выбирает браузер — Chromium 10–11 px, Firefox 8, macOS 0; её меряет
   paintGeometry: --grid-sb), слева — поле той же ширины (--grid-pad, меньше,
   если не влезает): колонки встают ровно в --grid-w и не переносятся.
   Влезают — оба 0, сетка как была. safe center: ряды влезают — по центру, не
   влезают — от верха, а не срезанные сверху. */
.call-overlay--tiles .call-grid {
  box-sizing: border-box;
  width: calc(var(--grid-w, 960px) + var(--grid-sb, 0px) + var(--grid-pad, 0px));
  padding-left: var(--grid-pad, 0px);
  overflow-x: hidden; overflow-y: auto;
  scrollbar-color: rgba(255, 255, 255, .3) transparent;
  overscroll-behavior: contain;
  align-content: safe center;
}
/* Сетка уступает и панели участников (videoSpaceWidth Jitsi вычитает её). */
.call-overlay--pane.call-overlay--tiles .call-grid { right: 315px; }
/* Плитка — размер формы Jitsi (--tile-w × --tile-h: от 16:9 до 1/1.3, видео
   режется cover — Д3), поля по 2 px (TILE_*_MARGIN 4). Своя шара плиткой
   (.j-screen-tile, W4-9) — плитка той же сетки и того же размера. Размеры
   явные — contain: strict экономии (ниже) им не мешает. */
.call-overlay--tiles .call-grid :is(.call-tile, .j-screen-tile) {
  width: var(--tile-w, 320px); height: var(--tile-h, 180px); margin: 2px;
  aspect-ratio: auto; max-height: none; flex: 0 0 auto;
}
/* Неполный последний ряд — по центру и шире, до 16:9 от высоты
   (ThumbnailWrapper.tsx Jitsi:189-210). Класс ставит paintGeometry. */
.call-overlay--tiles .call-grid .j-lastrow { width: var(--tile-w-last, var(--tile-w, 320px)); }

/* ---- пейджер плиток: «‹ 1/6 ›  +41 in the list» (план C4) ----
   В сетке — слева внизу, на уровне тулбара (с чатом — от его правой кромки).
   У Jitsi пейджера нет вовсе (прокрутка) — место наше (Д2 B). Справа
   (первый вариант W4-18) он уходил под тулбар уже на 1024 с панелью
   участников и на 1366 с чатом и панелью (проверка 4b2, находка 1): тулбар
   стоит по центру места под видео, z 20 — над пейджером. Слева тулбар его
   тоже накрывает — на узком окне (<960), с панелью на 1024–1280, с чатом и
   панелью на 1366: тогда group-call.js (placePager) поднимает его над
   тулбаром (.j-pager--lifted, --pager-lift на body — от высоты тулбара), а
   стопку уведомлений — над ним. Решает геометрия, а не видимость тулбара:
   спрятанный тулбар возвращает любое движение мыши к пейджеру. */
.j-pager {
  position: absolute; bottom: 24px; left: 20px;
  display: flex; align-items: center; gap: 6px; z-index: 15;
  font-size: 13px; color: #F1F1F1; font-variant-numeric: tabular-nums;
}
.j-pager[hidden] { display: none; }
.j-pager-btn {
  width: 28px; height: 28px; border: 0; border-radius: 3px; cursor: pointer;
  background: rgba(0,0,0,.6); color: #fff; font-size: 18px; line-height: 1;
  display: flex; align-items: center; justify-content: center;
}
.j-pager-btn:hover { background: #3D3D3D; }
.j-pager-btn:disabled { opacity: .35; cursor: default; }
.j-pager-label { background: rgba(0,0,0,.6); border-radius: 3px; padding: 4px 8px; }
.j-pager-rest { color: #C2C2C2; margin-left: 6px; }
.j-pager-rest[hidden] { display: none; }
.j-pager--lifted { bottom: var(--pager-lift, 84px); }
body.call-pager-lifted .call-notices { bottom: calc(var(--pager-lift, 84px) + 40px); }
/* В плёнке — столбик под миниатюрами: ▲ ▼ в ряд, под ними «2/7» и «+41». */
.j-pager--strip {
  bottom: 12px; left: auto; right: 0;
  width: var(--strip-outer, 140px); flex-wrap: wrap; justify-content: center; gap: 4px 8px;
  font-size: 12px;
}
.j-pager--strip .j-pager-btn { font-size: 12px; width: 32px; height: 24px; }
.j-pager--strip .j-pager-label { order: 1; }
.j-pager--strip .j-pager-rest { order: 2; margin: 0; width: 100%; text-align: center; }
.call-overlay--pane .j-pager--strip { right: 315px; }

/* ---- плитки чужих экранов «{name}'s screen» (W5-22) — вместо полоски
   «Screens:». Статичная карточка (Д9 B): иконка экрана и имя, без видео;
   размер — как у миниатюры в плёнке и как у плитки в сетке (правило сетки
   выше — .j-screen-tile). Клик закрепляет экран на сцене. */
.j-share-tile { cursor: pointer; background: #292929; }
.j-filmstrip .j-share-tile {
  width: var(--strip-tile-w, 122px); height: var(--strip-tile-h, 71px); flex: 0 0 var(--strip-tile-h, 71px);
  border-radius: 4px;
}
.call-overlay--strip-grid .j-filmstrip .j-share-tile { flex: 0 0 auto; margin: 2px; }
/* Карточка лежит поверх <video>: живой экран без первого кадра (08.10.2026 —
   статичный экран Нины, ключевой кадр не пришёл) показывает значок, а не
   пустой прямоугольник; <video> под ней при этом ждёт кадры. */
.j-share-tile-card { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: #C2C2C2; }
.j-share-tile-card { flex-direction: column; gap: 6px; }
.j-share-tile-card .icon { width: 40px; height: 40px; }
.j-share-tile-hint { font-size: 12px; color: #A4A4A4; }
.j-filmstrip .j-share-tile-hint { display: none; }
.j-filmstrip .j-share-tile-card .icon { width: 24px; height: 24px; }
.j-filmstrip .j-share-tile .call-tile-name { left: 50%; transform: translateX(-50%); bottom: 4px; }
.j-share-tile:hover { background: #3D3D3D; }
.j-share-tile:focus-visible { outline: 0; box-shadow: inset 0 0 0 2px #D7E3F9; }
/* Экран на сцене — обводка, как у закреплённой плитки. */
.j-share-tile--on { box-shadow: inset 0 0 0 2px #4687ED; }

/* Значок «делится экраном» на плитке — без картинки: экран на сцене один. */
.call-tile-share {
  position: absolute; top: var(--space-2); left: var(--space-2);
  width: 26px; height: 22px; border-radius: var(--radius-sm);
  background: rgba(0, 0, 0, 0.55); color: #fff;
  display: flex; align-items: center; justify-content: center;
}
.call-tile-share .icon { width: 16px; height: 16px; }
.call-tile-share[hidden] { display: none; }
.j-filmstrip .call-tile-share { top: 4px; left: 4px; width: 20px; height: 16px; }
.j-filmstrip .call-tile-share .icon { width: 12px; height: 12px; }
/* Своя шара плиткой в виде «плитка» (W4-9, filmstripLocalScreenShare Jitsi):
   рядом со своей плиткой, того же размера (правила сетки выше). Экран — текст
   и таблицы: целиком (contain), не обрезанным по краям, как лицо (cover). Не
   .call-tile: не человек — ни пина по клику, ни курсора-руки. */
.j-screen-tile {
  position: relative; background: #292929; border-radius: var(--radius-md); overflow: hidden;
  display: flex; align-items: center; justify-content: center;
}
.j-screen-tile-video { width: 100%; height: 100%; object-fit: contain; display: block; }
.j-screen-tile-video[hidden], .j-share-tile-card[hidden] { display: none; }
/* Копия экрана в плитке (13.10.2026) — поверх полной, той же рамкой; видна
   одна из двух (screenShow), вторая прозрачна, но получает кадры: по первому из
   них план гасит уходящую. Карточка и имя — после в DOM, остаются сверху. */
.j-screen-tile-low { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; display: block; }
.j-screen-tile-low--under, .j-screen-tile-video--under { opacity: 0; }
/* Своя шара плиткой в плёнке (как локальный экран у Jitsi) — того же размера,
   что миниатюра; клик ставит свой экран на сцену. */
.j-filmstrip .j-screen-tile {
  width: var(--strip-tile-w, 122px); height: var(--strip-tile-h, 71px); flex: 0 0 var(--strip-tile-h, 71px);
  border-radius: 4px; cursor: pointer;
}
.call-overlay--strip-grid .j-filmstrip .j-screen-tile { flex: 0 0 auto; margin: 2px; }
.j-filmstrip .j-screen-tile .call-tile-name { left: 50%; transform: translateX(-50%); bottom: 4px; max-width: calc(100% - 8px); }
.j-screen-tile--own { cursor: pointer; }
.j-screen-tile--own:focus-visible { outline: 0; box-shadow: inset 0 0 0 2px #D7E3F9; }
.j-screen-tile-name { display: inline-flex; align-items: center; gap: 4px; }
.j-screen-tile-name .icon { width: 14px; height: 14px; flex: none; }
.j-screen-tile-name span { overflow: hidden; text-overflow: ellipsis; }
/* Пин на сцену — кликом по плитке в плёнке и в сетке, своей тоже (W4-9/W4-10,
   как у Jitsi); сама плитка это показывает: обводка и булавка. */
.call-overlay .call-tile { cursor: pointer; }
.call-tile--pinned { outline: 2px solid #4687ED; outline-offset: -2px; }
/* Булавка — PinnedIndicator Jitsi: rgba(0,0,0,.7), padding 4, r4, левый верхний
   угол; значок «делится экраном» там же — булавка встаёт справа от него. */
.call-tile-pin {
  position: absolute; top: var(--space-2); left: var(--space-2); z-index: 3;
  display: flex; align-items: center; justify-content: center;
  padding: 4px; border-radius: 4px; background: rgba(0, 0, 0, 0.7); color: #fff;
}
.call-tile-pin .icon { width: 16px; height: 16px; }
.call-tile-pin[hidden] { display: none; }
.call-tile--sharing .call-tile-pin { left: calc(var(--space-2) + 30px); }
.j-filmstrip .call-tile-pin { top: 4px; left: 4px; padding: 2px; }
.j-filmstrip .call-tile-pin .icon { width: 12px; height: 12px; }
.j-filmstrip .call-tile--sharing .call-tile-pin { left: 28px; }
/* Кнопка пина только для клавиатуры (keyboardPinButton Jitsi): поверх плитки
   с отступом 3 px под обводку, мышь проходит насквозь — кликает плитку, а
   фокус не встаёт (пробел после клика остаётся «нажми и говори»). Видна
   только фокусом с клавиатуры. */
.call-tile-pinbtn {
  position: absolute; inset: 3px; z-index: 10; pointer-events: none;
  border-radius: inherit; outline: none;
}
.call-tile-pinbtn:focus-visible { outline: 2px solid #4687ED; outline-offset: 0; }
/* «⋯» меню плитки (W4-14) — VideoMenuTriggerButton Jitsi (Remote/Local
   VideoMenuTriggerButton.tsx: Button small primary, padding 3, значок 18, r4;
   action01 #246FE5, наведение #4687ED), правый верхний угол. Видна при
   наведении на плитку, фокусе внутри неё (Tab: кнопка пина → «⋯») и пока
   открыто её меню (.call-tile--menu, ставит group-call.js). Спрятана — opacity
   0 и мимо мыши, а НЕ display:none: до невидимой display:none кнопки Tab не
   доходит. Над кнопкой пина (z 10). Рука и точки уровня, что живут в том же
   углу, на это время отъезжают левее — не под кнопку. */
.call-tile-menu {
  position: absolute; top: var(--space-2); right: var(--space-2); z-index: 11;
  width: 24px; height: 24px; padding: 3px; box-sizing: border-box;
  border: 0; border-radius: 4px; background: #246FE5; color: #fff; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  opacity: 0; pointer-events: none;
}
.call-tile-menu .icon { width: 18px; height: 18px; }
.call-tile-menu:hover { background: #4687ED; }
.call-tile-menu:focus-visible { outline: 2px solid #fff; outline-offset: 0; }
.call-tile:is(:hover, :focus-within, .call-tile--menu) .call-tile-menu { opacity: 1; pointer-events: auto; }
.j-filmstrip .call-tile-menu { top: 4px; right: 4px; }
.call-tile:is(:hover, :focus-within, .call-tile--menu) :is(.call-tile-hand, .call-tile-level) { right: calc(var(--space-2) + 30px); }
.call-tile--hand:is(:hover, :focus-within, .call-tile--menu) .call-tile-level { right: calc(var(--space-2) + 70px); }

/* ---- меню реакций (W4-29): css/_reactions-menu.scss Jitsi ----
   330 по содержимому + 2×16 (у Jitsi box-sizing по умолчанию, content-box),
   фон reactionsMenuBackground #242528, тень и r6 — оттуда же. Над рукой с
   шевроном (reactions-menu.js, placeMenu), fixed в body/полноэкранном, как
   меню встречи (z 95). Кнопки 40×40 r6 (toolbox-icon меню), зазор 8,
   эмодзи 1.375rem; серия нажатий растит эмодзи на 1 px (increase-1…12,
   1.25rem + N px). Наведение — #3D3D3D, как у кнопок тулбара (замер Д4). */
.j-reactions {
  position: fixed; z-index: 95;
  box-sizing: content-box; width: 330px; padding: 16px;
  background: #242528; border-radius: 6px;
  box-shadow: 0 3px 16px rgba(0,0,0,.6), 0 0 4px 1px rgba(0,0,0,.25);
}
.j-reactions-row { display: flex; gap: 8px; }
.j-reaction-btn {
  position: relative; padding: 0; border: 0; background: transparent;
  color: #fff; cursor: pointer; touch-action: manipulation; line-height: 3rem;
}
.j-reaction-btn .toolbox-icon {
  display: flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: 6px;
}
.j-reaction-btn .emoji {
  display: flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; font-size: 1.375rem; line-height: 1;
  transition: font-size ease .1s;
}
@media (hover: hover) and (pointer: fine) {
  .j-reaction-btn:hover .toolbox-icon { background: #3D3D3D; }
  .j-reaction-btn:active .toolbox-icon { background: #525252; }
}
.j-reaction-btn:focus-visible { outline: 2px solid #4687ED; outline-offset: 0; border-radius: 6px; }
.j-reaction-btn .emoji.increase-1 { font-size: calc(1.25rem + 1px); }
.j-reaction-btn .emoji.increase-2 { font-size: calc(1.25rem + 2px); }
.j-reaction-btn .emoji.increase-3 { font-size: calc(1.25rem + 3px); }
.j-reaction-btn .emoji.increase-4 { font-size: calc(1.25rem + 4px); }
.j-reaction-btn .emoji.increase-5 { font-size: calc(1.25rem + 5px); }
.j-reaction-btn .emoji.increase-6 { font-size: calc(1.25rem + 6px); }
.j-reaction-btn .emoji.increase-7 { font-size: calc(1.25rem + 7px); }
.j-reaction-btn .emoji.increase-8 { font-size: calc(1.25rem + 8px); }
.j-reaction-btn .emoji.increase-9 { font-size: calc(1.25rem + 9px); }
.j-reaction-btn .emoji.increase-10 { font-size: calc(1.25rem + 10px); }
.j-reaction-btn .emoji.increase-11 { font-size: calc(1.25rem + 11px); }
.j-reaction-btn .emoji.increase-12 { font-size: calc(1.25rem + 12px); }
/* Взлетающая реакция (W4-29) — .reaction-emoji Jitsi: 32×32, 1.5rem,
   старт у руки (left/top ставит reactions-menu.js), 5 с, без имени.
   Траектория — CSS-переменные места в очереди (floatSlot, call-reactions.js):
   точка 70–75 % (--j-rx1, --j-ry1), конец (--j-rx2, --j-ry2), как
   flowToRight / animation-N Jitsi. Над сценой, мимо мыши. */
.j-float {
  position: absolute; z-index: 25; pointer-events: none;
  width: 32px; height: 32px; font-size: 1.5rem; line-height: 2rem;
  opacity: 0;
  animation: j-reaction-float 5s ease-in-out forwards;
}
@keyframes j-reaction-float {
  0%   { transform: translate(0, 0) scale(.6); opacity: 1; }
  70%  { transform: translate(var(--j-rx1), var(--j-ry1)) scale(1.5); opacity: 1; }
  75%  { transform: translate(var(--j-rx1), var(--j-ry1)) scale(1.5); opacity: 1; }
  100% { transform: translate(var(--j-rx2), var(--j-ry2)) scale(1); opacity: 0; }
}

/* ---- панель участников: 315px, #141414 — замер ---- */
.j-pane {
  position: absolute; top: 0; right: 0; bottom: 0; width: 315px;
  background: #141414; z-index: 40;
  display: flex; flex-direction: column;
  padding: 16px;
}
.call-overlay--pane .j-stage { right: calc(315px + var(--strip-outer, 140px)); }  /* сцена уступает панели */
.call-overlay--pane .j-filmstrip { right: 315px; }
.call-overlay--pane .j-strip-toggle { right: calc(313px + var(--strip-outer, 140px)); }  /* 315 + плёнка − 2 */
.call-overlay--pane.call-overlay--nostrip .j-stage { right: 315px; }
.call-overlay--pane.call-overlay--nostrip .j-strip-toggle { right: 313px; }
.call-overlay--pane .call-actions { left: calc(50% - 157px); }
.j-pane-close {
  position: absolute; top: 16px; right: 16px;
  width: 32px; height: 32px; border: 0; border-radius: 3px;
  background: transparent; color: #fff; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.j-pane-close:hover { background: #3D3D3D; }
.j-pane-close .icon { width: 20px; height: 20px; }
.j-pane h3 { font-size: 14px; font-weight: 600; color: #fff; margin: 8px 0 16px; }
.j-pane-invite {
  height: 40px; border: 0; border-radius: 6px; cursor: pointer;
  background: #4687ED; color: #fff; font-size: 14px; font-weight: 600;
  display: flex; align-items: center; justify-content: center; gap: 8px;
}
.j-pane-invite:hover { background: #246FE5; }        /* action04 */
.j-pane-invite .icon { width: 20px; height: 20px; }
.j-pane-search {
  margin-top: 8px; height: 40px; border: 0; border-radius: 6px;
  background: #3D3D3D; color: #fff; font-size: 14px; padding: 0 16px;
}
.j-pane-search::placeholder { color: #C2C2C2; }
.j-pane-list { flex: 1; overflow-y: auto; margin-top: 8px; }
.j-pane-section {
  font-size: 11px; letter-spacing: .4px; text-transform: uppercase;
  color: #858585; margin: 14px 0 6px;
}
.j-pane-row {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 4px; border-radius: 6px; font-size: 14px; color: #fff;
}
.j-pane-row:hover { background: #292929; }
.j-pane-row .avatar { width: 32px; height: 32px; font-size: 12px; flex: 0 0 32px; }
.j-pane-row-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.j-pane-row-sub { display: block; font-size: 12px; font-weight: 400; color: #C2C2C2; }
.j-pane-row .icon { width: 18px; height: 18px; color: #C2C2C2; flex: 0 0 18px; }
.j-pane-act { display: flex; gap: 6px; }
.j-pane-act .btn--primary {
  height: 28px; padding: 0 10px; font-size: 12px; border-radius: 6px;
}
.j-pane-act .j-deny {
  height: 28px; padding: 0 10px; font-size: 12px; border-radius: 6px;
  background: transparent; border: 1px solid #3D3D3D; color: #fff; cursor: pointer;
}
/* Индикаторы в строке участника (план C4): экран, камера, микрофон — без
   видео: панель показывает всех, плитки — только страницу. Микрофон как в
   Jitsi (29.09.2026): серый — включён, синий — говорит, красный
   перечёркнутый — выключен (классы строки ставят paintSpeaking и
   paintMicStates). */
.j-pane-ind { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.j-pane-row--speaking .j-pane-row-name { color: #fff; }
.j-pane-ind-cam .icon, .j-pane-ind-share .icon { width: 16px; height: 16px; color: #C2C2C2; }
.j-pane-ind-mic { display: inline-flex; }
.j-pane-ind-mic .icon { width: 16px; height: 16px; color: #C2C2C2; }
.j-pane-mic-on, .j-pane-mic-off { display: inline-flex; }
.j-pane-mic-off { display: none; }
.j-pane-row--muted .j-pane-mic-on { display: none; }
.j-pane-row--muted .j-pane-mic-off { display: inline-flex; }
.j-pane-row--muted .j-pane-mic-off .icon { color: #E04757; }
.j-pane-row--speaking:not(.j-pane-row--muted) .j-pane-mic-on .icon { color: #4687ED; }

/* ---- стук в дверь: карточка-уведомление слева сверху, как в Jitsi ---- */
.call-lobby {
  position: absolute; top: 20px; left: 20px; right: auto; bottom: auto;
  /* 🔴 transform: none — обязательно. Базовое правило выше центрирует полосу
     `left: 50%` + `translateX(-50%)`; здесь `left` переопределён, а transform
     наследовался и сдвигал карточку на полширины ЗА левый край: на экране
     оставались только кнопки «Впустить»/«Отклонить», имя гостя — за кадром
     (meet-a, 17.09.2026). Ширина — не больше экрана, чтобы на узком окне
     кнопки не уехали за правый край тем же способом. */
  transform: none;
  width: min(320px, calc(100vw - 40px)); z-index: 35;
  display: flex; flex-direction: column; gap: 10px;
}
.call-lobby-card {
  background: #141414; border: 1px solid #3D3D3D; border-radius: 8px;
  padding: 14px; box-shadow: rgba(0,0,0,.25) 0 2px 8px 4px;
}

/* ---- приджоин: экран #141414, колонка 300px, значения — замер master ---- */
.j-prejoin {
  position: fixed; inset: 0; z-index: 55;
  background: #141414;
  display: flex;
}
.j-prejoin-col {
  width: 400px; flex: 0 0 400px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 32px;
}
.j-prejoin-brand { position: absolute; top: 20px; left: 24px; font-size: 17px; font-weight: 700; color: #fff; }
.j-prejoin-title { font-size: 28px; font-weight: 600; color: #fff; text-align: center; }
.j-prejoin-room  { font-size: 15px; font-weight: 600; color: #C2C2C2; margin-top: 8px; text-align: center;
  max-width: 300px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Ссылка сразу в сессионный зал (/<Имя>/<N>, 08.10.2026): плашка под именем встречи. */
.j-prejoin-zal { margin-top: 14px; width: 300px; box-sizing: border-box; display: flex; gap: 10px; align-items: flex-start;
  padding: 10px 12px; border: 1px solid #4687ED; border-radius: 6px; background: rgba(70, 135, 237, .16); color: #E0E0E0; }
.j-prejoin-zal .icon { flex: none; width: 18px; height: 18px; margin-top: 1px; color: #6EA2FF; }
.j-prejoin-zal-text { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.j-prejoin-zal-title { font-size: 14px; font-weight: 600; }
.j-prejoin-zal-main { font-size: 13px; color: #6EA2FF; }
.j-prejoin-zal-main:hover { color: #9cc0ff; }
.j-prejoin-who   { margin-top: 20px; width: 300px; height: 40px; border-radius: 6px;
  background: #3D3D3D; color: #fff; font-size: 14px;
  display: flex; align-items: center; padding: 0 16px; }
.j-prejoin-join {
  margin-top: 12px; width: 300px; height: 38px; border: 0; border-radius: 6px;
  background: #4687ED; color: #fff; font-size: 14px; font-weight: 600; cursor: pointer;
}
.j-prejoin-join:hover { background: #246FE5; }
/* «Join meeting» с шевроном, как у Jitsi: справа — «Join without audio». */
.j-prejoin-join-group { position: relative; margin-top: 12px; width: 300px; max-width: 100%; display: flex; }
.j-prejoin-join-group .j-prejoin-join { margin-top: 0; width: auto; flex: 1 1 auto; border-radius: 6px 0 0 6px; }
.j-prejoin-join-more {
  flex: 0 0 38px; height: 38px; border: 0; border-left: 1px solid rgba(255, 255, 255, 0.28);
  border-radius: 0 6px 6px 0; background: #4687ED; color: #fff; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
}
.j-prejoin-join-more:hover { background: #246FE5; }
.j-prejoin-join-more .icon { width: 14px; height: 14px; }
.j-prejoin-join-menu {
  position: absolute; top: 44px; right: 0; z-index: 5; min-width: 200px; padding: 6px;
  border-radius: 6px; background: #1f2a38; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
}
.j-prejoin-join-item {
  display: block; width: 100%; padding: 8px 10px; border: 0; border-radius: 4px;
  background: transparent; color: #fff; font: inherit; font-size: 14px; text-align: left; cursor: pointer;
}
.j-prejoin-join-item:hover, .j-prejoin-join-item:focus-visible { background: rgba(255, 255, 255, 0.08); }
.j-prejoin-devices { margin-top: 24px; display: flex; gap: 18px; }
.j-prejoin-devices .t-wrap .call-btn { background: transparent; }
.j-prejoin-devices .t-wrap .call-btn:hover { background: #3D3D3D; }
.j-prejoin-devices .t-chev { background: #292929; }
.j-prejoin-ok { margin-top: 24px; display: flex; align-items: center; gap: 10px;
  font-size: 13px; color: #C2C2C2; max-width: 300px; }
.j-prejoin-ok i { width: 10px; height: 10px; border-radius: 50%; background: #189B55; flex: 0 0 auto; }
/* Та же строка, но про недоступный микрофон: янтарная, потому что это не
   поломка и не запрет — войти можно, слушать можно, говорить нет. */
.j-prejoin-ok--warn { color: #F1F1F1; }
.j-prejoin-ok--warn i { background: #f0b429; }
/* Пока захват идёт — «Настраиваются устройства…» с серой точкой (12.10.2026,
   DeviceStatus.tsx Jitsi: индикатор не 'ok' — ColorPalette.darkGrey #555). */
.j-prejoin-ok--pending i { background: #555555; }
.j-prejoin-preview { flex: 1; background: #292929; position: relative;
  display: flex; align-items: center; justify-content: center; overflow: hidden; }
/* 🔴 Видео ВНЕ потока. Пока камера выключена, пустой <video> оставался
   флекс-элементом шириной во всё превью и выталкивал кружок с инициалами к
   правому краю, наполовину за экран. А выключенная камера здесь — состояние ПО
   УМОЛЧАНИЮ (wantCam = false в prejoin.js), то есть так этот экран видел
   каждый входящий. */
.j-prejoin-preview video {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;  /* зеркало — .j-mirror (W4-15) */
}
.j-prejoin-preview .avatar--stage { width: 130px; height: 130px; font-size: 44px; border-radius: 50%; }
.j-prejoin-camoff {
  position: absolute; left: 50%; bottom: 26px; transform: translateX(-50%);
  background: rgba(0,0,0,.55); border-radius: 6px; padding: 6px 14px;
  font-size: 13px; color: #E0E0E0;
}

/* Меню устройств живёт и в приджоине — но привязано к СВОЕЙ кнопке.
 *
 * 🔴 Здесь стояло `.call-devices { bottom: auto; }` — без всякой области
 * действия, то есть и для встречи тоже. Оно убивало `bottom: 92px`, и меню
 * вставало по своей статической позиции: в приджоине это верх экрана, где оно
 * висело оторванным от шеврона и обрезалось краем.
 *
 * Теперь в приджоине меню вешается на .t-wrap своей кнопки (prejoin.js) — а
 * .t-wrap уже position: relative. Во встрече меню по-прежнему уходит в оверлей
 * и стоит над панелью кнопок, как и было задумано.
 *
 * ⚑ Раскрывается ВНИЗ, а не вверх: кнопки устройств стоят ПОД формой, и меню,
 * раскрытое вверх, накрывало бы «Join meeting» — единственную кнопку этого
 * экрана. Снизу же пусто до самого края. */
.t-wrap .call-devices { top: calc(100% + 10px); bottom: auto; }
/* …кроме невысокого окна: там снизу пусто НЕ до края. Замерено — при высоте
   620 меню уходило за нижний край на 39 px, и последний пункт списка терялся.
   Порог: колонка отцентрована, поэтому под кнопками остаётся примерно
   (высота / 2 − 130) px, а меню просит около 223. */
@media (max-height: 720px) {
  .t-wrap .call-devices { top: auto; bottom: calc(100% + 10px); }
}

/* ---- гостевая страница: тот же приджоин (контент слева, превью справа) ---- */
.guest-body { flex-direction: row-reverse; }

/* ---- вход: hero как на welcome-странице Jitsi ---- */
.meet-login { background: #040404; align-items: stretch; padding: 0; flex-direction: column; }
.meet-login-card {
  width: 100%; max-width: none; background: transparent; border: 0;
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 24px; position: relative;
}
.meet-login-card .meet-brand { position: absolute; top: 22px; left: 28px; font-size: 20px; }
.meet-login-sub { font-size: 38px; font-weight: 600; color: #fff; margin-bottom: 8px; }
.meet-quick { width: min(560px, 92%); }
.meet-quick-label { display: none; }               /* строка Jitsi: без подписи */
.meet-quick-row {
  display: flex; background: #fff; border-radius: 8px; padding: 4px; gap: 4px;
}
.meet-quick-row input {
  flex: 1; border: 0; outline: 0; background: transparent; color: #040404;
  font-size: 15px; padding: 0 14px; height: 48px;
}
.meet-quick-row input::placeholder { color: #858585; }
.meet-quick-row .meet-login-btn {
  height: 48px; padding: 0 22px; white-space: nowrap; border-radius: 6px;
  background: #4687ED; border: 0; color: #fff;
}
.meet-quick-hint { margin-top: 12px; }

/* 🔴 На телефоне эта строка ВЫЛЕЗАЛА за экран, и «New meeting» — единственная
   кнопка, ради которой сюда приходят без учётки, — оказывалась наполовину за
   правым краем. Классическая ловушка флексбокса: у `flex: 1` подразумевается
   min-width: auto, поэтому поле отказывалось ужиматься уже своего содержимого и
   выталкивало кнопку из строки (при ширине окна 375 документ разъезжался до
   381).
   Одного min-width: 0 мало: тогда поле схлопывается в полоску, потому что у
   кнопки текст в одну строку и она забирает всю ширину. Значит на узком экране
   строка складывается в столбик — поле и кнопка во всю ширину, по 48 px.
   ⚑ flex: 0 0 auto у поля обязателен: в колонке `flex: 1` считает уже ВЫСОТУ, и
   поле садится до высоты своего текста (20 px). */
@media (max-width: 420px) {
  .meet-quick-row { flex-direction: column; gap: 8px; padding: 0; background: transparent; }
  .meet-quick-row input { flex: 0 0 auto; min-width: 0; height: 48px; background: #fff; border-radius: 8px; }
  .meet-quick-row .meet-login-btn { width: 100%; }
}

/* ---- доводка 1:1 после сверки скриншотов с эталоном (27.08) ---- */
/* Hero: подзаголовок и серый вход, дословно по одобренному макету. */
.meet-hero-sub { margin: 0 0 26px; color: #C2C2C2; font-size: 16px; }
.meet-login-card .meet-signin {
  display: inline-block; text-decoration: none;
  align-self: center; width: auto;   /* карточка flex-стретчит детей */
  background: #2b2b2b; border: 1px solid #3D3D3D; border-radius: 8px;
  color: #F1F1F1; font-size: 14px; padding: 12px 20px;
}
.meet-login-card .meet-signin:hover { background: #3D3D3D; }

/* Приджоин: у Jitsi кнопки устройств прозрачные, имя комнаты — белый жирный. */
.j-prejoin .call-btn { background: transparent; color: #F1F1F1; }
.j-prejoin .call-btn:hover { background: #292929; }
.j-prejoin .call-btn--off { background: transparent; color: #F1F1F1; }
.j-prejoin-room { color: #F1F1F1; font-weight: 600; font-size: 16px; }

/* Панель: у Jitsi плейсхолдер поиска стоит по центру. */
.j-pane-search { text-align: center; }

/* Вотермарка в углу встречи — как «jitsi» слева сверху. */
.j-watermark {
  position: absolute; top: 18px; left: 20px; z-index: 5; pointer-events: none;
  color: #fff; opacity: .55; font-size: 19px; font-weight: 600;
}

/* ---- встреча по имени, как у Jitsi (24.09.2026) ---------------------------
   Главная: шапка (только бренд; вход через 405 — лишь для старой ссылки /r/<код>), hero с
   одной строкой «имя встречи + Start meeting», под ней «Recent meetings».
   Приджоин встречи по имени: поле «Enter your name» на месте подписи.
   После выхода — карточка «You left the meeting» с Rejoin. */
.j-welcome-head {
  position: absolute; top: 0; left: 0; right: 0; z-index: 2;
  display: flex; align-items: center; gap: 16px; padding: 18px 28px;
}
.j-welcome-head .meet-brand { font-size: 20px; }
.j-welcome-head .meet-signin {
  text-decoration: none; background: #2b2b2b; border: 1px solid #3D3D3D; border-radius: 8px;
  color: #F1F1F1; font-size: 14px; padding: 8px 14px;
}
.j-welcome-head .meet-signin:hover { background: #3D3D3D; }
/* Старые правила лендинга растягивали обе кнопки во всю ширину (width: 100%). */
.j-welcome-head .meet-signin { display: inline-block; width: auto; flex: 0 0 auto; }
.j-welcome .meet-quick-row .meet-login-btn { width: auto; flex: 0 0 auto; }
.j-welcome .meet-login-card { padding-top: 88px; }
.j-welcome .meet-login-sub { text-align: center; }
.j-welcome .meet-hero-sub { text-align: center; }
.j-welcome .meet-login-note { margin-top: 12px; color: #F8AE1A; text-align: center; }

.j-recent { width: min(560px, 92%); margin-top: 40px; }
.j-recent-title {
  font-size: 13px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: #858585; margin: 0 0 10px;
}
.j-recent-list { list-style: none; padding: 0; margin: 0; }
.j-recent-item {
  display: flex; align-items: center; gap: 12px; padding: 10px 14px; border-radius: 6px;
  color: #F1F1F1; text-decoration: none;
}
.j-recent-item:hover { background: #292929; }
.j-recent-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 15px; }
.j-recent-when { color: #858585; font-size: 13px; flex: 0 0 auto; }

.j-prejoin-name {
  margin-top: 20px; width: 300px; height: 40px; border-radius: 6px;
  background: #3D3D3D; color: #fff; font-size: 14px; padding: 0 16px;
  border: 1px solid transparent; outline: 0;
}
.j-prejoin-name::placeholder { color: #A3A3A3; }
.j-prejoin-name:focus { border-color: #4687ED; }
.j-prejoin-name--missing { border-color: #D83848; }
.j-prejoin-signin {
  display: flex; align-items: center; justify-content: center; text-decoration: none;
}

/* 4c (W4-24, W4-25, W4-27): приджоин как у Jitsi — ошибка имени под полем
   (prejoin.errorMissingName: красная плашка на ширину поля), выключенная
   «Join meeting», ряд кнопок с шестерёнкой и красным выходом; на узком экране
   превью сверху (PreMeetingScreen.tsx:115-172: ≤720 column-reverse; ≤420 —
   колонка во всю ширину, отступы 16/16/0; ≤400 — без заголовка). */
.j-prejoin-error {
  margin-top: 8px; width: 300px; max-width: 100%; box-sizing: border-box; padding: 6px 12px; border-radius: 6px;
  background: #CB2233; color: #fff; font-size: 12px; line-height: 16px; text-align: center;
}
.j-prejoin-join:disabled, .j-prejoin-join-more:disabled { background: #3D3D3D; color: #858585; cursor: default; }
.j-prejoin-devices { align-items: center; flex-wrap: wrap; justify-content: center; }
.j-prejoin .call-btn--end, .j-prejoin .call-btn--end:hover { background: #CB2233; }
.j-prejoin .call-btn--end:hover { background: #E04757; }
@media (max-width: 720px) {
  .j-prejoin { flex-direction: column-reverse; }
  .j-prejoin-col { width: 100%; flex: 0 0 auto; box-sizing: border-box; padding: 24px 32px; }
  .j-prejoin-preview { flex: 1 1 auto; min-height: 0; }
  .j-prejoin-brand { display: none; }
}
@media (max-width: 420px) {
  .j-prejoin-col { padding: 16px 16px 0; }
  .j-prejoin-devices { gap: 8px; margin-top: 16px; margin-bottom: 16px; }
}
@media (max-width: 400px) {
  .j-prejoin-title { display: none; }
}

/* Главная: шестерёнка в шапке (W4-25) — как кнопка тулбара, 40×40, иконка 24. */
.j-welcome-gear {
  width: 40px; height: 40px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: 6px; background: transparent; color: #F1F1F1; cursor: pointer;
}
.j-welcome-gear:hover { background: #3D3D3D; }
.j-welcome-gear .icon { width: 24px; height: 24px; }
/* «Your recent meetings»: строка — ссылка и корзина справа (видна при наведении и фокусе). */
.j-recent-row { display: flex; align-items: center; gap: 4px; }
.j-recent-row .j-recent-item { flex: 1 1 auto; min-width: 0; }
.j-recent-del {
  width: 32px; height: 32px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: 6px; background: transparent; color: #858585; cursor: pointer; opacity: 0;
}
.j-recent-row:hover .j-recent-del, .j-recent-del:focus-visible { opacity: 1; }
.j-recent-del:hover { background: #3D3D3D; color: #F1F1F1; }
.j-recent-del .icon { width: 14px; height: 14px; }
@media (hover: none) { .j-recent-del { opacity: 1; } }
/* Окно «Invite more people» (W4-26) — AddPeopleDialog / CopyButton Jitsi:
   подпись 14/20 над блоком, кнопка-поле на всю ширину (фон action01 #4687ED,
   r6, 8px 16px, текст 14/20 с многоточием, иконка 24 справа; при наведении —
   «Copy meeting link», после копирования — зелёный success #189B55 с галочкой),
   ряд иконок почты 24 в кнопках 40 с зазором 16. */
.j-invite { width: 400px; }
.j-invite-label { font-size: 14px; line-height: 20px; color: #fff; margin-top: 6px; }
.j-invite-copy {
  display: flex; align-items: center; gap: 12px; width: 100%; box-sizing: border-box; min-height: 40px; padding: 8px 16px;
  border: 0; border-radius: 6px; background: #4687ED; color: #fff; font: inherit; font-size: 14px; line-height: 20px;
  cursor: pointer; text-align: left;
}
.j-invite-copy:hover { background: #246FE5; }
.j-invite-copy-text, .j-invite-copy-hover, .j-invite-copy-done { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.j-invite-copy .icon { width: 24px; height: 24px; flex: 0 0 auto; }
.j-invite-copy-hover, .j-invite-copy-check { display: none; }
.j-invite-copy:hover:not(.j-invite-copy--done) .j-invite-copy-text, .j-invite-copy:focus-visible:not(.j-invite-copy--done) .j-invite-copy-text { display: none; }
.j-invite-copy:hover:not(.j-invite-copy--done) .j-invite-copy-hover, .j-invite-copy:focus-visible:not(.j-invite-copy--done) .j-invite-copy-hover { display: block; }
.j-invite-copy--done, .j-invite-copy--done:hover { background: #189B55; }
.j-invite-copy--done .j-invite-copy-text, .j-invite-copy--done > .icon:not(.j-invite-copy-check) { display: none; }
.j-invite-copy--done .j-invite-copy-check { display: block; }
.j-invite-mail { display: flex; gap: 16px; align-items: center; }
.j-invite-mail-btn {
  width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: 6px; background: #3D3D3D; color: #fff; cursor: pointer; text-decoration: none;
}
.j-invite-mail-btn:hover { background: #525252; }
.j-invite-mail-btn .icon { width: 24px; height: 24px; }
/* Profile (W4-23) — ProfileTab Jitsi: аватар 60 с отступом 16 снизу, подпись
   14/20 над полем, поле 40 в высоту на всю ширину, #3D3D3D, r6, 10px 16px;
   заблокированное — серым. */
.j-settings-profile { display: flex; flex-direction: column; padding: 0 2px; }
.j-settings-avatar { width: 60px; height: 60px; font-size: 22px; border-radius: 50%; margin-bottom: 16px; flex: 0 0 auto; }
.j-settings-input {
  width: 100%; box-sizing: border-box; height: 40px; padding: 10px 16px; border: 0; border-radius: 6px;
  background: #3D3D3D; color: #fff; font: inherit; font-size: 14px; line-height: 20px;
}
.j-settings-input::placeholder { color: #A3A3A3; }
.j-settings-input:focus { outline: 0; box-shadow: 0 0 0 2px #4687ED; }
.j-settings-input:disabled { color: #858585; cursor: default; }
/* Аватар кнопки и пункта Profile — 24, как иконка. */
.j-profile-avatar { width: 24px; height: 24px; font-size: 10px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; }
/* В пункте «Ещё» — 20, как иконки пунктов (Avatar size 20 у ProfileButton Jitsi): строка той же высоты, что соседние. */
.j-menu-item .j-profile-avatar, .j-profile-avatar.j-menu-item-icon { width: 20px; height: 20px; font-size: 9px; }
/* Имя на своей плитке можно править кликом (только кому можно менять имя). */
.call-tile--renamable .call-tile-name { cursor: text; pointer-events: auto; }
.call-tile-name--editing { background: transparent; padding: 0; }
.call-tile-name-input {
  width: 140px; max-width: 100%; box-sizing: border-box; height: 24px; padding: 2px 8px; border: 0; border-radius: 4px;
  background: #fff; color: #040404; font: inherit; font-size: 13px;
}
/* «Desktop sharing frame rate» (W5-24) — под «Mirror my video»: список и
   подсказка 12/16 серым с отступом 8 (VideoDeviceSelection.web.tsx:362-381). */
.j-settings-framerate { padding: 0 2px; margin-top: 8px; }
.j-settings-hint { margin-top: 8px; color: #C2C2C2; font-size: 12px; line-height: 16px; }
/* Меню камеры с превью (W5-25) — VideoSettingsContent Jitsi: превью 244×138,
   object-fit: cover, r6; у выбранной рамка 2 px action01; имя — плашкой слева
   внизу на rgba(0,0,0,.7), 12/16, r4; «Preview unavailable» — по центру. */
.call-devices-preview {
  position: relative; display: block; width: 244px; height: 138px; padding: 0; margin: 4px auto 8px;
  border: 2px solid transparent; border-radius: 6px; overflow: hidden; background: #040404;
}
.call-devices-preview.call-devices-item--on { border-color: #4687ED; }
.call-devices-preview:hover { background: #040404; }
.call-devices-preview-video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.call-devices-preview-label {
  position: absolute; left: 8px; bottom: 8px; max-width: calc(100% - 16px); padding: 2px 8px; border-radius: 4px;
  background: rgba(0, 0, 0, 0.7); color: #fff; font-size: 12px; line-height: 16px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.call-devices-preview-error { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: #C2C2C2; font-size: 13px; }
.call-devices-preview-error[hidden] { display: none; }
.call-devices-mirror { padding: 8px 10px; }
/* «Extra noise suppression» в меню микрофона (W5-14) — отдельной группой под чертой. */
.call-devices-ns { margin-top: 6px; padding: 10px 10px 8px; border-top: 1px solid #3D3D3D; }
/* После выхода (W4-27): строка причины под именем встречи. */
.j-left-reason { margin-top: 12px; color: #F1F1F1; font-size: 14px; max-width: min(480px, 90vw); }

.j-left {
  position: fixed; inset: 0; z-index: 56; background: #040404;
  display: flex; align-items: center; justify-content: center; padding: 16px;
}
.j-left-card { display: flex; flex-direction: column; align-items: center; text-align: center; }
.j-left-title { font-size: 28px; font-weight: 600; color: #fff; }
.j-left-room { margin-top: 8px; color: #C2C2C2; font-size: 16px; max-width: 90vw;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.j-left-actions { margin-top: 24px; display: flex; flex-direction: column; align-items: center; gap: 10px; }
.j-left-actions .j-prejoin-join { margin-top: 0; }
.j-left-home { color: #C2C2C2; text-decoration: none; font-size: 14px; padding: 8px 12px; }
.j-left-home:hover { color: #fff; }

@media (max-width: 520px) {
  .j-welcome-head { padding: 14px 16px; gap: 10px; }
  .j-welcome .meet-login-sub { font-size: 28px; }
  .j-prejoin-name, .j-prejoin-join { width: min(300px, 100%); }
}

/* ============================================================================
 * РЕЖИМ «ЭКОНОМИЯ» — .call-overlay--eco (план C5).
 *
 * ⚑ Уже НЕ умолчание (шапка поправлена 12.10.2026, сверка с Jitsi: здесь
 * стояло «Умолчание.»). С волны 5 (Д6) по умолчанию ступень HD, как у Jitsi, и
 * на HD класса нет. Он стоит на ступенях НИЖЕ HD — SD, LD и «Только звук»
 * (policy().ecoCss в call-quality.js, isEco() в call-profile.js): ставит
 * group-call.js (openOverlay / applyQualityChoice), ступень HD снимает — и
 * только она. Кто ползунок «Performance settings» не трогал, этих правил не
 * получает, в том числе на RDP-парке, ради которого они писались; развязать
 * их со ступенью (например, по программной отрисовке) — отдельная находка
 * той же сверки («Слабые ПК»), сначала ступень в телеметрию.
 *
 * Парк работает через RDP на слабых ПК: каждый композитный слой, маска и
 * анимация — это не «чуть плавнее», а лишние перерисовки, которые RDP гонит
 * по сети целыми прямоугольниками.
 *
 * ⚑ Секция в КОНЦЕ файла и с удвоенной специфичностью (.call-overlay.…):
 * она обязана побеждать любое правило скина выше при том же весе, и
 * будущее правило с transition не должно обойти её случайно.
 * ========================================================================== */

/* Ни одного перехода в оверлее: hover-кнопка полного экрана, точка
   «говорит» в панели — всё мгновенно. */
.call-overlay.call-overlay--eco,
.call-overlay.call-overlay--eco * { transition: none; }

/* Реакция не взлетает — стоит 5 с над рукой и исчезает (reactions-menu.js
   снимает узел; очередь в экономии — 10, не 50): анимация transform+opacity
   поверх сцены — это перерисовка всего экрана 60 раз в секунду пять секунд
   подряд. Разброс по горизонтали — половина точки траектории места. */
.call-overlay.call-overlay--eco .j-float { animation: none; opacity: 1; transform: translate(calc(var(--j-rx1) / 2), -96px); }
/* Меню реакций живёт в body (MENU_HOST): рост эмодзи серии — без перехода. */
body:has(> .call-overlay--eco) > .j-reactions .emoji { transition: none; }
/* Размытые поля сцены — только в HD (W5-21, Д10 A): в экономии слой blur
   заставил бы RDP пять раз в секунду пересылать всю сцену. JS его и не
   включает (backdropOn) — правило страхует смену ступени на лету. */
.call-overlay.call-overlay--eco .j-stage-bg { display: none; }

/* Плитка без скруглений: border-radius + overflow:hidden над <video> — это
   маска слоя у КАЖДОЙ плитки (девять на странице), и Chromium тянет её через
   отдельный композитный слой. overflow: clip вместо hidden — тот же срез без
   контейнера прокрутки. contain: strict — плитка не влияет на раскладку
   соседей и перерисовывается только сама: ширина у неё явная в обоих видах
   (122×71 в плёнке, min(30vw, …) в сетке), высота — из aspect-ratio, и
   size-containment тут ничего не ломает. will-change НЕ ставить: слой на
   каждую плитку — ровно то, чего избегаем. */
.call-overlay.call-overlay--eco .call-tile {
  border-radius: 0;
  overflow: hidden;
  overflow: clip;
  contain: strict;
}
/* Границу плитки рисует outline, а не скругление, — и только там, где её не
   рисуют уже «говорит» / «рука» / «пин» (у них свой outline, он важнее). */
.call-overlay.call-overlay--eco .call-tile:not(.call-tile--speaking):not(.call-tile--hand):not(.call-tile--pinned) {
  outline: 1px solid #292929;
  outline-offset: -1px;
}
/* Своя камера в экономии — ЗЕРКАЛОМ, как в полном качестве (Д12, W4-15:
   «всегда зеркало, как Jitsi»). Раньше здесь снимали scaleX(-1) ради одного
   слоя композитора на RDP — и картинка переворачивалась на входе: превью
   зеркальное, встреча нет. Правило зеркала одно — .j-mirror (mirrorOn). */

/* ---- во фрейме chat405 (chat405 wave8/meet, public/js/embed.js) ----------
   Видеочат группы и эфир канала — панель ВНУТРИ окна chat405. Встреча та же;
   снаружи неё здесь только одна строка-сообщение, когда войти нельзя (билет
   протух, сессии нет). Фон страницы — фон встречи: фрейм не должен мигнуть
   белым до того, как откроется оверлей. */
html.embed, html.embed body { background: #040404; }
.embed-note {
  position: fixed; inset: 0;
  display: flex; align-items: center; justify-content: center;
  padding: 24px; text-align: center;
  color: #F1F1F1; font-size: 15px; line-height: 1.4;
}

/* ---- чат встречи: панель слева 315px, как у Jitsi (волна 2, 30.09.2026) ----
   Открыт — сцена, сетка, тулбар, имя комнаты и стопка уведомлений уступают
   ему место слева; открыт вместе с участниками — тулбар по центру между ними.
   С W4-17 ширину тянут ручкой у правой кромки: --chat-w на body (315 — пока
   не тянули), от неё всё, что уступало 315. */
.j-chat {
  position: absolute; top: 0; left: 0; bottom: 0; width: var(--chat-w, 315px);
  background: #141414; z-index: 40;
  display: flex; flex-direction: column;
  color: #fff; font-size: 14px;
}
.call-overlay--chat .j-stage { left: var(--chat-w, 315px); }
.call-overlay--chat.call-overlay--tiles .call-grid { left: var(--chat-w, 315px); }
.call-overlay--chat .call-actions,
.call-overlay--chat .j-subject { left: calc(50% + var(--chat-w, 315px) / 2); }
.call-overlay--chat.call-overlay--pane .call-actions,
.call-overlay--chat.call-overlay--pane .j-subject { left: calc(50% + (var(--chat-w, 315px) - 315px) / 2); }
.call-overlay--chat .j-watermark,
.call-overlay--chat .call-lobby,
.call-overlay--chat .j-pager:not(.j-pager--strip) { left: calc(var(--chat-w, 315px) + 20px); }
body.call-chat-open .call-notices { left: calc(var(--chat-w, 315px) + 20px); width: min(400px, calc(100vw - var(--chat-w, 315px) - 40px)); }
/* Ручка ширины чата (W4-17) — dragHandleContainer Chat.tsx Jitsi:209-256:
   полоса 9 px во всю высоту в 4 px от правой кромки (на сенсорном — 44, по
   центру того же места), черта 3×100 #C2C2C2, под мышью и пока тянут — белая.
   Видна при наведении на чат и фокусе в нём, на сенсорном — всегда. */
.j-chat-resize {
  position: absolute; top: 0; bottom: 0; right: 4px; width: 9px;
  display: flex; align-items: center; justify-content: center;
  cursor: col-resize; touch-action: none; visibility: hidden; z-index: 2;
}
.j-chat-resize[hidden] { display: none; }
.j-chat:is(:hover, :focus-within) .j-chat-resize,
.j-chat-resize.j-resize--active { visibility: visible; }
.j-chat-resize:hover .j-drag-handle { background: #fff; }
@media (hover: none) and (pointer: coarse) {
  .j-strip-resize, .j-chat-resize { visibility: visible; }
  .j-chat-resize { width: 44px; right: -13px; }   /* 4 − ⌊(44 − 9) / 2⌋ */
}

.j-chat-head {
  display: flex; align-items: center; gap: 4px;
  padding: 16px 16px 8px;
}
.j-chat-head h3 { flex: 1; font-size: 14px; font-weight: 600; margin: 0; }
.j-chat-close, .j-chat-search-btn {
  width: 32px; height: 32px; border: 0; border-radius: 3px;
  background: transparent; color: #fff; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.j-chat-close:hover, .j-chat-search-btn:hover { background: #3D3D3D; }
.j-chat-close .icon, .j-chat-search-btn .icon { width: 20px; height: 20px; }

.j-chat-searchbar {
  display: flex; align-items: center; gap: 4px; padding: 0 16px 8px;
}
.j-chat-searchbar[hidden] { display: none; }
.j-chat-search {
  flex: 1; min-width: 0; height: 36px; border: 0; border-radius: 6px;
  background: #3D3D3D; color: #fff; font-size: 14px; padding: 0 12px;
}
.j-chat-search::placeholder { color: #C2C2C2; }
.j-chat-search-count { font-size: 12px; color: #C2C2C2; white-space: nowrap; min-width: 36px; text-align: center; }
.j-chat-searchbar button {
  width: 28px; height: 28px; border: 0; border-radius: 3px; cursor: pointer;
  background: transparent; color: #fff; font-size: 14px;
}
.j-chat-searchbar button:hover { background: #3D3D3D; }

.j-chat-list {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: 8px 16px 12px;
  display: flex; flex-direction: column; gap: 12px;
}
.j-chat-empty {
  margin: auto 8px; text-align: center; color: #C2C2C2; font-size: 14px; line-height: 20px;
}
.j-chat-group { display: flex; align-items: flex-start; gap: 8px; max-width: 100%; }
.j-chat-group--own { justify-content: flex-end; }
.j-chat-avatar { width: 32px; height: 32px; flex: none; font-size: 12px; }
/* Колонка — во всю оставшуюся ширину (flex: 1): от её ширины считается
   max-width пузыря, а колонка «по содержимому» сжимала пузырь до буквы. */
.j-chat-col { flex: 1 1 0; display: flex; flex-direction: column; align-items: flex-start; gap: 4px; min-width: 0; }
.j-chat-group--own .j-chat-col { align-items: flex-end; }
.j-chat-name { font-size: 12px; font-weight: 600; color: #C2C2C2; padding-left: 2px; }
.j-chat-guest { font-weight: 400; color: #858585; }

.j-chat-msg { position: relative; display: flex; flex-direction: column; max-width: calc(100% - 56px); }
.j-chat-group--own .j-chat-msg { align-items: flex-end; }
.j-chat-bubble {
  background: #292929; border-radius: 4px 12px 12px 12px;
  padding: 8px 12px; max-width: 100%;
}
.j-chat-msg--own .j-chat-bubble { background: #3D3D3D; border-radius: 12px 4px 12px 12px; }
.j-chat-msg--private .j-chat-bubble { background: #3B2E73; }
.j-chat-msg--match .j-chat-bubble { box-shadow: 0 0 0 1px #F8AE1A inset; }
.j-chat-msg--current .j-chat-bubble { box-shadow: 0 0 0 2px #F8AE1A inset; }
.j-chat-private { font-size: 12px; font-weight: 600; color: #C9BFFF; margin-bottom: 2px; }
.j-chat-text { white-space: pre-wrap; overflow-wrap: anywhere; line-height: 20px; }
.j-chat-text a { color: #6EA2FF; }
.j-chat-text--deleted { font-style: italic; color: #C2C2C2; }
.j-chat-meta { font-size: 11px; color: #A4A4A4; text-align: right; margin-top: 2px; }

.j-chat-reacts { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.j-chat-react {
  border: 1px solid #525252; border-radius: 12px; background: #1E1E1E; color: #fff;
  font-size: 12px; padding: 1px 8px; cursor: pointer;
}
.j-chat-react--mine { border-color: #4687ED; background: #1D3F7B; }

/* Действия у сообщения — по наведению, сбоку от пузыря, как у Jitsi: у
   чужого справа, у своего слева. Место под них оставляет max-width пузыря. */
.j-chat-acts {
  position: absolute; top: 4px; left: 100%; padding-left: 4px;   /* без щели: мышь не теряет наведение */
  display: none; gap: 2px; z-index: 2;
}
.j-chat-group--own .j-chat-acts { left: auto; right: 100%; padding: 0 4px 0 0; }
.j-chat-msg:hover .j-chat-acts, .j-chat-acts:focus-within, .j-chat-acts--open { display: flex; }
.j-chat-act {
  width: 24px; height: 24px; border: 0; border-radius: 3px; cursor: pointer;
  background: #525252; color: #fff; display: flex; align-items: center; justify-content: center;
  box-shadow: 0 2px 6px rgba(0,0,0,.4);
}
.j-chat-act:hover { background: #6A6A6A; }
.j-chat-act .icon { width: 16px; height: 16px; }
.j-chat-pop {
  position: fixed; z-index: 90;
  background: #292929; border-radius: 6px; padding: 4px;
  box-shadow: 0 8px 24px rgba(0,0,0,.45);
  display: flex; flex-direction: column; min-width: 160px;
}
.j-chat-pop[hidden] { display: none; }
.j-chat-pop:has(.j-chat-pop-emoji) { flex-direction: row; min-width: 0; }
.j-chat-pop-emoji {
  border: 0; background: transparent; font-size: 20px; width: 36px; height: 36px;
  border-radius: 4px; cursor: pointer;
}
.j-chat-pop-emoji:hover { background: #3D3D3D; }
.j-chat-pop-item {
  border: 0; background: transparent; color: #fff; text-align: left;
  font-size: 14px; padding: 8px 12px; border-radius: 4px; cursor: pointer;
}
.j-chat-pop-item:hover { background: #3D3D3D; }

.j-chat-reactionline { font-size: 13px; color: #C2C2C2; }
.j-chat-reactionline b { color: #fff; font-weight: 600; }

.j-chat-new {
  align-self: center; margin: -44px 0 8px; position: relative; z-index: 3;
  border: 0; border-radius: 16px; padding: 6px 14px; cursor: pointer;
  background: #4687ED; color: #fff; font-size: 13px; font-weight: 600;
  box-shadow: 0 4px 12px rgba(0,0,0,.4);
}
.j-chat-new[hidden] { display: none; }

.j-chat-compose { padding: 8px 16px 16px; display: flex; flex-direction: column; gap: 8px; position: relative; }
.j-chat-banner {
  display: flex; align-items: center; gap: 8px;
  background: #292929; border-radius: 6px; padding: 8px 8px 8px 12px; font-size: 13px;
}
.j-chat-banner[hidden] { display: none; }
.j-chat-banner--private { background: #3B2E73; }
.j-chat-banner span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.j-chat-banner-x {
  width: 24px; height: 24px; border: 0; border-radius: 3px; cursor: pointer;
  background: transparent; color: #fff; display: flex; align-items: center; justify-content: center;
}
.j-chat-banner-x:hover { background: rgba(255,255,255,.1); }
.j-chat-banner-x .icon { width: 16px; height: 16px; }
.j-chat-to-row { display: flex; align-items: center; gap: 8px; font-size: 13px; color: #C2C2C2; }
.j-chat-to {
  flex: 1; min-width: 0; height: 32px; border: 0; border-radius: 6px;
  background: #3D3D3D; color: #fff; font-size: 13px; padding: 0 8px;
}
.j-chat-input-row {
  display: flex; align-items: flex-end; gap: 4px;
  background: #3D3D3D; border-radius: 6px; padding: 4px;
}
.j-chat-input {
  flex: 1; min-width: 0; resize: none; border: 0; outline: none;
  background: transparent; color: #fff; font: inherit; font-size: 14px;
  line-height: 20px; padding: 6px 4px; max-height: 120px; field-sizing: content;
}
.j-chat-input::placeholder { color: #C2C2C2; }
.j-chat-input:focus, .j-chat-input:focus-visible { outline: none; box-shadow: none; }
.j-chat-input-row:focus-within { box-shadow: 0 0 0 1px #4687ED inset; }
.j-chat-emoji-btn, .j-chat-send {
  width: 32px; height: 32px; flex: none; border: 0; border-radius: 3px; cursor: pointer;
  background: transparent; color: #fff; display: flex; align-items: center; justify-content: center;
}
.j-chat-emoji-btn:hover { background: #525252; }
.j-chat-emoji-btn .icon, .j-chat-send .icon { width: 20px; height: 20px; }
.j-chat-send { background: #4687ED; }
.j-chat-send:hover { background: #246FE5; }
.j-chat-send:disabled { background: transparent; color: #858585; cursor: default; }
.j-chat-smileys {
  display: grid; grid-template-columns: repeat(5, 1fr); gap: 2px;
  background: #292929; border-radius: 6px; padding: 6px;
}
.j-chat-smileys[hidden] { display: none; }
.j-chat-smileys button {
  border: 0; background: transparent; font-size: 20px; height: 36px; border-radius: 4px; cursor: pointer;
}
.j-chat-smileys button:hover { background: #3D3D3D; }

/* Непрочитанное на кнопке чата — красный кружок, как у Jitsi. */
.t-badge {
  position: absolute; top: -6px; right: 2px;
  min-width: 16px; height: 16px; border-radius: 8px; padding: 0 4px;
  background: #E54B4B; color: #fff; pointer-events: none;
  font-size: 11px; font-weight: 600; line-height: 16px; text-align: center;
}
.t-badge[hidden] { display: none; }

/* ---- модерация «как в Jitsi» (волна 3, 30.09.2026) ------------------------------
   Счётчик рук в шапке, действия в строке панели (быстрое — по наведению, «⋯»),
   низ панели модератора, меню (одно на панель, fixed), меню красной кнопки и
   «⋯» тулбара, окна «Security Options» / «Moderator options», замок чата. */
.j-subject-hands {
  display: flex; align-items: center; gap: 4px; padding: 0 8px;
  background: #F8AE1A; color: #040404; border: 0; cursor: pointer;
  font-size: 12px; font-weight: 600;
}
.j-subject-hands[hidden] { display: none; }
.j-subject-hands .icon { width: 14px; height: 14px; color: #040404; }
/* Число участников в шапке (W4-11) — Label Jitsi цвета white
   (SpeakerStatsLabel): #C2C2C2 (ui08 → ui21), текст и иконка #040404, r4,
   отступ 6, высота 28, label01 (12/16), иконка 16, число в 8 px от неё. */
.j-subject-count {
  display: flex; align-items: center; gap: 8px; height: 28px; box-sizing: border-box;
  margin-left: 2px; padding: 6px; border: 0; border-radius: 4px; cursor: pointer;
  background: #C2C2C2; color: #040404;
  font-size: 12px; line-height: 16px; font-variant-numeric: tabular-nums;
}
.j-subject-count[hidden] { display: none; }
.j-subject-count .icon { width: 16px; height: 16px; color: #040404; }

.j-pane-row { position: relative; }
.j-pane-hover { display: none; align-items: center; gap: 4px; flex: 0 0 auto; }
.j-pane-row:hover .j-pane-hover, .j-pane-row:focus-within .j-pane-hover, .j-pane-row--open .j-pane-hover { display: flex; }
.j-pane-row:hover .j-pane-hover ~ .j-pane-ind, .j-pane-row:focus-within .j-pane-hover ~ .j-pane-ind, .j-pane-row--open .j-pane-hover ~ .j-pane-ind { display: none; }
.j-pane-quick {
  height: 28px; padding: 0 10px; border: 0; border-radius: 3px; cursor: pointer;
  background: #3D3D3D; color: #fff; font-size: 12px; font-weight: 600; white-space: nowrap;
}
.j-pane-quick:hover { background: #525252; }
.j-pane-more, .j-pane-footer-more {
  width: 28px; height: 28px; border: 0; border-radius: 3px; cursor: pointer;
  background: #3D3D3D; color: #fff; display: flex; align-items: center; justify-content: center;
}
.j-pane-more:hover, .j-pane-footer-more:hover { background: #525252; }
.j-pane-more .icon, .j-pane-footer-more .icon { width: 16px; height: 16px; color: #fff; flex: none; }
.j-pane-ind-hand .icon { width: 16px; height: 16px; color: #F8AE1A; }
.j-pane-row--hand .j-pane-row-name { color: #fff; }

.j-pane-section--lobby { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.j-pane-admit-all {
  border: 0; background: transparent; color: #6EA2FF; cursor: pointer;
  font-size: 12px; font-weight: 600; text-transform: none; letter-spacing: 0; padding: 0;
}
.j-pane-admit-all:disabled { opacity: .5; cursor: default; }

/* Комнаты-сессии в панели участников (волна 6, BR4) — RoomList / CollapsibleRoom
   Jitsi: кнопки во всю ширину 40 (secondary #3D3D3D, «Leave» — destructive
   #CB2233), заголовок зала — строка 14/600 со стрелкой 20, участники с
   отступом, Join и «⋯» — при наведении, как действия у участника. */
.j-breakout { margin-top: 16px; display: flex; flex-direction: column; gap: 8px; }
.j-breakout-btn {
  height: 40px; border: 0; border-radius: 6px; cursor: pointer; background: #3D3D3D; color: #fff;
  font: inherit; font-size: 14px; font-weight: 600; display: flex; align-items: center; justify-content: center; gap: 8px; padding: 0 12px;
}
.j-breakout-btn:hover { background: #525252; }
.j-breakout-btn .icon { width: 20px; height: 20px; }
.j-breakout-leave { background: #CB2233; }
.j-breakout-leave:hover { background: #E04757; }
.j-breakout-room { display: flex; flex-direction: column; }
.j-breakout-head { font-weight: 600; min-height: 40px; box-sizing: border-box; }
.j-breakout-title { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.j-breakout-arrow {
  width: 24px; height: 24px; flex: 0 0 24px; border: 0; border-radius: 3px; background: transparent; color: #fff; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; transform: rotate(-90deg);
}
.j-breakout-arrow--open { transform: none; }
.j-breakout-arrow .icon { width: 20px; height: 20px; }
.j-breakout-person { padding-left: 28px; }
/* Перетаскивание участника в комнату (12.10.2026): куда бросят — обведено. */
.j-pane-row[draggable="true"] { cursor: grab; }
.j-breakout-dragging { opacity: .5; }
.j-breakout-drop { outline: 2px dashed #4687ED; outline-offset: -2px; border-radius: 6px; background: rgba(70, 135, 237, .12); }
.j-menu-label { padding: 8px 16px 4px; color: #C2C2C2; font-size: 12px; line-height: 16px; }
/* Сквозное шифрование (волна 6, E2E4): метка «E2EE» в шапке (как метки
   ConferenceInfo Jitsi: плашка 28 высотой, r6, зелёная success), предупреждение
   в «Security Options» и окно «User verification» — семь эмодзи рядами 4 + 3. */
.j-subject-badge {
  display: inline-flex; align-items: center; height: 28px; padding: 0 8px; margin-left: 4px; border-radius: 6px;
  background: #189B55; color: #fff; font-size: 12px; font-weight: 600; line-height: 16px;
}
.j-e2ee-warning { color: #F8AE1A; }
.j-e2ee-verify { width: 400px; }
.j-e2ee-emoji { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px 8px; margin: 8px 0 12px; }
.j-e2ee-emoji-item { width: 84px; display: flex; flex-direction: column; align-items: center; gap: 4px; }
.j-e2ee-emoji-glyph { font-size: 32px; line-height: 40px; }
.j-e2ee-emoji-name { font-size: 12px; line-height: 16px; color: #C2C2C2; text-align: center; }
.j-breakout-rename .call-dialog-input { width: 100%; box-sizing: border-box; }
.j-pane-footer { display: flex; gap: 8px; padding-top: 12px; border-top: 1px solid #292929; margin-top: 8px; }
.j-pane-footer[hidden] { display: none; }
.j-pane-footer-btn {
  flex: 1; height: 40px; border: 0; border-radius: 6px; cursor: pointer;
  background: #3D3D3D; color: #fff; font-size: 14px; font-weight: 600;
}
.j-pane-footer-btn:hover { background: #525252; }
.j-pane-footer-more { width: 40px; height: 40px; border-radius: 6px; }

/* ---- меню встречи (волна 4, W4-2b): одно на «Ещё», выход модератора и «⋯»
   панели — call-menu.js. Метрики Jitsi: ContextMenu.tsx (фон surface02
   #141414, рамка surface05 #525252, r6, тень 0 1px 2px, отступ 8px 0),
   ContextMenuItem.tsx (строка ≥40, 10px 16px, иконка 20 с отступом 16, текст
   14/20, наведение surface03 #292929), ContextMenuItemGroup.tsx (8px 0,
   между группами черта 1px ui03 → #3D3D3D). «Ещё» — min-width 240 и
   max-height calc(100dvh − 100px) (OverflowMenuButton.tsx:83-98). ---- */
.j-menu {
  position: fixed; z-index: 95;
  background: #141414; border: 1px solid #525252; border-radius: 6px;
  box-shadow: 0 1px 2px rgba(41, 41, 41, .25);
  padding: 8px 0; color: #fff;
  font-size: 14px; line-height: 20px;
  display: flex; flex-direction: column;
  min-width: 220px; max-width: min(360px, calc(100vw - 16px));
  max-height: calc(100vh - 100px); max-height: calc(100dvh - 100px);
  overflow-y: auto; box-sizing: border-box;
}
.j-more-menu { min-width: 240px; }
/* «⋯» панели участников: не шире панели (315 − 2 × 8), длинная подпись
   («Остановить демонстрацию экрана для всех остальных») — в две строки,
   а не за край экрана. */
.j-pane-pop { max-width: 299px; }
.j-pane-pop .j-menu-item { white-space: normal; }
/* Меню плитки (W4-14) — те же подписи модерации, что у «⋯» панели: длинные —
   в две строки, а не за край. Ползунок громкости — VolumeSlider Jitsi
   (VolumeSlider.tsx: строка ≥40 и ≥180 в ширину, 10px 16px, значок 22 с
   отступом 16, наведение — подложка как у пункта). */
.j-tile-menu { max-width: 320px; }
.j-tile-menu .j-menu-item { white-space: normal; }
.j-volume {
  display: flex; align-items: center; gap: 16px;
  min-height: 40px; min-width: 180px; padding: 10px 16px; box-sizing: border-box; cursor: pointer;
}
.j-volume:hover { background: #292929; }
.j-volume-icon { display: flex; flex: none; }
.j-volume-icon .icon { width: 22px; height: 22px; color: #fff; }
.j-volume-input { flex: 1; min-width: 0; margin: 0; accent-color: #246FE5; cursor: pointer; }
.j-volume-input:focus-visible { outline: 2px solid #4687ED; outline-offset: 2px; }
.j-menu-group { display: flex; flex-direction: column; padding: 8px 0; }
.j-menu-group:first-child { padding-top: 0; }
.j-menu-group:last-child { padding-bottom: 0; }
.j-menu-group + .j-menu-group { border-top: 1px solid #3D3D3D; }
.j-menu-item {
  display: flex; align-items: center; gap: 16px;
  min-height: 40px; padding: 10px 16px; box-sizing: border-box;
  border: 0; border-radius: 0; background: transparent; color: #fff;
  font: inherit; text-align: left; cursor: pointer; white-space: nowrap;
}
.j-menu-item:hover, .j-menu-item:active { background: #292929; }
.j-menu-item:focus-visible { outline: 0; box-shadow: inset 0 0 0 2px #4687ED; }
.j-menu-item:disabled { color: #858585; cursor: default; background: transparent; }
.j-menu-item-icon { display: flex; flex: none; }
.j-menu-item-icon .icon { width: 20px; height: 20px; color: #fff; }
/* Число непрочитанного у пункта чата в «Ещё» (ChatCounter Jitsi едет в меню
   вместе с кнопкой) — в строке, у правого края, а не над углом кнопки. */
.j-menu-item .t-badge { position: static; flex: none; margin-left: auto; }
/* Меню красной кнопки модератора — как у Jitsi (Toolbox.tsx hangupMenu:
   отступ 16, между кнопками 8; EndConferenceButton — destructive,
   LeaveConferenceButton — secondary, Button.tsx: 10px 16px, r6, 14/20 600). */
.j-hangup-menu { padding: 16px; gap: 8px; min-width: 240px; }
.j-hangup-menu .j-menu-group { gap: 8px; padding: 0; }
.j-menu-btn {
  display: flex; align-items: center; justify-content: center;
  width: 100%; padding: 10px 16px; border: 0; border-radius: 6px; cursor: pointer;
  font: inherit; font-weight: 600; white-space: nowrap; transition: background .2s;
}
.j-menu-btn--danger { background: #D83848; color: #fff; }
.j-menu-btn--danger:hover { background: #F24D5F; }
.j-menu-btn--danger:active { background: #CB2233; }
.j-menu-btn--secondary { background: #E0E0E0; color: #040404; }
.j-menu-btn--secondary:hover { background: #F1F1F1; }
.j-menu-btn--secondary:active { background: #C2C2C2; }
.j-menu-btn:focus-visible { outline: 0; box-shadow: 0 0 0 2px #4687ED; }

/* Подсказка над кнопкой (W4-3) — Tooltip.tsx Jitsi: фон uiBackground #040404,
   текст #fff 12/16, r3, отступ 8; проявление 0,2 с только у «первой»
   подсказки, гаснет 0,2 с. pointer-events: none — висит над шевроном и
   не должна перехватывать клики. */
.j-tooltip {
  position: fixed; z-index: 96; pointer-events: none;
  background: #040404; color: #fff; border-radius: 3px; padding: 8px;
  font-size: 12px; line-height: 16px; font-weight: 400; white-space: nowrap;
  max-width: calc(100vw - 16px); overflow: hidden; text-overflow: ellipsis;
}
.j-tooltip[hidden] { display: none; }
.j-tooltip--in { animation: j-tooltip-in .2s ease-in forwards; }
.j-tooltip--out { animation: j-tooltip-out .2s ease-out forwards; }
@keyframes j-tooltip-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes j-tooltip-out { from { opacity: 1; } to { opacity: 0; } }
.call-overlay.call-overlay--eco .j-tooltip { animation: none; }
/* Подсказка и меню встречи живут в body (MENU_HOST) — экономия и там.
   Отдельными правилами: браузер без :has() выбросил бы весь список. */
body:has(> .call-overlay--eco) > .j-tooltip { animation: none; }
body:has(> .call-overlay--eco) > .j-menu,
body:has(> .call-overlay--eco) > .j-menu * { transition: none; }

/* Точка записи на ⋯ (Д8 A): запись ушла в «Ещё», и записывающий видит, что
   она идёт, не открывая меню. Только у того, кто может её остановить. */
.call-btn[data-key="overflowmenu"] { position: relative; }
.t-rec {
  position: absolute; top: 7px; right: 7px;
  width: 8px; height: 8px; border-radius: 50%;
  background: #E04757; box-shadow: 0 0 0 2px #141414; pointer-events: none;
}
.t-rec[hidden] { display: none; }

/* «Performance settings» (Д9 A): до ползунка волны 5 — наши «экономия /
   полное качество», те же строки, что в меню камеры. */
.call-perf-options { display: flex; flex-direction: column; gap: 4px; }
.call-perf-option {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 10px 12px; border: 1px solid transparent; border-radius: 6px;
  background: transparent; color: inherit; font: inherit; text-align: left; cursor: pointer;
}
.call-perf-option:hover { background: var(--bg-hover, #292929); }
.call-perf-option[aria-checked="true"] { border-color: #4687ED; }
.call-perf-check { width: 18px; height: 18px; flex: none; display: flex; }
.call-perf-check .icon { width: 18px; height: 18px; }

/* Список клавиш (W4-4, вкладка Shortcuts — W4-7) — как ShortcutsTab Jitsi
   (ShortcutsTab.tsx:47-90): плоский список без маркеров, строка 4px 0 и
   14/20, фишки справа — #525252, 12/16 600, 4px 8px, радиус 3, без переноса;
   фишки переносятся с зазором 4 и прижаты вправо. */
.j-shortcuts { list-style: none; padding: 0; margin: 0; }
.j-shortcuts-row {
  display: flex; justify-content: space-between; align-items: center; gap: 16px;
  padding: 4px 0; font-size: 14px; line-height: 20px;
}
.j-shortcuts-keys { display: flex; flex-wrap: wrap; gap: 4px; justify-content: flex-end; }
.j-shortcuts-key {
  background: #525252; color: #fff; font-size: 12px; line-height: 16px; font-weight: 600;
  padding: 4px 8px; border-radius: 3px; white-space: nowrap;
}

.call-dialog { width: 400px; padding: 18px 20px 16px; }
/* Фокус ставится на саму карточку (call-dialog.js) — без кольца вокруг окна. */
.call-dialog:focus { outline: none; }
.call-dialog-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 12px; }
.call-dialog-head h3 { margin: 0; font-size: 16px; font-weight: 600; }
.call-dialog-close {
  width: 32px; height: 32px; border: 0; border-radius: 3px; cursor: pointer;
  background: transparent; color: inherit; display: flex; align-items: center; justify-content: center;
}
.call-dialog-close:hover { background: var(--bg-hover); }
.call-dialog-close .icon { width: 18px; height: 18px; }
.call-dialog-body { display: flex; flex-direction: column; gap: 10px; font-size: 14px; }
.call-dialog-text { margin: 0; color: var(--text-secondary, #9aa0a6); line-height: 1.45; }
.call-dialog-sep { border: 0; border-top: 1px solid var(--border, #3D3D3D); margin: 6px 0; width: 100%; }
.call-dialog-input {
  height: 38px; border-radius: 6px; border: 1px solid var(--border-strong, #525252);
  background: var(--bg-input, #1E1E1E); color: inherit; padding: 0 12px; font-size: 14px;
}
.call-dialog-error { margin: 0; color: var(--danger, #E04757); font-size: 13px; }
.call-password-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.call-password-value { font-family: ui-monospace, monospace; }
.call-password-add { display: flex; flex-direction: column; gap: 8px; }
.call-password-add .confirm-actions { margin-top: 0; }
.call-link-btn {
  align-self: flex-start; border: 0; background: transparent; padding: 0; cursor: pointer;
  color: var(--accent, #4687ED); font-size: 14px; font-weight: 600;
}
.call-link-btn:hover { text-decoration: underline; }
.call-link-btn--danger { color: var(--danger, #E04757); }
.call-switch { display: flex; align-items: center; justify-content: space-between; gap: 12px; cursor: pointer; position: relative; }
.call-switch-label { flex: 1; }
.call-switch-input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.call-switch-track {
  flex: none; width: 40px; height: 22px; border-radius: 11px; background: #525252; position: relative; transition: background .15s;
}
.call-switch-track::after {
  content: ''; position: absolute; top: 3px; left: 3px; width: 16px; height: 16px; border-radius: 50%; background: #fff; transition: transform .15s;
}
.call-switch-input:checked + .call-switch-track { background: #4687ED; }
.call-switch-input:checked + .call-switch-track::after { transform: translateX(18px); }
.call-switch-input:focus-visible + .call-switch-track { box-shadow: 0 0 0 2px #6EA2FF; }
.call-switch-input:disabled + .call-switch-track { opacity: .5; }

/* Галочка как у Jitsi (Checkbox.tsx): подпись 14/24 #fff; поле 24×24 с
   отступом 15 до подписи; квадрат 18 с рамкой 2 icon03 #666 и радиусом 3,
   отмеченный — action01 #4687ED с галкой; выключенный — ui02 #3D3D3D с
   рамкой surface05 #525252. Не переключатель: окно настроек применяет всё
   по OK (checkboxRow, call-dialog.js). */
.j-checkbox { display: inline-flex; align-items: center; font-size: 14px; line-height: 24px; color: #fff; cursor: pointer; }
.j-checkbox--disabled { cursor: not-allowed; }
.j-checkbox-box { position: relative; display: grid; place-content: center; width: 24px; height: 24px; margin-right: 15px; flex: none; }
.j-checkbox-input {
  appearance: none; -webkit-appearance: none; margin: 3px; width: 18px; height: 18px; box-sizing: border-box;
  border: 2px solid #666666; border-radius: 3px; background: transparent; cursor: inherit;
  transition: background .2s, border-color .2s;
}
.j-checkbox-input:checked { background: #4687ED; border-color: #4687ED; }
.j-checkbox-input:disabled { background: #3D3D3D; border-color: #525252; }
.j-checkbox-input:focus-visible { outline: 0; box-shadow: 0 0 0 2px #D7E3F9; }
.j-checkbox-mark { position: absolute; left: 3px; top: 3px; width: 18px; height: 18px; color: #fff; opacity: 0; transition: opacity .2s; pointer-events: none; }
.j-checkbox-input:checked + .j-checkbox-mark { opacity: 1; }
.j-checkbox--disabled .j-checkbox-mark { color: #858585; }

/* Окно «Settings» (волна 4, W4-6) — DialogWithTabs + BaseDialog Jitsi:
   подложка surface03 #292929 с прозрачностью .75, окно сверху с отступом 64;
   карточка surface02 #141414, рамка ui02 #3D3D3D, r6, тень 0 4px 25px 4px
   rgba(20,20,20,.6); 664 × 560 (не выше 80vh), при окне 608–712 — 560 в
   ширину, при ≤607 — во всю ширину от верхнего края, при ≤448 — во весь
   экран. Слева колонка вкладок (не уже 211, черта справа), справа
   содержимое с отступом 24, крестик сверху (order −1), внизу «Cancel» и
   «OK» с зазором 16. */
.j-settings-overlay { padding-top: 64px; background: rgba(41, 41, 41, .75); }
.j-settings {
  display: flex; flex-direction: row; width: 664px; height: 560px; max-height: 80vh; max-width: calc(100vw - 16px);
  box-sizing: border-box; background: #141414; border: 1px solid #3D3D3D; border-radius: 6px;
  box-shadow: 0 4px 25px 4px rgba(20, 20, 20, .6); color: #fff; font-size: 14px; line-height: 24px; overflow: hidden;
}
@media (min-width: 608px) and (max-width: 712px) { .j-settings { width: 560px; } }
.j-settings-sidebar {
  display: flex; flex-direction: column; min-width: 211px; max-width: 100%;
  border-right: 1px solid #3D3D3D; overflow-y: auto; flex: none;
}
.j-settings-titlebar { display: flex; align-items: center; justify-content: space-between; padding: 24px 0 24px 24px; margin: 0; }
.j-settings-title { margin: 0; padding: 0; font-size: 20px; line-height: 28px; font-weight: 600; color: #fff; outline: 0; }
.j-settings-tab {
  display: flex; align-items: center; gap: 16px; min-height: 40px; padding: 10px 16px; box-sizing: border-box;
  border: 0; border-radius: 0; background: transparent; color: #fff; font: inherit; font-size: 14px; line-height: 20px;
  text-align: left; cursor: pointer; width: 100%;
}
.j-settings-tab .icon { width: 20px; height: 20px; flex: none; color: #fff; }
.j-settings-tab:hover, .j-settings-tab:active { background: #292929; }
.j-settings-tab:focus-visible { outline: 0; box-shadow: inset 0 0 0 2px #4687ED; }
/* Выбранная — полоса 3px action01Hover слева и фон строки (ContextMenuItem selected). */
.j-settings-tab--on { border-left: 3px solid #4687ED; padding-left: 13px; background: #292929; }
.j-settings-content { position: relative; display: flex; flex-direction: column; padding: 24px; overflow: hidden; width: 100%; box-sizing: border-box; min-width: 0; }
.j-settings-panel { flex-grow: 1; overflow-y: auto; width: 100%; box-sizing: border-box; }
.j-settings-header { order: -1; display: flex; align-items: center; justify-content: flex-end; padding-bottom: 24px; flex: none; }
.j-settings-footer { display: flex; align-items: center; justify-content: flex-end; gap: 16px; padding-top: 24px; flex: none; }
.j-settings-icon-btn {
  display: flex; align-items: center; justify-content: center; padding: 2px; border: 0; border-radius: 6px;
  background: transparent; color: #fff; cursor: pointer;
}
.j-settings-icon-btn .icon { width: 24px; height: 24px; }
.j-settings-icon-btn:hover { background: #3D3D3D; }
.j-settings-icon-btn:active { background: #292929; }
.j-settings-icon-btn:focus-visible { outline: 0; box-shadow: 0 0 0 2px #D7E3F9; }
/* Кнопки Jitsi (Button.tsx): 10px 16px, r6, 14/20 600; OK — primary action01,
   Cancel — tertiary (прозрачная, наведение hover05 #3D3D3D). */
.j-settings-btn {
  display: flex; align-items: center; justify-content: center; padding: 10px 16px; border: 0; border-radius: 6px;
  font: inherit; font-size: 14px; line-height: 20px; font-weight: 600; color: #fff; cursor: pointer; transition: background .2s;
}
.j-settings-btn--primary { background: #4687ED; }
.j-settings-btn--primary:active { background: #0056E0; }
.j-settings-btn--tertiary { background: transparent; }
.j-settings-btn--tertiary:hover { background: #3D3D3D; }
.j-settings-btn--tertiary:active { background: #292929; }
.j-settings-btn:focus-visible { outline: 0; box-shadow: 0 0 0 2px #D7E3F9; }
/* Заголовки колонок и вкладки Moderator — heading6 16/26 600, отступ 16;
   галочки — столбиком с отступом 16 (theme.spacing(3)). */
.j-settings-legend { margin: 0 0 16px; padding: 0; font-size: 16px; line-height: 26px; font-weight: 600; color: #fff; }
.j-settings-panel .j-checkbox { margin-bottom: 16px; }
.j-settings-notifications { display: flex; width: 100%; }
.j-settings-col { display: flex; flex-direction: column; align-items: flex-start; flex: 1; min-width: 0; border: 0; margin: 0; padding: 0; }
.j-settings-col:first-child:not(:last-child) { margin-right: 16px; }
.j-settings-moderator { display: flex; flex-direction: column; align-items: flex-start; }
/* Поле с выпадающим списком (W5-23: «Maximum number of participants who can
   be pinned to the main stage») — Select Jitsi: подпись сверху 14/20, поле 40. */
.j-settings-field { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; font-size: 14px; line-height: 20px; color: #fff; }
.j-settings-select {
  height: 40px; padding: 0 12px; border: 0; border-radius: 6px; background: #3D3D3D; color: #fff;
  font: inherit; font-size: 14px; max-width: 320px; cursor: pointer;
}
.j-settings-select:focus-visible { outline: 0; box-shadow: 0 0 0 2px #4687ED; }
.j-settings-shortcuts { display: flex; flex-direction: column; width: 100%; padding-bottom: 16px; }
.j-settings-shortcuts > .j-checkbox { align-self: flex-start; }
/* Телефон (≤607, MOBILE_BREAKPOINT): во всю ширину от верхнего края; экран
   списка — строки с отступом 24; экран вкладки — шапка «← Название» и
   крестик (16px 24px), содержимое 0 24px, «Cancel»/«OK» по краям. */
@media (max-width: 607px) {
  .j-settings-overlay { padding-top: 0; }
  .j-settings { position: absolute; top: 0; left: 0; width: 100%; max-width: none; border-radius: 0; }
  .j-settings-notifications { flex-direction: column; }
  .j-settings-col:first-child:not(:last-child) { margin-right: 0; margin-bottom: 16px; }
}
.j-settings--mobile .j-settings-sidebar { width: 100%; border-right: 0; }
.j-settings--mobile .j-settings-titlebar { padding: 16px 24px; }
.j-settings--mobile .j-settings-tab { padding-left: 24px; }
.j-settings--mobile .j-settings-content { padding: 0; }
.j-settings--mobile .j-settings-header { justify-content: space-between; padding: 16px 24px; }
.j-settings--mobile .j-settings-back-wrap { display: flex; flex-direction: row-reverse; align-items: center; gap: 24px; }
.j-settings--mobile .j-settings-panel { padding: 0 24px; }
.j-settings--mobile .j-settings-footer { justify-content: space-between; padding: 16px 24px; }
@media (max-width: 448px) {
  .j-settings { height: 100%; max-height: none; }
}

/* Settings → Audio, Video, «Language» (4c, W4-19…W4-21) — замер meet.jit.si
   (visual/jitsi/en_desktop/11_01, 11_02, 11_08 на 1280×800) и
   AudioDevicesSelection / VideoDeviceSelection / Select.tsx Jitsi:
   - список: подпись 14/20 над ним (отступ 8), <select> 40 в высоту на всю
     ширину, фон #3D3D3D, r6, 14/20, 10px 42px 10px 16px, без системной
     стрелки; стрелка-иконка 22 поверх справа (8/8), фокус — кольцо 2px;
   - шкала: 11 секций по 4 px с зазором 4, r1, покой — #FFFFFF, горит —
     success01 meet.jit.si #189B55 (палитра замера);
   - Audio: колонка с отступом 0 2px; список микрофона — отступ 16 снизу;
     галочки — сетка в 2 колонки, зазор 16, поля 16 сверху и снизу (поля
     есть и у пустой сетки — как у Jitsi на приджоине); вывод — строка со
     «Test» справа (отступ 16), поля 32;
   - Video: превью r3, фон #040404, отступ 24 снизу, 16:9 (у Jitsi высота —
     от кадра; без кадра — пустая строка, и «Preview unavailable» висела бы
     в воздухе); «Mirror my video» — поля 24. */
.j-select { display: flex; flex-direction: column; min-width: 0; }
.j-select-label { color: #fff; font-size: 14px; line-height: 20px; margin-bottom: 8px; }
.j-select-wrap { position: relative; }
.j-select-input {
  width: 100%; box-sizing: border-box; height: 40px; padding: 10px 42px 10px 16px; border: 0; border-radius: 6px;
  background: #3D3D3D; color: #fff; font: inherit; font-size: 14px; line-height: 20px;
  appearance: none; -webkit-appearance: none; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; cursor: pointer;
}
.j-select-input:focus { outline: 0; box-shadow: 0 0 0 2px #D7E3F9; }
.j-select-input:disabled { color: #858585; cursor: default; }
.j-select-input option { background: #3D3D3D; color: #fff; }
.j-select-icon { position: absolute; top: 8px; right: 8px; width: 22px; height: 22px; color: #fff; pointer-events: none; }
.j-settings-language { margin-bottom: 16px; }
/* Вкладки Audio и Video. Вертикаль сверена с замером: подпись 141, список
   169…209, шкала 225 (отступ 16), пустая сетка галочек — ещё 16 + 16, вывод
   — поля 32 (следующий блок Jitsi «Call control» стоит на 325 = 229 + 32 +
   64). Плашка вместо списка (нет разрешения / нет устройств) — textSelector
   DeviceSelector: фон uiBackground #040404, рамка ui03 → #3D3D3D, по центру.
   «Test» — кнопка secondary (action02 #E0E0E0, текст #040404, наведение
   hover02 #F1F1F1, нажатие active02 #C2C2C2 — tokens.json Jitsi). */
.j-settings-audio, .j-settings-video { display: flex; flex-direction: column; padding: 0 2px; width: 100%; box-sizing: border-box; }
.j-settings-audio-input { margin-bottom: 16px; }
.j-meter { display: flex; }
.j-meter-section { flex: 1; height: 4px; border-radius: 1px; background: #FFFFFF; margin-right: 4px; }
.j-meter-section:last-child { margin-right: 0; }
.j-meter-section--on { background: #189B55; }
.j-settings-processing { display: grid; grid-template-columns: auto auto; gap: 16px; margin: 16px 0; padding: 0; border: 0; min-width: 0; }
.j-settings-panel .j-settings-processing .j-checkbox { margin-bottom: 0; width: max-content; max-width: 100%; }
.j-settings-output { display: flex; align-items: flex-end; margin: 32px 0; }
.j-settings-output > .j-select, .j-settings-output > .j-settings-textselector { flex: 1; min-width: 0; }
.j-settings-btn--secondary { background: #E0E0E0; color: #040404; }
.j-settings-btn--secondary:hover { background: #F1F1F1; }
.j-settings-btn--secondary:active { background: #C2C2C2; }
.j-settings-test { margin-left: 16px; flex: none; }
.j-settings-textselector {
  width: 100%; box-sizing: border-box; padding: 10px 16px; border: 1px solid #3D3D3D; border-radius: 6px;
  background: #040404; color: #fff; font-size: 14px; line-height: 20px; text-align: center;
}
/* Превью камеры — VideoInputPreview: r3, фон #040404, отступ 24, видео во
   всю ширину; «Preview unavailable» — по центру поверх. Зеркало — .j-mirror
   (то же правило, что у своей плитки). */
.j-settings-preview { position: relative; border-radius: 3px; overflow: hidden; margin-bottom: 24px; background: #040404; aspect-ratio: 16 / 9; }
.j-settings-preview-video { display: block; width: 100%; height: 100%; object-fit: cover; }
.j-settings-preview-error { position: absolute; left: 0; right: 0; top: 50%; transform: translateY(-50%); text-align: center; color: #fff; }
.j-settings-preview-error[hidden] { display: none; }
.j-settings-mirror { margin: 24px 0; }
.j-settings-panel .j-settings-mirror .j-checkbox { margin-bottom: 0; }

.j-chat-lock { background: #292929; border-radius: 6px; padding: 8px 12px; font-size: 13px; color: #C2C2C2; }
.j-chat-lock[hidden] { display: none; }

/* ============================================================================
   Волна 4 (W4-31, W4-32): телефон и узкое окно — как у Jitsi.
   Заменяет заплатку W4-0 (перенос кнопок во вторую строку на ≤ 500 px): по
   модели тулбара на узком окне в ряд и так встаёт не больше, чем влезает.

   Два порога — оба по ширине, не по UA (call-narrow.js):
   - .call-overlay--narrow — место под видео < 512 (group-call.js paintNarrow):
     шевроны прячутся, меню встречи — шторкой снизу (call-menu.js);
   - @media ≤ 580 — чат и панель участников листами во весь экран, ≤ 448 —
     окна встречи во весь экран.
   ============================================================================ */

/* Шевроны микрофона, камеры и руки — только с мышью и не в узком режиме
   (AudioSettingsButton.tsx:169, VideoSettingsButton.tsx:186,
   RaiseHandContainerButtons.tsx:17: !isMobileBrowser() && !isNarrowLayout).
   Устройства тогда — в Settings, реакции — в подвале «Ещё». */
.call-overlay--narrow .call-actions .t-chev { display: none; }
@media (hover: none) and (pointer: coarse) {
  .call-overlay .call-actions .t-chev { display: none; }
}

/* ---- шторка снизу — Drawer.tsx + JitsiPortal.tsx Jitsi ----
   Подложка rgba(0,0,0,.6) во весь экран, шторка прижата к низу: фон
   drawerBackground surface02 #141414, радиус 24 24 0 0, не выше
   DRAWER_MAX_HEIGHT (80dvh − 64), снизу отступ безопасной зоны. Над
   уведомлениями и тулбаром (меню — 95), под окнами подтверждения (200).
   Шторка «Ещё» — всегда этой высоты (overflowMenuDrawer, OverflowMenuButton.tsx:
   73-77): пункты сверху прокручиваются, подвал реакций прибит к низу. */
.j-drawer-overlay {
  position: fixed; inset: 0; z-index: 95;
  background: rgba(0, 0, 0, .6);
  display: flex; align-items: flex-end;
}
.j-drawer {
  width: 100%; box-sizing: border-box;
  max-height: calc(80vh - 64px); max-height: calc(80dvh - 64px);
  margin-bottom: env(safe-area-inset-bottom, 0px);
  background: #141414; color: #fff;
  border-radius: 24px 24px 0 0;
  overflow-y: auto;
}
.j-drawer:focus { outline: none; }
.j-drawer--more {
  height: calc(80vh - 64px); height: calc(80dvh - 64px);
  display: flex; flex-direction: column; overflow: hidden;
}
/* Меню в шторке — ContextMenu inDrawer: без рамки и тени, сверху 16
   (ContextMenu.tsx:164-173), пункты bodyShortRegularLarge 16/22 с отступом
   13px 16px — строка 48 (ContextMenuItem.tsx: contextMenuItemDrawer). */
.j-menu.j-menu--drawer {
  position: static; z-index: auto;
  min-width: 0; max-width: none; max-height: none;
  border: 0; border-radius: 0; box-shadow: none; background: transparent;
  padding: 16px 0 0; overflow: visible;
  font-size: 16px; line-height: 22px;
}
.j-drawer--more > .j-menu.j-menu--drawer { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.j-menu--drawer .j-menu-item { min-height: 48px; padding: 13px 16px; white-space: normal; }
/* Меню красной кнопки в шторке: className контекстного меню в шторке у Jitsi не
   применяется (ContextMenu.tsx:372-378) — «End meeting for all» и «Leave
   meeting» во всю ширину шторки друг под другом, сверху 16. */
.j-menu--drawer.j-hangup-menu { padding: 16px 0 0; gap: 0; }
.j-menu--drawer.j-hangup-menu .j-menu-group { gap: 0; }

/* ---- подвал реакций «Ещё» — ReactionsMenu Jitsi в OverflowDrawer /
   OverflowMenu (ReactionsMenu.tsx:69-123, css/_reactions-menu.scss) ----
   Фон reactionsMenuBackground #242528, отступ 16 (снизу — не меньше безопасной
   зоны), высота 144 / 106 со строкой руки, на 54 меньше без неё. Эмодзи:
   в шторке кнопки 48×48 и 1.375rem, во всплывашке 24×24 и 1rem; строка руки —
   ✋ и подпись 600 14/24 на фоне «нажатой» кнопки ui02 #3D3D3D, на всю ширину,
   48 / 32 в высоту. Наведение (только мышь) — #525252, нажатие — #3D3D3D.
   Скругление 6 и тень — как НАРИСОВАНО у Jitsi (замер meet.ffmuc.net, 375:
   r6, тень .reactions-menu): класс overflow в ReactionsMenu.tsx их обнуляет,
   но в каскаде побеждает .reactions-menu из css/_reactions-menu.scss. */
.j-reactions-footer {
  box-sizing: border-box; width: 100%; flex: none;
  padding: 16px 16px max(env(safe-area-inset-bottom, 0px), 16px);
  background: #242528;
  border-radius: 6px;
  box-shadow: 0 3px 16px rgba(0, 0, 0, .6), 0 0 4px 1px rgba(0, 0, 0, .25);
}
.j-reactions-footer--drawer { height: 90px; }
.j-reactions-footer--drawer.j-reactions-footer--hand { height: 144px; }
/* Во всплывашке подвал прилипает к низу меню (у Jitsi — absolute bottom 0 под
   прокручиваемыми пунктами, OverflowMenuButton.tsx:99-107). */
.j-reactions-footer--menu { height: 52px; position: sticky; bottom: 0; }
.j-reactions-footer--menu.j-reactions-footer--hand { height: 106px; }
.j-menu--with-footer { padding-bottom: 0; }
.j-reactions-row { display: flex; flex-direction: row; justify-content: space-around; }
.j-reaction, .j-raise-hand {
  display: flex; align-items: center; justify-content: center;
  padding: 0; border: 0; border-radius: 6px;
  background: transparent; color: #fff; font: inherit; cursor: pointer;
  touch-action: manipulation;
}
.j-reaction { width: 48px; height: 48px; flex: none; }
.j-reaction-emoji {
  display: flex; align-items: center; justify-content: center; flex: none;
  width: 48px; height: 48px; font-size: 1.375rem; line-height: normal;
  transition: font-size .1s ease;
}
.j-reactions-footer--menu .j-reaction,
.j-reactions-footer--menu .j-reactions-row .j-reaction-emoji { width: 24px; height: 24px; }
.j-reactions-footer--menu .j-reactions-row .j-reaction-emoji { font-size: 1rem; line-height: 1.5rem; }
.j-raise-hand-row { margin-top: 16px; }
.j-raise-hand { width: 100%; height: 48px; background: #3D3D3D; }
.j-reactions-footer--menu .j-raise-hand,
.j-reactions-footer--menu .j-raise-hand .j-reaction-emoji { height: 32px; }
.j-raise-hand-text { font-style: normal; font-weight: 600; font-size: 14px; line-height: 24px; margin-left: 8px; }
@media (hover: hover) and (pointer: fine) {
  .j-reaction:hover, .j-raise-hand:hover { background: #525252; }
  .j-reaction:active, .j-raise-hand:active { background: #3D3D3D; }
}
.j-reaction:focus-visible, .j-raise-hand:focus-visible { outline: 0; box-shadow: inset 0 0 0 2px #4687ED; }
/* Экономия — и в шторке (она в body, как меню): без переходов. */
body:has(> .call-overlay--eco) > .j-drawer-overlay * { transition: none; }

/* ---- W4-32: чат и участники во весь экран на окне ≤ 580 ----
   SMALL_WIDTH_THRESHOLD (J:chat/constants.ts:34): Chat.tsx:146-153 и
   ParticipantsPane.tsx:61-68 — position fixed, во весь экран; открыты оба —
   чат сверху (ParticipantsPane.tsx:51). Сдвиги сцены, сетки, тулбара, шапки и
   уведомлений от открытых панелей отменяются: лист лежит ПОВЕРХ видео, и под
   ним ничего не переезжает (group-call.js videoSpace — то же в раскладке).
   Ручка ширины чата у листа во весь экран бессмысленна — её нет. */
@media (max-width: 580px) {
  .call-overlay .j-chat,
  .call-overlay .j-pane { position: fixed; top: 0; right: 0; bottom: 0; left: 0; width: auto; height: auto; }
  .call-overlay .j-chat { z-index: 41; }
  .call-overlay .j-chat .j-chat-resize { display: none; }
  .call-overlay--chat .j-stage { left: 0; }
  .call-overlay--chat.call-overlay--tiles .call-grid { left: 0; }
  .call-overlay--chat .call-actions,
  .call-overlay--chat .j-subject,
  .call-overlay--chat .j-screens,
  .call-overlay--chat.call-overlay--pane .call-actions,
  .call-overlay--chat.call-overlay--pane .j-subject,
  .call-overlay--chat.call-overlay--pane .j-screens,
  .call-overlay--pane .call-actions,
  .call-overlay--pane .j-screens { left: 50%; }
  .call-overlay--chat .j-watermark,
  .call-overlay--chat .call-lobby,
  .call-overlay--chat .j-pager:not(.j-pager--strip) { left: 20px; }
  body.call-chat-open .call-notices { left: 20px; width: min(400px, calc(100vw - 40px)); }
  .call-overlay--pane .j-stage { right: var(--strip-outer, 140px); }
  .call-overlay--pane .j-filmstrip { right: 0; }
  .call-overlay--pane .j-strip-toggle { right: calc(var(--strip-outer, 140px) - 2px); }
  .call-overlay--pane.call-overlay--nostrip .j-stage { right: 0; }
  .call-overlay--pane.call-overlay--nostrip .j-strip-toggle { right: -2px; }
  .call-overlay--pane.call-overlay--tiles .call-grid { right: 0; }
  .call-overlay--pane .j-pager--strip { right: 0; }
}

/* ---- W4-31: тулбар во всю ширину на окне ≤ 500 ----
   .toolbox-content-mobile (css/_toolbars.scss:179-204, класс при isMobile ||
   isNarrowLayout): от края до края у нижней кромки, без скругления, кнопки
   space-evenly, 8px сверху и снизу плюс безопасная зона (::after обёртки,
   _toolbars.scss:92-96). Спрятанный (W4-12) — уезжает вниз целиком. После
   блока ≤ 580: с открытыми панелями ряд всё равно во всю ширину.
   Между кнопками — 8 справа у каждой, кроме последней (.toolbox-content-items
   > div, J:base/ui/constants.web.ts:289-295): с space-evenly это ровно
   x = 7, 69, 132, 195, 258, 320 замера Jitsi на 375 (без них — 12, 73, 133…).
   gap 0 — явно: зазор задают поля, а не gap ряда десктопа. */
/* Телефонная плёнка (W4-33): 120 на экране, миниатюры 106×60 с полями 7, без
   ручки (как Jitsi без ресайза плёнки); низ — по --strip-bottom: место под
   пейджер ▲▼, а при тулбаре во всю ширину — ещё и под него. */
.call-overlay .j-filmstrip { bottom: var(--strip-bottom, 72px); }
.call-overlay--strip-compact .j-filmstrip { padding: 7px; }
.call-overlay--strip-compact .j-strip-toggle { top: calc((100% - var(--strip-bottom, 72px)) / 2 - 12px); }
@media (max-width: 500px) {
  /* Пейджер плёнки — над тулбаром (64), а не под ним. */
  .call-overlay.call-overlay--narrow .j-pager--strip { bottom: calc(12px + 64px); }
  .call-overlay.call-overlay--narrow .call-actions {
    left: 0; right: 0; bottom: 0; transform: none;
    width: auto; max-width: none;
    border-radius: 0;
    justify-content: space-evenly; gap: 0;
    padding: 8px 0 calc(8px + env(safe-area-inset-bottom, 0px));
  }
  .call-overlay.call-overlay--narrow .call-actions > :not(:last-child) { margin-right: 8px; }
  .call-overlay.call-overlay--narrow.call-overlay--toolbar-hidden .call-actions { transform: translateY(max(96px, 100%)); }
}
/* < 320 — кнопки 36×36 (theme.breakpoints.down(320), J:base/ui/constants.web.ts:249-252). */
@media (max-width: 319.98px) {
  .call-overlay .call-actions .call-btn { width: 36px; height: 36px; }
}
/* Сенсорный экран: у кнопок тулбара Jitsi наведения и нажатия нет вовсе
   (.toolbox-icon — :hover/:active только в (hover: hover) and (pointer: fine),
   J:base/ui/constants.web.ts:242-250; hangup — так же, _toolbars.scss:106-122).
   Иначе после тапа «липкий» :hover телефона держал кнопку подсвеченной
   #3D3D3D (а включённую — не #525252) до тапа в другое место. */
@media (hover: none) and (pointer: coarse) {
  .call-overlay .call-actions .call-btn:hover { background: transparent; }
  .call-overlay .call-actions .call-btn--on:hover { background: #525252; }
  .call-overlay .call-actions .call-btn--end:hover { background: #CB2233; }
}

/* ---- W4-31: строка панели участников в узком режиме — ParticipantItem Jitsi
   при overflowDrawer (MeetingParticipantItem.tsx:251-271): быстрого действия и
   «⋯» у строки нет вовсе (и на тап, и на наведение), индикаторы на месте;
   тап по чужой строке открывает шторку участника (group-call.js
   openPaneRowDrawer). Шапка шторки — аватар 20 и имя (ParticipantContextMenu.
   tsx:380-387): не пункт, не нажимается. ---- */
.call-overlay--narrow .j-pane-row .j-pane-hover { display: none; }
.call-overlay--narrow .j-pane-row .j-pane-hover ~ .j-pane-ind { display: flex; }
.call-overlay--narrow .j-pane-row--peer { cursor: pointer; }
.j-menu-item.j-menu-item--static { cursor: default; }
.j-menu-item.j-menu-item--static:hover { background: transparent; }
.j-menu-avatar.avatar { width: 20px; height: 20px; flex: 0 0 20px; font-size: 8px; font-weight: 600; letter-spacing: -.272px; }

/* ---- W4-32: окна встречи во весь экран на окне ≤ 448 ----
   BaseDialog.tsx:95-104 Jitsi: width 100%, height 100%, margin 0, position
   absolute от верхнего левого угла. Только во встрече (html.meet-in-call):
   подтверждения списка комнат и чатов — не окна Jitsi. Окно «Settings» —
   своё правило (.j-settings, ≤ 448 выше по файлу). */
@media (max-width: 448px) {
  .meet-in-call .confirm-overlay > .confirm-box {
    position: absolute; top: 0; right: 0; bottom: 0; left: 0;
    width: 100%; max-width: none; height: 100%; max-height: none; margin: 0;
    box-sizing: border-box; overflow-y: auto;
  }
}

/* ============================================================================
   Волна 5 (W5-9): обрыв связи и сон компьютера — оверлеи Jitsi
   (css/overlay/_overlay.scss, css/_inlay.scss, css/reload_overlay/*.scss).
   ============================================================================ */
/* Во встрече (и под оверлеями обрыва и сна) полосы «нет связи» нет: у Jitsi
   во время восстановления видно только индикаторы (Д2-A). Класс ставит
   group-call.js (syncInCallClass). */
.meet-in-call .meet-offline { display: none; }

/* Контейнер на весь экран: #474747, светлый (сетевой сбой) — 70 %. Выше
   стопки уведомлений (80), меню (95/96) и окна подтверждения (200). */
.j-overlay {
  position: fixed; inset: 0; z-index: 300;
  background: #474747; color: #fff;
}
.j-overlay--light { background: rgba(71, 71, 71, 0.7); }
.j-overlay-content {
  position: absolute; left: 50%; transform: translateX(-50%);
  width: 56%; height: 100%; margin: 0 auto;
}
.j-inlay {
  margin-top: 14%; border-radius: 4px; padding: 40px 38px 44px;
  background: #7a7a7a; color: #fff; text-align: center;
  display: flex; flex-direction: column; align-items: center;
}
.j-inlay-title {
  margin: 17px 0; padding-bottom: 17px; color: #fff; font-size: 20px; font-weight: 400;
  letter-spacing: 0.3px; border-bottom: 1px solid #fff; align-self: stretch;
}
.j-inlay-icon { display: inline-flex; margin: 0 10px; }
.j-inlay-icon .icon { width: 50px; height: 50px; }
.j-suspended-overlay .j-inlay > .j-inlay-icon { display: inline-flex; }
.j-suspended-overlay .j-inlay { flex-direction: row; flex-wrap: wrap; justify-content: center; }
.j-suspended-overlay .j-inlay-title,
.j-suspended-overlay .j-overlay-btn { flex-basis: 100%; }
.reload_overlay_title { display: block; font-size: 16px; line-height: 20px; }
.reload_overlay_text { display: block; font-size: 12px; line-height: 30px; }
#reloadProgressBar {
  background: #e9e9e9; border-radius: 3px; height: 5px; margin: 5px auto;
  overflow: hidden; width: 180px;
}
#reloadProgressBar .progress-indicator-fill { background: #0074E0; height: 100%; width: 0; transition: width .5s; }
/* Кнопка Jitsi (Button primary) с отступом сверху theme.spacing(2). */
.j-overlay-btn {
  margin: 16px auto 0; min-width: 120px; height: 40px; padding: 0 16px; border: 0; border-radius: 6px;
  background: #4687ED; color: #fff; font-size: 14px; font-weight: 600; cursor: pointer;
}
.j-overlay-btn:hover { background: #246FE5; }
.j-overlay-btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
@media (max-width: 600px) {
  .j-overlay-content { width: calc(100% - 32px); }
  .j-inlay { padding: 28px 20px 32px; }
}

/* ============================================================================
   Волна 5 (W5-10): «браузер не поддерживается» — css/unsupported-browser
   Jitsi (_unsupported-desktop-browser.scss): по центру, заголовок 1.5rem/300,
   описание 1.25rem/300 rgba(255,255,255,.7), ссылки #489afe.
   ============================================================================ */
.unsupported-browser-page {
  position: fixed; inset: 0; z-index: 400; background: #040404; color: #fff;
}
.unsupported-desktop-browser {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  display: block; text-align: center; width: min(720px, calc(100vw - 32px));
}
.unsupported-desktop-browser__title { color: #fff; font-weight: 300; font-size: 24px; letter-spacing: 1px; margin: 0; }
.unsupported-desktop-browser__description {
  color: rgba(255, 255, 255, 0.7); font-size: 20px; font-weight: 300; letter-spacing: 1px; margin: 16px 0 0;
}
.unsupported-desktop-browser__link { color: #489afe; transition: color .1s ease-out; }
.unsupported-desktop-browser__link:hover { color: #287ade; cursor: pointer; text-decoration: none; transition: color .1s ease-in; }

/* ============================================================================
   Волна 5 (W5-12): заглушка своей шары на сцене — ScreenSharePlaceholder
   Jitsi (largeVideoPlaceholder #292929, dialogText #fff, link01 #4687ED,
   link01Hover #99BBF3).
   ============================================================================ */
.j-share-placeholder {
  position: absolute; inset: 0; z-index: 2; background: #292929;
  display: flex; justify-content: center; align-items: center;
}
.j-share-placeholder[hidden] { display: none; }
.j-share-placeholder-content { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 0 16px; }
.j-share-laptop { width: 88px; height: 56px; box-sizing: border-box; border: 3px solid #fff; border-radius: 6px; }
.j-share-laptop-stand { width: 40px; height: 4px; box-sizing: border-box; background: #fff; border-radius: 6px; margin-top: 4px; }
.j-share-message { font-weight: 600; font-size: 20px; line-height: 28px; margin-top: 24px; letter-spacing: -0.012em; color: #fff; }
.j-share-show { font-weight: 600; font-size: 14px; line-height: 20px; height: 20px; margin-top: 16px; color: #4687ED; cursor: pointer; }
.j-share-show:hover { color: #99BBF3; }
.j-share-show:focus-visible { outline: 2px solid #99BBF3; outline-offset: 2px; border-radius: 2px; }

/* ---- Виртуальный фон (волна 6, VB1–VB2): вкладка Settings → Virtual backgrounds.
   Превью 16:9 сверху, под ним плитки 107×60 (как у Jitsi: thumbnail 107 в
   ширину, r6, выбранная — рамка action01), «Add background» — пунктиром. */
.j-settings-vb { display: flex; flex-direction: column; gap: 16px; width: 100%; }
.j-vb-preview {
  position: relative; width: 100%; max-width: 356px; aspect-ratio: 16 / 9; align-self: center; flex: none;
  border-radius: 6px; overflow: hidden; background: #040404;
}
.j-vb-video { width: 100%; height: 100%; object-fit: cover; display: block; }
.j-vb-wait, .j-vb-hint {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; padding: 16px;
  text-align: center; font-size: 14px; line-height: 20px; color: #C2C2C2;
}
.j-vb-wait[hidden], .j-vb-hint[hidden], .j-vb-video[hidden] { display: none; }
.j-vb-wait { background: rgba(4, 4, 4, .6); color: #fff; }
.j-vb-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 8px; }
.j-vb-tile {
  position: relative; display: flex; align-items: center; justify-content: center; width: 100%; aspect-ratio: 16 / 9;
  padding: 0; border: 2px solid transparent; border-radius: 6px; overflow: hidden; box-sizing: border-box;
  background: #292929; color: #fff; font: inherit; font-size: 12px; line-height: 16px; cursor: pointer;
}
.j-vb-tile:hover { border-color: #525252; }
.j-vb-tile--on, .j-vb-tile--on:hover { border-color: #4687ED; }
.j-vb-tile:focus-visible { outline: 0; box-shadow: 0 0 0 2px #D7E3F9; }
.j-vb-thumb { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; object-fit: cover; text-align: center; padding: 0 4px; box-sizing: border-box; }
img.j-vb-thumb { padding: 0; }
.j-vb-custom { position: relative; display: block; }
.j-vb-delete {
  position: absolute; top: 4px; right: 4px; display: flex; opacity: 0; align-items: center; justify-content: center; width: 20px; height: 20px;
  padding: 0; border: 0; border-radius: 4px; background: rgba(4, 4, 4, .75); color: #fff; cursor: pointer;
}
.j-vb-delete .icon { width: 14px; height: 14px; }
/* Прозрачность, а не display: кнопка остаётся в порядке Tab. */
.j-vb-custom:hover .j-vb-delete, .j-vb-delete:focus-visible { opacity: 1; }
.j-vb-add { flex-direction: column; gap: 2px; border: 1px dashed #525252; background: transparent; color: #C2C2C2; }
.j-vb-add .icon { width: 20px; height: 20px; }
.j-vb-add-label { font-size: 11px; line-height: 14px; text-align: center; padding: 0 4px; }
.j-vb-file { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.j-vb-add:focus-within { box-shadow: 0 0 0 2px #D7E3F9; }
/* Пункт-действие в меню камеры («Select background»): иконка на месте галочки. */
.call-devices-item--action .call-devices-check .icon { width: 16px; height: 16px; }
@media (hover: none) { .j-vb-delete { opacity: 1; } }

/* ---- вход для своих: /admin (10.10.2026) -----------------------------------
   Матвей: «вход должен быть только через small-talk.org/admin, на этой
   странице вход через 405». Отдельная маленькая страница в тех же цветах, что
   лендинг (#040404 и карточка по центру), — ни главную, ни приджоин она не
   трогает: для постороннего сайт остаётся прежним. */
.meet-admin {
  min-height: 100vh; box-sizing: border-box; background: #040404;
  display: flex; align-items: center; justify-content: center; padding: 24px;
}
.meet-admin-card {
  width: min(420px, 100%); display: flex; flex-direction: column; align-items: center; text-align: center;
}
.meet-admin-card .meet-brand { font-size: 20px; color: #fff; margin-bottom: 28px; }
.meet-admin-title { font-size: 28px; font-weight: 600; color: #fff; margin: 0 0 8px; }
.meet-admin-sub { margin: 0 0 24px; color: #C2C2C2; font-size: 15px; line-height: 1.5; }
/* Отказ входа — та же плашка, что на главной (visual-parity .meet-login-note). */
.meet-admin-note {
  margin: 0 0 18px; background: #fff; color: #CB2233; border-radius: 5px;
  padding: 6px 10px; font-size: 12px; font-weight: 600; line-height: 1.4;
}
.meet-admin-me {
  width: 100%; box-sizing: border-box; display: flex; align-items: center; gap: 12px; text-align: left;
  background: #141414; border: 1px solid #292929; border-radius: 8px; padding: 12px 16px;
}
.meet-admin-avatar { width: 40px; height: 40px; font-size: 15px; }
.meet-admin-who { display: flex; flex-direction: column; min-width: 0; }
.meet-admin-name { color: #fff; font-size: 15px; font-weight: 600; }
.meet-admin-login { color: #858585; font-size: 13px; }
/* Роль — не украшение: ведущим в любой встрече делает именно она, и человеку
   с member надо сказать это словами, а не оставить гадать, почему прав нет. */
.meet-admin-role {
  width: 100%; box-sizing: border-box; margin: 12px 0 0; text-align: left;
  color: #C2C2C2; font-size: 13.5px; line-height: 1.5;
}
.meet-admin-role--host {
  color: #E0E0E0; background: rgba(70, 135, 237, 0.14);
  border-left: 3px solid #4687ED; border-radius: 0 6px 6px 0; padding: 10px 12px;
}
.meet-admin-btn { height: 44px; display: flex; align-items: center; justify-content: center; text-decoration: none; }
.meet-admin-actions { display: flex; gap: 10px; width: 100%; margin-top: 20px; }
.meet-admin-actions .btn {
  flex: 1 1 0; width: auto; display: flex; align-items: center; justify-content: center; text-decoration: none;
  background: #2b2b2b; border: 1px solid #3D3D3D; color: #F1F1F1;
}
.meet-admin-actions .btn:hover { background: #3D3D3D; }
