:root {
  color-scheme: dark;
  --bg: #0b0d10;
  --panel: #151922;
  --panel-2: #10141b;
  --panel-3: #1d2430;
  --line: #2c3444;
  --line-soft: rgba(255, 255, 255, 0.08);
  --text: #f3f6fb;
  --muted: #9aa6b9;
  --accent: #4fa3ff;
  --accent-2: #15b8a6;
  --ok: #39c76f;
  --warn: #f3c94f;
  --danger: #f15c5c;
  --shadow: rgba(0, 0, 0, 0.34);
}

* {
  box-sizing: border-box;
}

html,
body {
  width: 100%;
  min-height: 100%;
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;
}

body {
  overflow: hidden;
}

button,
input,
select,
textarea {
  font: inherit;
}

button {
  border: 0;
  cursor: pointer;
}

.app-shell {
  width: 100vw;
  height: 100dvh;
  min-height: 680px;
}

.screen {
  display: none;
  width: 100%;
  height: 100%;
}

.screen.active {
  display: block;
}

.login-screen.active {
  display: grid;
  place-items: center;
  padding: 24px;
  background:
    radial-gradient(circle at top, rgba(79, 163, 255, 0.15), transparent 42%),
    var(--bg);
}

.login-card {
  display: grid;
  gap: 16px;
  width: min(420px, 100%);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 22px;
  background: var(--panel);
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.42);
}

.login-card h1 {
  margin: 0 0 2px;
  font-size: 26px;
  letter-spacing: 0;
}

.login-status {
  min-height: 18px;
  color: #ffb8b8;
  font-size: 13px;
}

.home-header {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 18px;
  min-height: 72px;
  padding: 16px 22px;
  border-bottom: 1px solid var(--line);
  background: #11161f;
}

.home-header h1 {
  margin: 0;
  font-size: 24px;
  letter-spacing: 0;
}

.status-text {
  min-width: 160px;
  color: var(--muted);
  font-size: 13px;
  text-align: right;
}

.top-actions,
.sidebar-status-row {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
}

.sidebar-status-row {
  justify-content: space-between;
}

.primary-button,
.secondary-button,
.ghost-button,
.danger-button,
.control-button,
.icon-button {
  min-height: 34px;
  border-radius: 7px;
  padding: 8px 12px;
  color: var(--text);
  font-weight: 600;
}

.primary-button {
  background: var(--accent);
  color: #04111f;
}

.secondary-button {
  border: 1px solid var(--line);
  background: var(--panel-3);
}

.ghost-button {
  border: 1px solid var(--line);
  background: transparent;
  color: var(--muted);
}

.danger-button {
  border: 1px solid rgba(241, 92, 92, 0.38);
  background: rgba(241, 92, 92, 0.14);
  color: #ffb8b8;
}

.full-width {
  width: 100%;
}

.events-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 260px));
  align-content: start;
  justify-content: start;
  gap: 16px;
  height: calc(100dvh - 72px);
  padding: 24px 32px;
  overflow: auto;
}

.event-card,
.empty-card {
  min-height: 0;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--panel);
  box-shadow: 0 14px 34px var(--shadow);
}

.event-card {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto auto auto;
  align-content: start;
  gap: 8px;
  width: min(260px, calc(100vw - 64px));
  aspect-ratio: 1 / 1;
  padding: 12px;
}

.empty-card {
  display: grid;
  place-items: center;
  width: min(260px, calc(100vw - 64px));
  aspect-ratio: 1 / 1;
  color: var(--muted);
}

.event-count {
  display: inline-grid;
  grid-template-columns: auto 1fr;
  align-items: baseline;
  gap: 7px;
  width: fit-content;
  padding: 7px 10px;
  border: 1px solid rgba(21, 184, 166, 0.32);
  border-radius: 8px;
  background: rgba(21, 184, 166, 0.11);
  color: #9ff4e9;
}

.event-count b {
  font-size: 26px;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.event-count span {
  font-size: 13px;
  font-weight: 800;
}

.event-name,
.event-title-input {
  width: 100%;
  min-width: 0;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: #0d1118;
  color: var(--text);
  outline: none;
}

.event-name {
  min-height: 54px;
  padding: 8px 9px;
  font-size: 16px;
  font-weight: 650;
  align-self: stretch;
}

.event-name:focus,
.event-title-input:focus,
.field input:focus,
.quality-select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px rgba(79, 163, 255, 0.16);
}

.event-meta {
  color: var(--muted);
  font-size: 11px;
}

.event-share {
  display: grid;
  gap: 5px;
  min-width: 0;
  color: var(--muted);
  font-size: 10px;
  font-weight: 700;
}

.event-share-title-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  min-width: 0;
}

.share-panel {
  display: grid;
  gap: 7px;
  min-width: 0;
}

.event-actions {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 6px;
  margin-top: 0;
}

.event-actions .enter-event {
  flex: 1;
}

.monitor-screen.active {
  display: grid;
  grid-template-columns: 320px minmax(0, 1fr);
}

.monitor-screen.public-view {
  grid-template-columns: minmax(0, 1fr);
}

.monitor-screen.public-view .sidebar {
  display: none;
}

.monitor-screen.public-view .stream-url {
  display: none;
}

.monitor-screen.public-view .stats {
  display: none;
}

.monitor-screen.public-view .stream-body {
  grid-template-columns: minmax(0, 1fr);
}

/* Viewers don't need the mute/visibility state spelled out in text — the
   video itself (or, for embeds, the title moved below it) already says enough. */
.monitor-screen.public-view .sound-badge {
  display: none;
}

/* Side meter column width follows how many language streams this player has
   (set as --meter-count by mountPlayerCard() in app.js) instead of a fixed
   width — one language doesn't need to reserve as much room as five. */
.monitor-screen.public-view .stream-main {
  grid-template-columns: minmax(0, 1fr) clamp(64px, calc(28px + var(--meter-count, 1) * 30px), 260px);
}

/* The auto-fetched VK/Rutube/YouTube title is moved here (out of .stream-side)
   by relocateNotePanelForPublicView() in app.js — in both the admin monitor
   screen and the public share page — style it as a full-width row under the
   player instead of a narrow sidebar panel. */
.stream-card > .stream-note-panel {
  /* The card's single grid column can be wider than the card itself (the
     .stream-controls row has hard minimum widths and gets clipped by the
     card's overflow:hidden on narrow cards — pre-existing). Keep the schedule
     panel to the card's real width so its one-line layout, the toggle and the
     list overlay stay fully visible. The card is an inline-size container. */
  min-width: 0;
  max-width: 100cqw;
  min-height: 0;
  border-top: 1px solid var(--line);
  border-left: 0;
}

.stream-card > .stream-note-panel .stream-note-title {
  font-size: 12px;
  font-weight: 700;
}

/* Embed-only players (VK/Rutube/YouTube) have nothing left to show in the side
   column once the title has moved below the player (meter/stats are already
   hidden for embeds elsewhere) — collapse the column entirely so the iframe
   gets the full card width. */
.is-embed-card .stream-main,
.stream-card.showing-embed .stream-main {
  grid-template-columns: 1fr;
}

.is-embed-card .stream-side,
.stream-card.showing-embed .stream-side {
  display: none;
}

/* .stream-controls has its own `display: grid` (see base rule below), which
   beats the UA default for [hidden] — app.js sets streamControls.hidden on
   embed-only cards, so it needs an explicit override here to actually hide. */
.is-embed-card .stream-controls {
  display: none;
}

/* Multiple embed languages: bring the side column back as a vertical
   language switcher (built by mountEmbedOnlyCard() in app.js) instead of the
   full-width collapse above. */
.is-embed-card.has-embed-switch .stream-main {
  grid-template-columns: minmax(0, 1fr) 150px;
}

.is-embed-card.has-embed-switch .stream-side {
  display: flex;
}

.embed-side-switch {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 100%;
  padding: 8px;
}

.embed-side-switch-btn {
  min-height: 32px;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 6px 8px;
  background: var(--panel-3);
  color: var(--muted);
  font-size: 12px;
  font-weight: 650;
  text-align: left;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.embed-side-switch-btn.is-active {
  border-color: var(--accent);
  background: rgba(79, 163, 255, 0.16);
  color: var(--text);
}

/* Paginated layout (data-mode="page") — the "show all at once" overview mode
   (data-mode="overview"/.overview-grid) keeps its own separate compact-card
   masonry layout untouched below. */
.monitor-screen.public-view .stage-grid[data-mode="page"] {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-content: center;
  align-items: center;
  gap: 16px;
}

.monitor-screen.public-view .stage-grid[data-mode="page"] .stream-card {
  aspect-ratio: 16 / 9;
}

/* 1 → alone, centered (~50% width); 2 → pair in a row; 3 → 2 up top + 1 that
   wraps to its own centered row below (the "triangle"); 4 → 2x2 square —
   all four fall out of the same ~48%-wide flex-basis with wrap+center, no
   per-count placement rules needed. */
.monitor-screen.public-view .stage-grid[data-mode="page"][data-count="1"] .stream-card,
.monitor-screen.public-view .stage-grid[data-mode="page"][data-count="2"] .stream-card,
.monitor-screen.public-view .stage-grid[data-mode="page"][data-count="3"] .stream-card,
.monitor-screen.public-view .stage-grid[data-mode="page"][data-count="4"] .stream-card {
  flex: 0 0 min(720px, calc(50% - 16px));
}

/* 5 → 3 up top + 2 that wrap and center below; 6 → 3x2 — same trick with a
   narrower ~31%-wide flex-basis (3 per row instead of 2). */
.monitor-screen.public-view .stage-grid[data-mode="page"][data-count="5"] .stream-card,
.monitor-screen.public-view .stage-grid[data-mode="page"][data-count="6"] .stream-card {
  flex: 0 0 min(560px, calc(33.333% - 16px));
}

.monitor-screen.public-view .stage-grid[data-mode="page"].has-pager {
  padding-bottom: 68px;
}

.sidebar {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
  height: 100dvh;
  padding: 12px;
  border-right: 1px solid var(--line);
  background: #11161e;
}

.sidebar-top {
  display: grid;
  gap: 9px;
}

.event-title-input {
  min-height: 42px;
  padding: 8px 10px;
  font-size: 18px;
  font-weight: 650;
}

.sidebar .status-text {
  min-height: 18px;
  min-width: 0;
  text-align: left;
}

.sidebar-section-title {
  margin-top: 6px;
  color: var(--muted);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.sidebar-section-title-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.viewer-count {
  flex-shrink: 0;
  padding: 2px 7px;
  border-radius: 999px;
  background: rgba(79, 163, 255, 0.14);
  color: var(--accent);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.02em;
  white-space: nowrap;
}

.viewer-count:empty {
  display: none;
}

.players-list {
  display: grid;
  gap: 8px;
  min-height: 0;
  overflow: auto;
  padding-right: 2px;
}

.empty-list {
  border: 1px dashed var(--line);
  border-radius: 8px;
  padding: 18px 12px;
  color: var(--muted);
  text-align: center;
}

.player-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 32px 32px 32px;
  align-items: stretch;
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
  background: var(--panel);
}

.player-row.active {
  border-color: var(--accent-2);
  box-shadow: inset 3px 0 0 var(--accent-2);
}

.player-row-main {
  min-width: 0;
  padding: 10px;
  background: transparent;
  color: var(--text);
  text-align: left;
}

.player-row-main strong,
.player-row-main span {
  display: block;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.player-row-main strong {
  font-size: 14px;
}

.player-row-main span {
  margin-top: 3px;
  color: var(--muted);
  font-size: 11px;
}

.player-copy,
.player-edit,
.player-delete {
  border-left: 1px solid var(--line);
  font-size: 16px;
}

.player-copy {
  background: rgba(21, 184, 166, 0.12);
  color: var(--accent-2);
}

.player-edit {
  background: rgba(79, 163, 255, 0.12);
  color: var(--accent);
}

.player-delete {
  background: rgba(241, 92, 92, 0.12);
  color: #ffb8b8;
  font-size: 18px;
}

.player-row-main .player-row-languages {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 5px;
}

.player-lang {
  display: grid;
  justify-items: center;
  gap: 3px;
  min-width: 0;
}

.player-row-main .player-lang-label {
  margin-top: 0;
  overflow: hidden;
  max-width: 44px;
  color: var(--muted);
  font-size: 10px;
  font-weight: 700;
  text-overflow: ellipsis;
  text-transform: uppercase;
  white-space: nowrap;
}

.player-row-main .player-lang-box {
  margin-top: 0;
  width: 18px;
  height: 18px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--panel-3);
}

.player-lang-box.is-live {
  border-color: rgba(241, 92, 92, 0.5);
  background: var(--danger);
  box-shadow: 0 0 0 2px rgba(241, 92, 92, 0.22);
}

.player-lang-box.is-stale {
  border-color: rgba(243, 201, 79, 0.5);
  background: var(--warn);
  animation: player-lang-blink 1s step-start infinite;
}

.player-lang-box.is-embed {
  border-style: dashed;
  border-color: var(--muted);
  background: transparent;
}

@keyframes player-lang-blink {
  50% {
    opacity: 0.2;
  }
}

.share-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 6px;
  min-width: 0;
}

.share-input {
  width: 100%;
  min-width: 0;
  min-height: 32px;
  border: 1px solid var(--line);
  border-radius: 7px;
  padding: 6px 8px;
  overflow: hidden;
  background: #0d1118;
  color: var(--muted);
  font-size: 11px;
  text-overflow: ellipsis;
  white-space: nowrap;
  outline: none;
}

.copy-share-button {
  min-height: 32px;
  padding: 6px 8px;
  font-size: 11px;
}

.stage-shell {
  display: grid;
  place-items: center;
  min-width: 0;
  height: 100dvh;
  padding: 18px;
  overflow: hidden;
  background: #080a0d;
}

.stage-grid {
  --tile-w: min(
    calc((100vw - 320px - 36px - 16px) / 2),
    calc((100dvh - 36px - 16px) / 2 * 1.78)
  );
  --tile-h: min(
    calc((100dvh - 36px - 16px) / 2),
    calc((100vw - 320px - 36px - 16px) / 2 / 1.78)
  );
  display: grid;
  width: 100%;
  height: 100%;
  min-width: 0;
  min-height: 0;
  gap: 16px;
  place-content: start;
  justify-content: start;
  align-content: start;
}

.stage-grid[data-count="0"] {
  grid-template-columns: 1fr;
}

.stage-grid[data-count="1"] {
  grid-template-columns: 1fr;
  grid-template-rows: 1fr;
  place-content: center;
}

.stage-grid[data-count="2"] {
  grid-template-columns: repeat(2, var(--tile-w));
  grid-template-rows: var(--tile-h);
}

.stage-grid[data-count="3"] {
  grid-template-columns: repeat(2, var(--tile-w));
  grid-template-rows: repeat(2, var(--tile-h));
}

.stage-grid[data-count="4"] {
  grid-template-columns: repeat(2, var(--tile-w));
  grid-template-rows: repeat(2, var(--tile-h));
}

.stage-grid[data-count="1"] .stream-card {
  width: min(1120px, 100%);
  height: min(660px, 100%);
  place-self: center;
}

.stage-grid[data-count="3"] .stream-card:nth-child(3) {
  grid-column: 1;
  grid-row: 2;
}

.empty-stage {
  display: grid;
  place-items: center;
  border: 1px dashed var(--line);
  border-radius: 8px;
  color: var(--muted);
  background: var(--panel-2);
}

.stream-card {
  container-type: inline-size;
  min-width: 0;
  min-height: 0;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: #090d13;
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.36);
}

.stream-card.stream-ok {
  border-color: rgba(57, 199, 111, 0.38);
}

.stream-card.stream-ok .stream-header {
  background: linear-gradient(90deg, rgba(28, 109, 68, 0.82), rgba(20, 34, 28, 0.96));
}

.stream-card.stream-checking {
  border-color: rgba(241, 92, 92, 0.46);
}

.stream-card.stream-checking .stream-header {
  background: linear-gradient(90deg, rgba(121, 43, 47, 0.84), rgba(41, 22, 27, 0.96));
}

.stream-card.stream-missing {
  border-color: rgba(241, 92, 92, 0.46);
}

.stream-card.stream-missing .stream-header {
  background: linear-gradient(90deg, rgba(132, 38, 44, 0.9), rgba(46, 20, 26, 0.98));
}

.stream-card.stream-missing .status-line {
  background: rgba(72, 22, 28, 0.82);
  color: #ffc4c4;
}

.stream-header {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
  min-height: 54px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--line);
  background: #141923;
}

.stream-title {
  margin: 0;
  overflow: hidden;
  font-size: clamp(17px, 1.1vw, 26px);
  font-weight: 650;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.stream-url {
  display: block;
  max-width: 100%;
  margin-top: 2px;
  overflow: hidden;
  color: var(--muted);
  font-size: clamp(10px, 0.7vw, 14px);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sound-badge {
  align-self: start;
  padding: 7px 12px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  color: var(--muted);
  font-size: clamp(11px, 0.75vw, 14px);
  font-weight: 600;
  white-space: nowrap;
}

/* Admin-only controls (see .monitor-screen.public-view rules below) — replace
   .sound-badge in that same header slot so viewers keep seeing sound status,
   while admins get a toggle for whether this player is shown on the public
   share page at all, plus the public-page sort number. Grouped in one flex
   wrapper (.stream-header-controls) so the header grid always sees exactly
   one child in its second column, regardless of which controls are hidden. */
.stream-header-controls {
  display: flex;
  align-items: center;
  gap: 8px;
}

.visibility-toggle-button {
  align-self: center;
  padding: 7px 12px;
  border: 1px solid #9aa6b9;
  border-radius: 999px;
  background: #9aa6b9;
  color: #0b0d10;
  font-size: clamp(11px, 0.75vw, 14px);
  font-weight: 600;
  white-space: nowrap;
}

.visibility-toggle-button.is-visible {
  border-color: #1c6d44;
  background: #1c6d44;
  color: #ffffff;
}

.public-sort-select {
  align-self: center;
  min-height: 34px;
  min-width: 52px;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 5px 8px;
  background: var(--panel-3);
  color: var(--text);
  font-size: clamp(11px, 0.75vw, 14px);
  font-weight: 600;
  text-align: center;
}

.monitor-screen.public-view .visibility-toggle-button,
.monitor-screen.public-view .public-sort-select {
  display: none !important;
}

.monitor-screen.active:not(.public-view) .sound-badge {
  display: none;
}

/* Публичная страница: звук может быть включён только у одного плеера
   (StreamSoundCoordinator в player.js). Кнопка плеера, у которого звук сейчас
   включён, подсвечивается тем же зелёным, что и «Открыто для просмотра». */
.monitor-screen.public-view .mute-button.is-sound-on,
.monitor-screen.public-view .embed-sound-toggle.is-sound-on {
  border-color: #1c6d44;
  background: #1c6d44;
  color: #ffffff;
}

.quality-select,
.stream-select {
  min-height: 40px;
  min-width: 92px;
  max-width: 136px;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 5px 10px;
  background: var(--panel-3);
  color: var(--text);
  font-weight: 650;
}

.quality-select:disabled,
.stream-select:disabled {
  opacity: 0.55;
  cursor: default;
}

.quality-select.quality-static,
.stream-select.quality-static {
  appearance: none;
  padding-right: 10px;
  color: var(--muted);
  pointer-events: none;
}

.stream-main {
  min-width: 0;
  min-height: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) clamp(200px, 27%, 320px);
  background: #000;
}

.video-wrap {
  position: relative;
  min-height: 0;
  overflow: hidden;
  background: #000;
}

.video-wrap video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: #000;
}

.embed-wrap {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
  background: #000;
}

.embed-wrap[hidden] {
  display: none;
}

.embed-frame-slot {
  position: relative;
  min-height: 0;
  flex: 1 1 auto;
  background: #000;
}

.embed-frame-slot iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

.embed-sound-toggle {
  position: absolute;
  right: 8px;
  bottom: 8px;
  z-index: 2;
  min-height: 30px;
  padding: 5px 10px;
  font-size: 11px;
}

.embed-lang-switch {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 0 14px 10px;
}

.embed-lang-switch[hidden] {
  display: none;
}

.embed-lang-switch-btn {
  min-height: 28px;
  padding: 4px 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--panel-3);
  color: var(--muted);
  font-size: 11px;
  font-weight: 650;
}

.embed-lang-switch-btn.is-active {
  border-color: var(--accent);
  color: var(--text);
  background: rgba(79, 163, 255, 0.16);
}

/* meter-section/stats are hls.js-only readouts (audio analyser, decoded frames, etc.) —
   nothing to show for an iframe embed, so hide them and let stream-note-title (the
   fetched video title) be the only content of the sidebar instead. */
.is-embed-card .mute-button,
.is-embed-card .volume-slider,
.is-embed-card .volume-value,
.is-embed-card .quality-select,
.is-embed-card .play-button,
.is-embed-card .center-play,
.is-embed-card .status-line,
.is-embed-card .stats,
.is-embed-card .meter-section,
.stream-card.showing-embed .mute-button,
.stream-card.showing-embed .volume-slider,
.stream-card.showing-embed .volume-value,
.stream-card.showing-embed .quality-select,
.stream-card.showing-embed .play-button,
.stream-card.showing-embed .center-play,
.stream-card.showing-embed .status-line,
.stream-card.showing-embed .meter-section {
  display: none;
}

.center-play {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 2;
  width: clamp(52px, 4.8vw, 88px);
  height: clamp(52px, 4.8vw, 88px);
  border: 1px solid rgba(255, 255, 255, 0.42);
  border-radius: 50%;
  transform: translate(-50%, -50%);
  background: rgba(10, 12, 16, 0.68);
  color: #fff;
  font-size: clamp(22px, 2.3vw, 36px);
  line-height: 1;
}

.stream-card.is-playing .center-play,
.stream-card.is-playing .status-line {
  display: none;
}

/* Public page: while a hall waits for its stream to start, show just the
   poster (no ▶ / «Нет потока» over it) — the yellow dot says it all. */
.monitor-screen.public-view .stream-card.stream-waiting .center-play,
.monitor-screen.public-view .stream-card.stream-waiting .status-line {
  display: none;
}

.status-line {
  position: absolute;
  left: 8px;
  bottom: 8px;
  z-index: 2;
  max-width: calc(100% - 16px);
  padding: 4px 7px;
  overflow: hidden;
  border-radius: 6px;
  background: rgba(0, 0, 0, 0.62);
  color: rgba(255, 255, 255, 0.86);
  font-size: 10px;
  text-overflow: ellipsis;
  white-space: nowrap;
  pointer-events: none;
}

.stream-body {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  gap: 7px;
  min-width: 0;
  min-height: 0;
  padding: 8px;
  border-top: 0;
  background: #0e131a;
}

.stream-side {
  min-width: 0;
  min-height: 0;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  border-left: 1px solid var(--line);
  background: #0e131a;
}

.meter-section {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  justify-items: center;
  gap: 4px;
  min-width: 0;
  height: 100%;
}

.meter-title {
  color: var(--muted);
  font-size: 8px;
  font-weight: 600;
  white-space: nowrap;
}

.meter-row {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 4px;
  width: 100%;
  min-height: 104px;
  height: 100%;
}

.meter-lang {
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  justify-items: center;
  gap: 3px;
  height: 100%;
}

.meter-lang-track {
  position: relative;
  width: 10px;
  min-height: 0;
  height: 100%;
  overflow: hidden;
  border: 1px solid #465266;
  border-radius: 3px;
  background:
    linear-gradient(
      to top,
      rgba(57, 199, 111, 0.22) 0%,
      rgba(57, 199, 111, 0.22) 80%,
      rgba(243, 201, 79, 0.24) 80%,
      rgba(243, 201, 79, 0.24) 90%,
      rgba(241, 92, 92, 0.25) 90%,
      rgba(241, 92, 92, 0.25) 100%
    );
}

.meter-lang-fill {
  position: absolute;
  left: 1px;
  right: 1px;
  bottom: 1px;
  height: var(--level, 0%); /* set from JS (setCardMeterLevel) */
  border-radius: 2px;
  background: var(--ok);
  transition: height 55ms linear;
}

.meter-lang-fill.level-green {
  background: var(--ok);
}

.meter-lang-fill.level-yellow {
  background: var(--warn);
}

.meter-lang-fill.level-red {
  background: var(--danger);
}

.meter-lang-dot,
.lang-segment {
  display: none; /* phone layout only */
}

.meter-lang-label {
  color: var(--muted);
  font-size: 8px;
  font-weight: 700;
  text-transform: uppercase;
  white-space: nowrap;
}

.meter-lang.is-embed {
  grid-template-rows: auto auto;
  opacity: 0.7;
}

.meter-lang-note {
  color: var(--muted);
  font-size: 7px;
  font-style: italic;
  text-transform: uppercase;
  white-space: nowrap;
}

.stats {
  min-width: 0;
  display: grid;
  align-content: center;
  gap: 1px;
}

.stats div {
  min-width: 0;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 5px;
  align-items: center;
  min-height: clamp(14px, 1.55vh, 22px);
  border-bottom: 1px solid rgba(255, 255, 255, 0.045);
  font-size: clamp(10px, 0.68vw, 14px);
}

.stats div:last-child {
  border-bottom: 0;
}

.stats span {
  color: #7b8799;
  white-space: nowrap;
}

.stats b {
  min-width: 0;
  overflow: hidden;
  color: #dfe7f3;
  font-weight: 600;
  text-align: right;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.stream-note-panel {
  display: grid;
  gap: 3px;
  min-height: 74px;
  padding: 8px;
  overflow: hidden;
  border-top: 1px solid var(--line);
  background: #141923;
}

.stream-clock {
  color: var(--muted);
  font-size: clamp(10px, 0.7vw, 13px);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.stream-note-state {
  color: var(--muted);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.05em;
}

.stream-note-state.is-live {
  color: var(--danger);
}

.stream-note-title {
  color: var(--text);
  font-size: 12px;
  font-weight: 700;
  line-height: 1.22;
}

.stream-note-next {
  color: var(--muted);
  font-size: 12px;
  line-height: 1.2;
}

.stream-controls {
  display: grid;
  grid-template-columns: minmax(78px, 0.75fr) minmax(118px, 1fr) minmax(82px, 1.2fr) 42px minmax(84px, auto) minmax(92px, auto) 38px;
  gap: 8px;
  align-items: center;
  min-height: 56px;
  padding: 8px 10px;
  border-top: 1px solid var(--line);
  background: #141923;
}

.control-button {
  min-height: 38px;
  border: 1px solid var(--line);
  background: var(--panel-3);
  font-size: clamp(12px, 0.85vw, 16px);
}

.play-button {
  min-width: 0;
}

.mute-button {
  min-width: 0;
}

.fullscreen-button {
  min-width: 38px;
  padding: 0;
}

.volume-slider {
  width: 100%;
  accent-color: var(--accent-2);
}

.volume-value {
  color: var(--muted);
  font-size: clamp(12px, 0.9vw, 16px);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

@container (max-width: 760px) {
  .stream-header {
    min-height: 48px;
    padding: 8px 12px;
  }

  .stream-title {
    font-size: 18px;
  }

  .stream-url {
    font-size: 11px;
  }

  .sound-badge {
    padding: 6px 10px;
    font-size: 11px;
  }

  .stream-main {
    grid-template-columns: minmax(0, 1fr) minmax(172px, 26%, 210px);
  }

  .stream-body {
    grid-template-columns: 38px minmax(0, 1fr);
    gap: 6px;
    padding: 7px;
  }

  .meter-title {
    font-size: 7px;
  }

  .meter-row {
    min-height: 82px;
    gap: 3px;
  }

  .meter-lang-track {
    width: 8px;
  }

  .meter-lang-label {
    font-size: 7px;
  }

  .stats div {
    min-height: 13px;
    gap: 4px;
    font-size: 10px;
  }

  .stream-note-panel {
    min-height: 56px;
    padding: 7px;
  }

  .stream-clock {
    font-size: 10px;
  }

  .stream-note-state,
  .stream-note-title,
  .stream-note-next {
    font-size: 12px;
    line-height: 1.15;
  }

  .stream-controls {
    grid-template-columns: minmax(68px, 0.75fr) minmax(108px, 1fr) minmax(70px, 1fr) 34px minmax(68px, 0.7fr) minmax(76px, 0.8fr) 34px;
    gap: 6px;
    min-height: 48px;
    padding: 6px 7px;
  }

  .control-button {
    min-height: 34px;
    padding: 5px 7px;
    font-size: 12px;
  }

  .quality-select,
  .stream-select {
    min-width: 0;
    max-width: none;
    min-height: 34px;
    padding: 4px 7px;
    font-size: 14px;
  }

  .volume-value {
    font-size: 12px;
  }

  .fullscreen-button {
    min-width: 34px;
  }
}

@container (max-width: 560px) {
  .stream-side {
    grid-template-rows: 1fr;
  }

  /* Hidden here to save space for meter/stats on regular hls cards — but for
     embed cards (VK/Rutube/YouTube) the note panel (video title) is the ONLY
     sidebar content (meter/stats are already display:none via .is-embed-card),
     so it must stay visible regardless of card width. */
  .stream-note-panel {
    display: none;
  }

  .is-embed-card .stream-side,
  .stream-card.showing-embed .stream-side {
    grid-template-rows: auto;
  }

  .is-embed-card .stream-note-panel,
  .stream-card.showing-embed .stream-note-panel {
    display: grid;
  }

  .stream-controls {
    grid-template-columns: minmax(62px, 0.8fr) minmax(96px, 1fr) minmax(70px, 1fr) minmax(64px, 0.7fr) minmax(76px, 0.8fr) 34px;
  }

  .volume-value {
    display: none;
  }
}

@container (max-width: 440px) {
  .stream-main {
    grid-template-columns: 1fr;
    grid-template-rows: minmax(0, 1fr) auto;
  }

  .stream-side {
    grid-template-rows: auto;
    border-left: 0;
    border-top: 1px solid var(--line);
  }
}

/* Fullscreen: a plain top-to-bottom stack, nothing overlaid —
   header / [video | meter+stats] / schedule line / controls.
   (Before 2026-09-24 the side panel and the controls were absolute overlays:
   the side panel covered the top-right of the picture and the controls sat on
   top of the relocated schedule panel.) The video area takes the stream's real
   frame ratio (--video-ar, set by StreamPlayer from videoWidth/videoHeight),
   capped so the whole stack fits the screen; the main row is sized to that
   and the side panel is bottom-aligned (align-items: end) — so its bottom is
   exactly the bottom of the picture. */
.stream-card:fullscreen {
  --fs-chrome: 250px; /* header + schedule line + controls + paddings */
  width: 100vw;
  height: 100vh;
  border: 0;
  border-radius: 0;
  grid-template-rows: auto minmax(0, 1fr) auto auto;
  background: #000;
}

.stream-card:fullscreen .stream-header {
  min-height: 54px;
}

.stream-card:fullscreen .stream-main {
  grid-template-columns: minmax(0, 1fr) 320px;
  grid-template-rows: auto;
  align-content: center;
  align-items: end;
  column-gap: 14px;
  padding: 12px 18px;
}

.stream-card:fullscreen .video-wrap {
  justify-self: center;
  width: min(100%, calc((100vh - var(--fs-chrome)) * var(--video-ar, 1.7778)));
  aspect-ratio: var(--video-ar, 1.7778);
  max-height: calc(100vh - var(--fs-chrome));
}

.stream-card:fullscreen .stream-side {
  align-self: end;
  max-height: calc(100vh - var(--fs-chrome));
  overflow: auto;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 8px;
  background: rgba(10, 14, 20, 0.74);
}

.stream-card:fullscreen > .stream-note-panel {
  max-width: none;
  padding: 8px 18px;
  background: #000;
  border-top: 0;
}

.stream-card:fullscreen .stream-controls {
  margin: 0 18px 18px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 8px;
  background: rgba(10, 14, 20, 0.74);
}

.modal {
  width: min(580px, calc(100vw - 28px));
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 0;
  background: var(--panel);
  color: var(--text);
  box-shadow: 0 28px 70px rgba(0, 0, 0, 0.45);
}

.modal::backdrop {
  background: rgba(0, 0, 0, 0.68);
}

.modal-panel {
  display: grid;
  gap: 14px;
  padding: 16px;
}

.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
}

.modal-header h2 {
  margin: 0;
  font-size: 20px;
}

.icon-button {
  width: 34px;
  padding: 0;
  border: 1px solid var(--line);
  background: var(--panel-3);
  font-size: 22px;
  line-height: 1;
}

.sidebar-action-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.sidebar-action-row .full-width {
  width: auto;
  flex: 1;
}

.help-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 20px;
  height: 20px;
  min-height: 0;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--muted);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  vertical-align: middle;
}

.help-icon:hover,
.help-icon:focus-visible {
  color: var(--accent);
  outline: none;
}

.help-popover {
  display: none;
  position: fixed;
  z-index: 80;
  width: max-content;
  max-width: 320px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--panel-3);
  color: var(--text);
  font-size: 13px;
  font-weight: 400;
  line-height: 1.45;
  box-shadow: 0 16px 40px var(--shadow);
}

.help-popover.is-visible {
  display: block;
}

.help-popover p {
  margin: 0 0 8px;
}

.help-popover p:last-child {
  margin-bottom: 0;
}

.help-popover ul {
  margin: 0 0 8px;
  padding-left: 18px;
}

.help-popover ul:last-child {
  margin-bottom: 0;
}

.help-popover .help-warn {
  color: var(--warn);
}

.field {
  display: grid;
  gap: 6px;
  color: var(--muted);
  font-size: 13px;
  font-weight: 700;
}

.field input {
  min-height: 40px;
  border: 1px solid var(--line);
  border-radius: 7px;
  padding: 8px 10px;
  background: #0d1118;
  color: var(--text);
  outline: none;
}

.schedule-upload-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.schedule-upload-label {
  display: inline-flex;
  align-items: center;
  cursor: pointer;
}

.schedule-upload-row select {
  min-height: 40px;
  border: 1px solid var(--line);
  border-radius: 7px;
  padding: 8px 10px;
  background: var(--panel-3);
  color: var(--text);
  font-weight: 600;
  font-size: 13px;
}

.schedule-status {
  color: var(--muted);
  font-size: 12px;
  font-weight: 500;
}

.schedule-status.is-error {
  color: var(--danger);
}

.stream-rows {
  display: grid;
  gap: 6px;
}

.stream-row {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding-bottom: 8px;
  border-bottom: 1px dashed var(--line-soft);
}

.stream-row:last-child {
  border-bottom: none;
  padding-bottom: 0;
}

.stream-row-main {
  display: grid;
  grid-template-columns: 74px minmax(0, 1fr) 32px;
  gap: 6px;
}

.stream-row input {
  min-height: 38px;
  min-width: 0;
  border: 1px solid var(--line);
  border-radius: 7px;
  padding: 7px 9px;
  background: #0d1118;
  color: var(--text);
  font-size: 13px;
  font-weight: 500;
  outline: none;
}

.stream-row-remove {
  min-height: 38px;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: var(--panel-3);
  color: var(--muted);
  font-size: 18px;
  line-height: 1;
}

.stream-row-meta {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.stream-row-meta-line {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.stream-row-meta-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  min-width: 0;
}

.stream-row-badge {
  flex-shrink: 0;
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--panel-3);
  color: var(--muted);
  font-size: 11px;
  font-weight: 650;
  white-space: nowrap;
}

.stream-row-badge.badge-vk { background: rgba(79, 163, 255, 0.16); color: var(--accent); }
.stream-row-badge.badge-rutube { background: rgba(243, 201, 79, 0.16); color: var(--warn); }
.stream-row-badge.badge-youtube { background: rgba(241, 92, 92, 0.16); color: var(--danger); }
.stream-row-badge.badge-direct,
.stream-row-badge.badge-hls { background: rgba(57, 199, 111, 0.16); color: var(--ok); }

.stream-row-hint {
  min-width: 0;
  flex: 1 1 auto;
  overflow: hidden;
  color: var(--muted);
  font-size: 11px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.stream-row-preview-btn,
.stream-row-resolve-btn {
  flex-shrink: 0;
  min-height: 28px;
  padding: 4px 10px;
  font-size: 11px;
  white-space: nowrap;
}

.stream-row-preview {
  aspect-ratio: 16 / 9;
  max-width: 100%;
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
  background: #000;
}

.stream-row-preview iframe {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

.modal-error {
  min-height: 16px;
  margin-top: -4px;
  color: #ffb8b8;
  font-size: 13px;
  font-weight: 600;
}

.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

@media (max-width: 980px) {
  body {
    overflow: auto;
  }

  .app-shell {
    height: auto;
    min-height: 100dvh;
  }

  .monitor-screen.active {
    grid-template-columns: 1fr;
  }

  .sidebar {
    height: auto;
  }

  .stage-shell {
    height: auto;
    min-height: 60dvh;
    padding: 12px;
  }

  .stage-grid {
    --tile-w: 100%;
    --tile-h: auto;
    width: 100%;
    height: auto;
    min-height: 56dvh;
  }

  .stage-grid[data-count="2"],
  .stage-grid[data-count="3"],
  .stage-grid[data-count="4"],
  .stage-grid[data-count="5"],
  .stage-grid[data-count="6"] {
    grid-template-columns: 1fr;
    grid-template-rows: none;
  }

  .stage-grid[data-count="3"] .stream-card:nth-child(3) {
    grid-column: auto;
    grid-row: auto;
  }

  .stream-main {
    grid-template-columns: 1fr;
  }

  .stream-side {
    border-left: 0;
    border-top: 1px solid var(--line);
  }
}

@media (max-width: 720px) {
  .home-header {
    grid-template-columns: 1fr;
    align-items: start;
  }

  .home-header h1 {
    order: -1;
  }

  .status-text {
    text-align: left;
  }

  .top-actions,
  .sidebar-status-row {
    align-items: flex-start;
    flex-direction: column;
  }

  .events-list {
    grid-template-columns: 1fr;
    padding: 16px;
  }

  .stream-controls {
    grid-template-columns: 1fr 1fr;
  }

  .volume-slider,
  .volume-value,
  .fullscreen-button,
  .quality-select,
  .stream-select {
    display: none;
  }

  .sound-badge {
    justify-self: start;
  }
}

/* BEGIN MONITORING UI HOTFIX */
.home-header {
  min-height: 64px;
  gap: 14px;
  padding: 12px 22px;
}

.home-header h1 {
  font-size: 22px;
  font-weight: 650;
}

.primary-button,
.secondary-button,
.ghost-button,
.danger-button,
.control-button {
  min-height: 32px;
  padding: 7px 10px;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.15;
}

.events-list {
  grid-template-columns: repeat(auto-fill, minmax(320px, 360px));
  gap: 14px;
  height: calc(100dvh - 64px);
  padding: 22px 28px;
}

.event-card {
  grid-template-rows: auto auto auto auto auto;
  gap: 6px;
  width: min(360px, calc(100vw - 56px));
  min-height: 240px;
  aspect-ratio: auto;
  padding: 10px;
}

.empty-card {
  width: min(360px, calc(100vw - 56px));
}

.event-count {
  gap: 6px;
  padding: 6px 9px;
}

.event-count b {
  font-size: 22px;
}

.event-count span {
  font-size: 12px;
  font-weight: 700;
}

.event-name {
  min-height: 48px;
  max-height: 92px;
  padding: 7px 8px;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.25;
  resize: none;
  overflow-y: auto;
}

.event-meta {
  font-size: 10px;
  line-height: 1.2;
}

.event-share {
  gap: 4px;
  font-size: 9px;
  font-weight: 650;
  line-height: 1.2;
}

.share-row {
  gap: 6px;
}

.share-input {
  min-height: 32px;
  padding: 6px 8px;
  font-size: 10px;
}

.copy-share-button {
  min-height: 32px;
  padding: 5px 7px;
  font-size: 10px;
}

.event-actions {
  grid-template-columns: minmax(0, 1fr) 42px minmax(82px, auto);
  gap: 6px;
}

.event-actions .secondary-button,
.event-actions .danger-button {
  min-height: 42px;
  font-size: 13px;
}

.event-actions .copy-event {
  padding: 0;
  font-size: 18px;
  color: var(--accent-2);
  border-color: rgba(21, 184, 166, 0.32);
  background: rgba(21, 184, 166, 0.11);
}

.stage-shell {
  position: relative;
}

.public-start-notice {
  position: fixed;
  left: 50%;
  bottom: 20px;
  z-index: 50;
  display: none;
  max-width: calc(100vw - 32px);
  transform: translateX(-50%);
  pointer-events: none;
}

.public-start-notice.is-visible {
  display: block;
}

.public-start-notice button {
  min-height: 44px;
  border: 1px solid rgba(79, 163, 255, 0.48);
  border-radius: 999px;
  padding: 10px 18px;
  background: rgba(79, 163, 255, 0.96);
  color: #04111f;
  font-size: 14px;
  font-weight: 700;
  box-shadow: 0 14px 36px rgba(0, 0, 0, 0.36);
  pointer-events: auto;
}

.stream-title {
  font-size: clamp(15px, 0.95vw, 22px);
  font-weight: 620;
}

.stream-url {
  font-size: clamp(9px, 0.62vw, 12px);
}

.sound-badge {
  padding: 6px 10px;
  font-size: clamp(10px, 0.66vw, 12px);
}

.stats div {
  font-size: clamp(9px, 0.62vw, 12px);
}

.stream-note-state,
.stream-note-title,
.stream-note-next {
  font-size: 12px;
}

.stream-note-title {
  font-weight: 700;
}

.stream-clock {
  font-size: clamp(9px, 0.62vw, 12px);
}

.stage-pager {
  position: absolute;
  left: 50%;
  bottom: 16px;
  z-index: 30;
  display: flex;
  align-items: center;
  gap: 8px;
  max-width: calc(100% - 32px);
  padding: 8px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 8px;
  background: rgba(17, 22, 30, 0.9);
  box-shadow: 0 14px 36px rgba(0, 0, 0, 0.34);
  transform: translateX(-50%);
}

.stage-pager[hidden] {
  display: none;
}

.stage-pager button {
  min-width: 42px;
}

.stage-pager button:disabled {
  cursor: default;
  opacity: 0.45;
}

.stage-pager span {
  min-width: 58px;
  color: var(--muted);
  font-size: 12px;
  font-weight: 700;
  text-align: center;
  white-space: nowrap;
}

.stage-grid.has-pager:not(.overview-grid) {
  padding-bottom: 68px;
  --tile-w: min(
    calc((100vw - 320px - 36px - 16px) / 2),
    calc((100dvh - 36px - 16px - 68px) / 2 * 1.78)
  );
  --tile-h: min(
    calc((100dvh - 36px - 16px - 68px) / 2),
    calc((100vw - 320px - 36px - 16px) / 2 / 1.78)
  );
}

.monitor-screen.public-view .stage-grid.has-pager:not(.overview-grid) {
  --tile-w: min(
    calc((100vw - 36px - 16px) / 2),
    calc((100dvh - 36px - 16px - 68px) / 2 * 1.78)
  );
  --tile-h: min(
    calc((100dvh - 36px - 16px - 68px) / 2),
    calc((100vw - 36px - 16px) / 2 / 1.78)
  );
}

.monitor-screen.public-view .stage-grid[data-mode="page"][data-count="5"],
.monitor-screen.public-view .stage-grid[data-mode="page"][data-count="6"] {
  --tile-w: min(
    calc((100vw - 36px - 32px) / 3),
    calc((100dvh - 36px - 16px) / 2 * 1.78)
  );
  --tile-h: min(
    calc((100dvh - 36px - 16px) / 2),
    calc((100vw - 36px - 32px) / 3 / 1.78)
  );
  grid-template-columns: repeat(3, var(--tile-w));
  grid-template-rows: repeat(2, var(--tile-h));
}

.monitor-screen.public-view .stage-grid.has-pager[data-mode="page"][data-count="5"],
.monitor-screen.public-view .stage-grid.has-pager[data-mode="page"][data-count="6"] {
  --tile-w: min(
    calc((100vw - 36px - 32px) / 3),
    calc((100dvh - 36px - 16px - 68px) / 2 * 1.78)
  );
  --tile-h: min(
    calc((100dvh - 36px - 16px - 68px) / 2),
    calc((100vw - 36px - 32px) / 3 / 1.78)
  );
}

.stage-grid.overview-grid {
  grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr));
  grid-auto-rows: clamp(130px, 15.5vh, 168px);
  grid-template-rows: none;
  align-content: start;
  justify-content: stretch;
  place-content: start stretch;
  overflow: auto;
  padding-bottom: 72px;
}

.stage-grid.overview-grid .stream-card {
  width: 100%;
  height: 100%;
}

.stage-grid.overview-grid .stream-card:nth-child(3) {
  grid-column: auto;
  grid-row: auto;
}

.stream-card-compact {
  grid-template-rows: auto minmax(0, 1fr);
}

.stream-card-compact .stream-header {
  min-height: 34px;
  padding: 6px 9px;
}

.stream-card-compact .stream-title {
  font-size: clamp(12px, 0.72vw, 15px);
  font-weight: 620;
}

.stream-card-compact .stream-url {
  margin-top: 1px;
  font-size: 9px;
}

.stream-card-compact .sound-badge,
.stream-card-compact .stream-controls,
.stream-card-compact .stream-note-panel {
  display: none;
}

.stream-card-compact .stream-main {
  grid-template-columns: minmax(0, 1fr) 32px;
}

.stream-card-compact.is-playing .video-wrap::after {
  content: "Эфир";
  position: absolute;
  left: 8px;
  top: 8px;
  z-index: 3;
  border-radius: 999px;
  padding: 4px 8px;
  background: rgba(57, 199, 111, 0.16);
  color: #b8ffd4;
  font-size: 10px;
  font-weight: 800;
}

.stream-card-compact .stream-side {
  border-left: 1px solid var(--line);
}

.stream-card-compact .stream-body {
  grid-template-columns: 1fr;
  padding: 5px 3px;
}

.stream-card-compact .stats {
  display: none;
}

.stream-card-compact .meter-section {
  gap: 2px;
}

.stream-card-compact .meter-row {
  min-height: 58px;
  gap: 2px;
}

.stream-card-compact .meter-title {
  font-size: 6px;
}

.stream-card-compact .meter-lang-track {
  width: 6px;
  border-radius: 2px;
}

.stream-card-compact .meter-lang-label {
  display: none;
}

.stream-card-compact .center-play {
  width: 34px;
  height: 34px;
  font-size: 16px;
}

.stream-card-compact .status-line {
  right: 8px;
  max-width: calc(100% - 16px);
  padding: 3px 6px;
  font-size: 9px;
}
/* END MONITORING UI HOTFIX */

/* «Всё расписание» — full session list opened from .stream-note-panel
   (renderScheduleList() in app.js). It is an overlay that opens UPWARD over
   the video (bottom: 100% of the panel), not an in-flow block: cards on the
   public page have a fixed height, so an in-flow list squeezed the video to
   zero. Its max-height is set from JS to the height of .stream-main. */
.stream-note-panel.has-schedule-list {
  position: relative;
  overflow: visible;
}
.schedule-toggle {
  justify-self: start;
  margin-top: 4px;
  padding: 3px 9px;
  min-height: 0;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--panel-3);
  color: var(--muted);
  font-size: 11px;
  font-weight: 700;
  cursor: pointer;
}

.schedule-toggle-short {
  display: none;
}

.schedule-toggle:hover,
.schedule-toggle[aria-expanded="true"] {
  color: var(--text);
  border-color: var(--muted);
}

.schedule-list {
  position: absolute;
  left: 6px;
  right: 6px;
  bottom: calc(100% + 4px);
  z-index: 5;
  display: grid;
  align-content: start;
  gap: 2px;
  max-height: 320px;
  padding: 2px 8px 8px;
  overflow-y: auto;
  overscroll-behavior: contain;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #141923;
  box-shadow: 0 -8px 24px var(--shadow);
}

.schedule-list[hidden] {
  display: none;
}

.schedule-day {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 6px 0 3px;
  background: #141923;
  color: var(--muted);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

/* ✕ close button: a zero-height sticky row, so it takes no space and stays
   in the top-right corner while the list scrolls. */
.schedule-close-wrap {
  position: sticky;
  top: -2px;
  z-index: 3;
  height: 0;
}

.schedule-close {
  position: absolute;
  top: 3px;
  right: -4px;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: #232a36;
  color: var(--text);
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
}

.schedule-close:hover,
.schedule-close:focus-visible {
  background: #2f3847;
}

.schedule-day {
  top: -2px; /* cover the list's 2px top padding so rows don't peek above */
  padding-right: 28px;
}

.schedule-item {
  display: grid;
  grid-template-columns: 84px minmax(0, 1fr) auto;
  gap: 8px;
  align-items: baseline;
  padding: 4px 6px;
  border-left: 2px solid transparent;
  border-radius: 4px;
  color: var(--text);
  font-size: 12px;
  line-height: 1.25;
}

.schedule-time {
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.schedule-item.is-past {
  opacity: 0.45;
}

.schedule-item.is-live {
  border-left-color: var(--danger);
  background: rgba(241, 92, 92, 0.1);
  font-weight: 700;
}

.schedule-item.is-next {
  border-left-color: var(--accent);
  background: rgba(79, 163, 255, 0.08);
}

.schedule-badge {
  color: var(--danger);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* Schedule note panel visibility (regular HLS / mixed cards; embed-only cards
   keep using the panel for the fetched video title and are untouched):
   - no Excel schedule uploaded → no panel at all (no empty strip under video);
   - schedule uploaded → always visible, at any card width. The older
     `@container (max-width: 560px) { .stream-note-panel { display: none } }`
     rule dates from when the panel lived in the narrow side column; since
     relocateNotePanelForPublicView() moved it under the video it only hid the
     schedule from viewers on narrow cards (5–6 per row, laptops, phones).
   Compact overview cards still hide it (see .stream-card-compact). */
.stream-card:not(.is-embed-card):not(.showing-embed) > .stream-note-panel:not(.has-schedule) {
  display: none;
}

.stream-card:not(.stream-card-compact):not(.is-embed-card):not(.showing-embed) > .stream-note-panel.has-schedule {
  display: grid;
}

/* «Пример расписания (Excel)» — download link above «Создать плеер». */
.schedule-example-link {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  margin-bottom: 8px;
  text-decoration: none;
}

/* Narrow cards (5–6 per row, laptops): a 3-line schedule panel squeezed the
   video to a thin strip inside the fixed-height card. Collapse it to ONE line —
   state · title (ellipsis) · «Всё расписание» — and drop «Далее»; the full
   list is one click away. */
@container (max-width: 560px) {
  .stream-card:not(.stream-card-compact):not(.is-embed-card):not(.showing-embed) > .stream-note-panel.has-schedule {
    grid-template-columns: minmax(0, max-content) minmax(0, 1fr) max-content;
    align-items: center;
    gap: 6px;
    min-height: 0;
    padding: 4px 8px;
  }

  .stream-card > .stream-note-panel.has-schedule .stream-note-state,
  .stream-card > .stream-note-panel.has-schedule .stream-note-title {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-size: 11px;
  }

  .stream-card > .stream-note-panel.has-schedule .stream-note-next {
    display: none;
  }

  .stream-card > .stream-note-panel.has-schedule .schedule-toggle {
    margin-top: 0;
    padding: 2px 7px;
    font-size: 10px;
    white-space: nowrap;
  }

  .stream-card > .stream-note-panel.has-schedule .schedule-toggle-long {
    display: none;
  }

  .stream-card > .stream-note-panel.has-schedule .schedule-toggle-short {
    display: inline;
  }
}

/* Fit-to-screen page layout — layoutStageToFit() in app.js sets .fit-layout
   and --fit-card-w (page mode, screens > 980px). The card no longer has a
   fixed 16:9 OUTER box: the video area takes the stream's own ratio
   (--video-ar, 16:9 by default; embeds 16:9) so there are no black side bars,
   the card is as tall as its content, and the JS picks the widest card that
   still lets every row fit on screen. The side meter/stats column is
   `contain: size` so it never makes the row taller than the video.
   Fullscreen and the «Все потоки» overview keep their own rules. */
.monitor-screen .stage-grid.fit-layout[data-mode="page"] {
  /* Strict column count (--fit-cols from layoutStageToFit(): 1 / 2 for ≤4 /
     3): a wrapping flex row put 3 cards in a row whenever the height-bound
     card width was small enough (4 players on a wide window → 3 + 1). Each
     card spans two half-columns of (card + gap) / 2, so an incomplete last
     row can be centered by starting it on a half-column (set from JS). */
  display: grid;
  grid-template-columns: repeat(calc(var(--fit-cols, 2) * 2), calc((var(--fit-card-w, 640px) + 16px) / 2)) !important;
  grid-template-rows: none !important;
  grid-auto-rows: auto;
  justify-content: center;
  align-content: center;
  align-items: start;
  column-gap: 0;
  row-gap: 16px;
}

.monitor-screen .stage-grid.fit-layout[data-mode="page"] > .stream-card:not(:fullscreen) {
  flex: 0 0 var(--fit-card-w, 640px);
  width: var(--fit-card-w, 640px);
  grid-column-end: span 2;
  justify-self: center;
  height: auto;
  min-height: var(--fit-card-h, 0px);
  aspect-ratio: auto;
  place-self: auto;
  /* Column flex instead of auto grid rows: when --fit-card-h (the tallest
     card, set by layoutStageToFit()) makes a card taller than its content,
     the extra space must go to the schedule panel / above the controls —
     auto grid rows would spread it over the video row too. */
  display: flex;
  flex-direction: column;
}

.monitor-screen .stage-grid.fit-layout[data-mode="page"] > .stream-card:not(:fullscreen) > * {
  flex: 0 0 auto;
}

.monitor-screen .stage-grid.fit-layout[data-mode="page"] > .stream-card:not(:fullscreen) > .stream-note-panel {
  flex-grow: 1;
  align-content: start;
}

.monitor-screen .stage-grid.fit-layout[data-mode="page"] > .stream-card:not(:fullscreen) > .stream-controls {
  margin-top: auto;
}

.monitor-screen .stage-grid.fit-layout[data-mode="page"] > .stream-card:not(:fullscreen) .video-wrap {
  aspect-ratio: var(--video-ar, 1.7778);
}

.monitor-screen .stage-grid.fit-layout[data-mode="page"] > .stream-card:not(:fullscreen) .embed-wrap {
  aspect-ratio: 16 / 9;
}

.monitor-screen .stage-grid.fit-layout[data-mode="page"] > .stream-card:not(:fullscreen) .stream-side {
  contain: size;
  overflow: hidden;
}

/* Placeholder image («заглушка») — inside .video-wrap, above the <video>,
   below the play button / status line (both z-index 2). Visible while the card
   has no live picture (.has-picture is toggled by StreamPlayer), fades out
   when frames flow and back in when the stream drops. */
.video-poster {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: #000;
  opacity: 1;
  transition: opacity 0.45s ease;
  pointer-events: none;
}

.video-poster[hidden] {
  display: none;
}

.video-poster img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.stream-card.has-picture .video-poster {
  opacity: 0;
}

/* Keep the controls over the poster readable. */
.stream-card.has-poster:not(.has-picture) .status-line {
  background: rgba(10, 14, 20, 0.72);
}

/* Admin: event-wide poster (sidebar) and per-player poster (player dialog). */
.poster-panel {
  display: grid;
  gap: 6px;
}

.poster-upload-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.poster-thumb {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 64px;
  height: 36px;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 5px;
  background: #000;
  color: var(--muted);
  font-size: 10px;
}

.poster-thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.poster-thumb.is-empty {
  border-style: dashed;
  background: transparent;
}

.poster-upload-label {
  display: inline-flex;
  align-items: center;
  cursor: pointer;
}

.poster-hint {
  color: var(--muted);
  font-size: 11px;
}

/* --- Compact admin sidebar (2026-09-25) ---------------------------------
   Order: [← | event title] / status (only when non-empty) / share link /
   placeholder («заглушка») in one row / «Плееры» header with the Excel
   example link / [+ Создать плеер][Все сразу] / players list. Everything is
   tightened so more hall rows fit on screen — the players list is what
   matters here. */
.monitor-screen .sidebar {
  gap: 8px;
  padding: 10px;
}

.monitor-screen .sidebar-top {
  gap: 4px;
}

.sidebar-top-row {
  display: grid;
  grid-template-columns: 32px minmax(0, 1fr);
  gap: 6px;
  align-items: stretch;
}

.sidebar-back {
  min-height: 0;
  padding: 0;
  font-size: 16px;
}

.monitor-screen .event-title-input {
  min-height: 34px;
  padding: 5px 9px;
  font-size: 15px;
}

.monitor-screen .sidebar-status-row:has(.status-text:empty) {
  display: none;
}

.monitor-screen .sidebar-section-title {
  margin-top: 0;
  font-size: 10px;
}

.monitor-screen .share-panel {
  gap: 4px;
}

.monitor-screen .share-input,
.monitor-screen .copy-share-button {
  min-height: 28px;
}

/* placeholder panel:
     [thumb] [ЗАГЛУШКА ПЛЕЕРОВ ⓘ      ] [Загрузить ×]
     [thumb] [WebP · 1920×1080 · 101 КБ          ]
     [thumb] [JPG, PNG, WebP · до 1,5 МБ          ]
   .poster-panel-body is `display: contents` so its three lines become grid
   items and the meta/hint lines can run under the buttons (full width) —
   in a single cell the file size got cut off with an ellipsis. */
.monitor-screen .poster-panel {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas:
    "thumb title actions"
    "thumb meta  meta"
    "thumb hint  hint";
  column-gap: 8px;
  row-gap: 1px;
  align-items: center;
  padding: 6px 0;
  border-top: 1px solid var(--line-soft);
  border-bottom: 1px solid var(--line-soft);
}

.monitor-screen .poster-panel .poster-thumb {
  grid-area: thumb;
  align-self: center;
  width: 56px;
  height: 32px;
}

.poster-panel-body {
  display: contents;
}

.poster-panel-body .sidebar-section-title {
  grid-area: title;
  display: flex;
  align-items: center;
  gap: 2px;
  min-width: 0;
  white-space: nowrap;
}

.poster-panel-body .help-icon {
  width: 16px;
  height: 16px;
  font-size: 12px;
}

.poster-panel-body .poster-meta {
  grid-area: meta;
}

.poster-panel-body .poster-hint {
  grid-area: hint;
}

.poster-meta {
  overflow: hidden;
  color: var(--text);
  font-size: 11px;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.poster-meta.is-error {
  color: var(--danger);
  white-space: normal;
}

.poster-hint {
  color: var(--muted);
  font-size: 9.5px;
  line-height: 1.2;
  white-space: nowrap;
}

.poster-panel-actions {
  grid-area: actions;
  display: flex;
  gap: 4px;
}

.poster-panel-actions .poster-upload-label,
.poster-panel-actions .poster-remove-btn {
  min-height: 24px;
  padding: 2px 8px;
  font-size: 11.5px;
}

/* players header + actions right above the list */
.players-section {
  display: grid;
  gap: 5px;
}

.players-section-links {
  display: inline-flex;
  align-items: center;
  gap: 2px;
}

.small-link {
  color: var(--accent);
  font-size: 11px;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}

.small-link:hover {
  text-decoration: underline;
}

.players-section-links .help-icon {
  width: 16px;
  height: 16px;
  font-size: 12px;
}

.players-actions {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 6px;
  align-items: center;
}

.players-actions .primary-button,
.players-actions .secondary-button {
  min-height: 30px;
  padding: 5px 10px;
  font-size: 12.5px;
  white-space: nowrap;
}

/* denser player rows */
.monitor-screen .players-list {
  gap: 5px;
}

.monitor-screen .player-row {
  grid-template-columns: minmax(0, 1fr) 28px 28px 28px;
  border-radius: 7px;
}

.monitor-screen .player-row-main {
  padding: 6px 9px;
}

.monitor-screen .player-row-main strong {
  font-size: 13px;
}

.monitor-screen .player-row-main .player-row-languages {
  gap: 5px;
  margin-top: 3px;
}

.monitor-screen .player-row-main .player-lang {
  grid-auto-flow: column;
  align-items: center;
  gap: 3px;
}

.monitor-screen .player-row-main .player-lang-box {
  width: 13px;
  height: 13px;
  border-radius: 3px;
}

.monitor-screen .player-copy,
.monitor-screen .player-edit,
.monitor-screen .player-delete {
  font-size: 14px;
}

/* player dialog: placeholder meta + tiny hint */
.poster-field .poster-meta {
  margin-top: 2px;
}

/* ===== Phone layout of the public page (2026-09-26) =====================
   Enabled by layoutStageToFit() → layoutPhoneStage() in app.js (class
   .phone-layout on #stageGrid) for the public share page on phones (any
   model — sizes come from the real viewport): portrait ≤ 600px wide → one
   hall per row, 4 per screen; landscape ≤ 500px tall → 2×2. Each card:
       [ hall title — full width, one line with ellipsis              ]
       [ video 16:9 (--phone-video-w) | ● RU ▬▬▬ / ● EN ▬▬▬ (meters)  ]
       [                               | Звук: выкл                    ]
       [                               | RU | EN (.lang-segment)       ]
       [ «В эфире» / «Следующая — …» · session title  | Расписание ▾ ]
   ● = stream state per language: red — поток есть, yellow — нет потока,
   grey — проверка. Rows 2 and 5 are flexible spacers, so the right block
   is vertically centred next to the video.
   .stream-main is `display: contents`, so .video-wrap/.embed-wrap and
   .stream-side (the meters) become grid items of the card. The video box is
   an exact 16:9 (no cropped poster), centred in its row; its width is
   computed in JS from the row height left after the title and schedule
   lines. The full schedule list opens over the whole card (note panel
   `position: static` → the card is the list's containing block). Safe areas
   respected. Fullscreen and «Все потоки» keep their own rules. */
.monitor-screen.public-view:has(.stage-grid.phone-layout) .stage-shell {
  height: 100dvh;
  min-height: 0;
  padding:
    max(4px, env(safe-area-inset-top))
    max(4px, env(safe-area-inset-right))
    max(4px, env(safe-area-inset-bottom))
    max(4px, env(safe-area-inset-left));
  place-items: stretch;
}

.monitor-screen.public-view .stage-grid.phone-layout[data-mode="page"] {
  display: grid;
  grid-template-columns: repeat(var(--phone-cols, 1), minmax(0, 1fr));
  grid-template-rows: repeat(var(--phone-rows, 4), minmax(0, 1fr));
  gap: 4px;
  width: 100%;
  height: 100%;
  min-height: 0;
  padding: 0;
  align-content: stretch;
  align-items: stretch;   /* the desktop public rule centers cards — here   */
  justify-items: stretch; /* every card must fill its whole row             */
}

.monitor-screen.public-view .stage-grid.phone-layout[data-mode="page"].has-pager {
  padding-bottom: 52px; /* pager ≈ 40px + its bottom offset */
}

.monitor-screen.public-view:has(.stage-grid.phone-layout) .stage-pager {
  bottom: max(4px, env(safe-area-inset-bottom));
  padding: 3px;
  gap: 4px;
}

.monitor-screen.public-view:has(.stage-grid.phone-layout) .stage-pager button {
  min-height: 30px;
  padding: 3px 10px;
  font-size: 12px;
}

.monitor-screen.public-view .stage-grid.phone-layout[data-mode="page"] > .stream-card:not(:fullscreen) {
  position: relative;
  flex: none;
  width: auto;
  height: auto;
  min-width: 0;
  min-height: 0;
  aspect-ratio: auto;
  display: grid;
  grid-template-columns: var(--phone-video-w, 60%) minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr) auto auto minmax(0, 1fr) auto;
  align-self: stretch;
  justify-self: stretch;
  overflow: hidden;
  border-radius: 8px;
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) .stream-main {
  display: contents;
}

/* row 1 — hall title, full width, one line with ellipsis */
.stage-grid.phone-layout > .stream-card:not(:fullscreen) .stream-header {
  grid-column: 1 / -1;
  grid-row: 1;
  display: block;
  min-width: 0;
  min-height: 0;
  padding: 3px 7px 2px;
  border-bottom: 0;
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) .stream-title {
  display: block;
  overflow: hidden;
  font-size: 12px;
  line-height: 1.2;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) .stream-header-controls {
  display: none;
}

/* rows 2–5 — video (exact 16:9, centred); right block: meters, controls */
.stage-grid.phone-layout > .stream-card:not(:fullscreen) .video-wrap,
.stage-grid.phone-layout > .stream-card:not(:fullscreen) .embed-wrap {
  grid-column: 1;
  grid-row: 2 / 6;
  align-self: center;
  width: 100%;
  height: auto;
  min-height: 0;
  aspect-ratio: 16 / 9;
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) .stream-controls {
  grid-column: 2;
  grid-row: 4;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
  gap: 4px;
  min-width: 0;
  min-height: 0;
  padding: 0 4px 0 6px;
  border-top: 0;
  background: transparent;
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) .stream-controls > * {
  display: none;
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) .stream-controls .mute-button {
  display: block;
  min-width: 0;
  min-height: 26px;
  padding: 2px 2px;
  overflow: hidden;
  font-size: 0; /* the JS label «Включить/Выключить звук» doesn't fit → short one */
  line-height: 1.1;
  white-space: nowrap;
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) .stream-controls .mute-button::after {
  content: "Звук: выкл";
  font-size: 10.5px;
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) .stream-controls .mute-button.is-sound-on::after {
  content: "Звук: вкл";
}

/* language: RU | EN buttons instead of the system <select> popup */
.stage-grid.phone-layout > .stream-card:not(:fullscreen) .stream-controls .lang-segment {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr)); /* 3–4 languages → 2 rows */
  gap: 2px;
  min-width: 0;
  padding: 2px;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: #0d1118;
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) .lang-segment button {
  min-width: 0;
  min-height: 22px;
  padding: 0 2px;
  overflow: hidden;
  border: 0;
  border-radius: 5px;
  background: transparent;
  color: var(--muted);
  font-size: 10.5px;
  font-weight: 700;
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: pointer;
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) .lang-segment button.is-active {
  background: #2c3a50;
  color: var(--text);
  box-shadow: inset 0 0 0 1px rgba(79, 163, 255, 0.55);
}

/* meters — horizontal bars on top of the right block: ● RU ▬▬▬▬ */
.stage-grid.phone-layout > .stream-card:not(:fullscreen) .stream-side {
  grid-column: 2;
  grid-row: 3;
  display: block;
  width: auto;
  min-width: 0;
  min-height: 0;
  margin-bottom: 6px;
  padding: 0 4px 0 6px;
  overflow: hidden;
  border: 0;
  background: transparent;
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) .stream-body,
.stage-grid.phone-layout > .stream-card:not(:fullscreen) .meter-section {
  display: block;
  height: auto;
  min-height: 0;
  padding: 0;
  border: 0;
  background: transparent;
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) .meter-title {
  display: none;
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) .meter-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  justify-content: stretch; /* the base rule centres the (vertical) meters */
  align-items: center;
  gap: 5px;
  width: 100%;
  min-height: 0;
  height: auto;
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) .meter-lang {
  display: grid;
  grid-template-columns: 7px 17px minmax(0, 1fr);
  grid-template-areas: "dot label track";
  grid-template-rows: auto;
  align-items: center;
  justify-items: stretch;
  gap: 5px;
  width: 100%;
  height: auto;
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) .meter-lang-dot {
  grid-area: dot;
  display: block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #5b6576; /* idle — проверка */
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) .meter-lang[data-state="stale"] .meter-lang-dot {
  background: var(--warn); /* нет потока */
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) .meter-lang[data-state="live"] .meter-lang-dot {
  background: var(--danger); /* поток есть */
  box-shadow: 0 0 5px rgba(241, 92, 92, 0.8);
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) .meter-lang-label {
  grid-area: label;
  justify-self: start;
  font-size: 9px;
  line-height: 1;
}

/* same look as the desktop vertical meter (10px, frame, colour zones), turned
   on its side — fills the rest of the row from the left */
.stage-grid.phone-layout > .stream-card:not(:fullscreen) .meter-lang-track {
  grid-area: track;
  width: 100%;
  height: 10px;
  background:
    linear-gradient(
      to right,
      rgba(57, 199, 111, 0.22) 0%,
      rgba(57, 199, 111, 0.22) 80%,
      rgba(243, 201, 79, 0.24) 80%,
      rgba(243, 201, 79, 0.24) 90%,
      rgba(241, 92, 92, 0.25) 90%,
      rgba(241, 92, 92, 0.25) 100%
    );
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) .meter-lang-fill {
  top: 1px;
  right: auto;
  bottom: 1px;
  width: var(--level, 0%);
  max-width: calc(100% - 2px);
  height: auto;
  transition: width 55ms linear;
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) .meter-lang.is-embed {
  grid-template-columns: auto auto;
  grid-template-areas: "label track";
}

/* row 3 — now on air / next + «Расписание», full width */
.stage-grid.phone-layout > .stream-card:not(:fullscreen) > .stream-note-panel.has-schedule {
  grid-column: 1 / -1;
  grid-row: 6;
  position: static;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-rows: auto auto;
  column-gap: 8px;
  row-gap: 0;
  align-items: center;
  max-width: none;
  min-width: 0;
  min-height: 0;
  padding: 2px 6px 3px 7px;
  border-top: 1px solid var(--line-soft);
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) > .stream-note-panel.has-schedule .stream-note-state,
.stage-grid.phone-layout > .stream-card:not(:fullscreen) > .stream-note-panel.has-schedule .stream-note-title {
  grid-column: 1;
  overflow: hidden;
  font-size: 10px;
  line-height: 1.25;
  text-overflow: ellipsis;
  white-space: nowrap;
  letter-spacing: 0;
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) > .stream-note-panel .stream-note-next {
  display: none;
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) > .stream-note-panel .schedule-toggle {
  grid-column: 2;
  grid-row: 1 / 3;
  margin-top: 0;
  min-height: 0;
  padding: 3px 7px;
  font-size: 10px;
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) > .stream-note-panel .schedule-toggle-long {
  display: none;
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) > .stream-note-panel .schedule-toggle-short {
  display: inline;
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) .schedule-close {
  top: 5px;
  width: 30px;
  height: 30px;
  font-size: 14px;
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) .schedule-day {
  padding: 11px 38px 10px 0; /* tall enough to hold the ✕ */
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) .schedule-list {
  top: 4px;
  right: 4px;
  bottom: 4px;
  left: 4px;
  z-index: 6;
  max-height: none !important;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.6);
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) .center-play {
  width: 38px;
  height: 38px;
  font-size: 15px;
}

.stage-grid.phone-layout > .stream-card:not(:fullscreen) .status-line {
  max-width: calc(100% - 12px);
  font-size: 9.5px;
}

/* ?debug=1 — диагностика плеера поверх видео (для проверки на телефонах) */
.player-debug {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 7;
  margin: 0;
  padding: 2px 4px;
  overflow: hidden;
  background: rgba(0, 0, 0, 0.72);
  color: #7dff9b;
  font: 8.5px/1.25 ui-monospace, Menlo, monospace;
  white-space: pre-wrap;
  word-break: break-all;
  pointer-events: none;
}

/* «Расписание с сайта» — event-wide JSON feed (sidebar row + dialog). */
.monitor-screen .feed-panel {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 8px;
  padding: 0 0 6px;
  border-bottom: 1px solid var(--line-soft);
}

.feed-panel-body {
  display: grid;
  gap: 1px;
  min-width: 0;
}

.feed-panel-body .sidebar-section-title {
  display: flex;
  align-items: center;
  gap: 2px;
  white-space: nowrap;
}

.feed-panel-body .help-icon {
  width: 16px;
  height: 16px;
  font-size: 12px;
}

.feed-panel-btn {
  min-height: 30px;
  padding: 4px 10px;
  font-size: 12px;
}

#scheduleFeedDialog {
  width: min(660px, calc(100vw - 28px));
}

.feed-info {
  display: grid;
  gap: 8px;
}

.feed-hint {
  margin: 0;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.4;
}

.feed-hint.is-error {
  color: var(--danger);
}

.feed-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12.5px;
}

.feed-table th,
.feed-table td {
  padding: 6px 8px;
  border-bottom: 1px solid var(--line-soft);
  text-align: left;
  vertical-align: top;
}

.feed-table th {
  color: var(--muted);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.feed-table td:nth-child(2) {
  width: 64px;
  color: var(--muted);
}

.feed-table td.is-muted {
  color: var(--muted);
  font-style: italic;
}

.feed-remove-btn {
  margin-right: auto;
}

.schedule-hall-row {
  display: grid;
  gap: 4px;
  margin-top: 6px;
  font-size: 12px;
  color: var(--muted);
}

.schedule-hall-row[hidden] {
  display: none;
}

.schedule-hall-row input {
  min-height: 36px;
  border: 1px solid var(--line);
  border-radius: 7px;
  padding: 6px 10px;
  background: var(--panel-3);
  color: var(--text);
  font-size: 13px;
}

.feed-stale {
  margin-top: 2px;
  color: #f0b44c;
  font-size: 11px;
}

/* Fit-to-screen page mode: the schedule panel is ALWAYS one line
   (state · title · «Расписание ▾»), not only on ≤560px cards. The 3-line
   variant was 51px taller, which capped the height-bound cards at 560px wide
   (anything wider no longer fit the row) — lots of empty space on big
   screens. «Далее» stays available in the full list. */
.monitor-screen .stage-grid.fit-layout[data-mode="page"] > .stream-card:not(:fullscreen):not(.stream-card-compact):not(.is-embed-card):not(.showing-embed) > .stream-note-panel.has-schedule {
  grid-template-columns: minmax(0, max-content) minmax(0, 1fr) max-content;
  align-items: center;
  align-content: center;
  gap: 8px;
  min-height: 0;
  padding: 4px 10px;
}

.monitor-screen .stage-grid.fit-layout[data-mode="page"] > .stream-card:not(:fullscreen) > .stream-note-panel.has-schedule .stream-note-state,
.monitor-screen .stage-grid.fit-layout[data-mode="page"] > .stream-card:not(:fullscreen) > .stream-note-panel.has-schedule .stream-note-title {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: 12px;
}

.monitor-screen .stage-grid.fit-layout[data-mode="page"] > .stream-card:not(:fullscreen) > .stream-note-panel.has-schedule .stream-note-next {
  display: none;
}

.monitor-screen .stage-grid.fit-layout[data-mode="page"] > .stream-card:not(:fullscreen) > .stream-note-panel.has-schedule .schedule-toggle {
  margin-top: 0;
  padding: 2px 8px;
  font-size: 11px;
  white-space: nowrap;
}

.monitor-screen .stage-grid.fit-layout[data-mode="page"] > .stream-card:not(:fullscreen) > .stream-note-panel.has-schedule .schedule-toggle-long {
  display: none;
}

.monitor-screen .stage-grid.fit-layout[data-mode="page"] > .stream-card:not(:fullscreen) > .stream-note-panel.has-schedule .schedule-toggle-short {
  display: inline;
}

/* Public share page, fit-to-screen mode: tighter chrome around the video.
   Cards there are height-bound (2 rows of 16:9), so every pixel saved on the
   header / controls / outer padding goes straight into a bigger picture. */
.monitor-screen.public-view .stage-shell {
  padding: 8px;
}

.monitor-screen.public-view .stage-grid.fit-layout[data-mode="page"] {
  row-gap: 10px;
}

.monitor-screen.public-view .stage-grid.fit-layout[data-mode="page"] > .stream-card:not(:fullscreen) .stream-header {
  min-height: 0;
  padding: 7px 12px;
}

.monitor-screen.public-view .stage-grid.fit-layout[data-mode="page"] > .stream-card:not(:fullscreen) .stream-controls {
  min-height: 0;
  padding: 5px 8px;
  gap: 6px;
}

.monitor-screen.public-view .stage-grid.fit-layout[data-mode="page"] > .stream-card:not(:fullscreen) .stream-controls .control-button,
.monitor-screen.public-view .stage-grid.fit-layout[data-mode="page"] > .stream-card:not(:fullscreen) .stream-controls select {
  min-height: 32px;
  padding-top: 4px;
  padding-bottom: 4px;
}
