/* 08-parent-profile-room.css — part 08/10 of the ordered bp bundle (the former single bp.css,
   split by surface; the content is UNREORDERED). ORDER IS LOAD-BEARING: cascade ties
   resolve by document order, so hosts must link 01→10 in exactly this sequence —
   CssHygieneTests pins both the list and the order in both hosts. */

/* ── Главная родителя (/home/parent) — wave 6 Task 3, Главная родителя.dc.html ──────────────────── */

.rp-phome-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  margin-bottom: 16px;
}

.rp-phome-card {
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.rp-phome-head {
  display: flex;
  align-items: center;
  gap: 12px;
}

.rp-phome-head-text { flex: 1; min-width: 0; }
.rp-phome-name { font-size: 15.5px; font-weight: 700; }
.rp-phome-tenant { font-size: 12.5px; color: var(--muted-foreground); }

/* Shared initials avatar (card head 40px, week rows 26px via --sm). --warm is the alternating
   per-child tint — children are told apart by avatar tone, not by fabricated subject colours. */
.rp-phome-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-foreground);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 700;
  flex-shrink: 0;
}

.rp-phome-avatar--warm {
  background: var(--warning-muted);
  color: var(--warning-muted-foreground);
}

.rp-phome-avatar--sm {
  width: 26px;
  height: 26px;
  font-size: 10.5px;
}

.rp-phome-next {
  display: flex;
  align-items: center;
  gap: 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 10px 12px;
}

.rp-phome-next-ico {
  width: 16px;
  height: 16px;
  display: inline-flex;
  color: var(--primary);
  flex-shrink: 0;
}

.rp-phome-next-body { flex: 1; min-width: 0; line-height: 1.3; }
.rp-phome-next-title { font-size: 13px; font-weight: 600; }
/* Spec 11.5: «Курс „X" · Поток „Y"» — optional line between the title and the "when" line. */
.rp-phome-next-ctx { font-size: 11.5px; color: var(--muted-foreground); opacity: 0.85; }
.rp-phome-next-when { font-size: 12px; color: var(--muted-foreground); }
.rp-phome-next-none { font-size: 13px; color: var(--muted-foreground); }

.rp-phome-next-link {
  font-size: 12.5px;
  color: var(--primary);
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}

.rp-phome-bal {
  display: flex;
  align-items: center;
  gap: 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 10px 12px;
}

.rp-phome-bal--warn {
  border-color: color-mix(in srgb, var(--warning) 45%, var(--border));
  background: var(--warning-muted);
}

.rp-phome-bal-body { flex: 1; line-height: 1.3; }

.rp-phome-bal-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted-foreground);
}

.rp-phome-bal-num { font-size: 13.5px; font-weight: 700; }

.rp-phome-bal--warn .rp-phome-bal-label,
.rp-phome-bal--warn .rp-phome-bal-num { color: var(--warning-muted-foreground); }

.rp-phome-topup {
  height: 34px;
  padding: 0 14px;
  display: inline-flex;
  align-items: center;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--primary);
  border: 1.5px solid var(--primary);
  font-size: 12.5px;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  flex-shrink: 0;
}

.rp-phome-topup--primary {
  background: var(--primary);
  color: var(--primary-foreground);
  border: 0;
}

.rp-phome-tasks { display: flex; flex-direction: column; }
.rp-phome-tasks .rp-shome-card-head { margin-bottom: 4px; }

/* «Курсы ребёнка» — read-only per-course progress rows (UX-audit wave 4, item 7). */
.rp-phome-courses { display: flex; flex-direction: column; }
.rp-phome-courses .rp-shome-card-head { margin-bottom: 4px; }

.rp-phome-course-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 0;
  border-top: 1px solid var(--border);
}

.rp-phome-courses .rp-phome-course-row:first-of-type { border-top: 0; }

.rp-phome-course-name { font-size: 13.5px; font-weight: 600; min-width: 0; }

.rp-phome-course-pct {
  font-size: 12.5px;
  color: var(--muted-foreground);
  white-space: nowrap;
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}

.rp-phome-week { padding: 20px; }

.rp-phome-week-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 11px 0;
  border-top: 1px solid var(--border);
}

.rp-phome-week-list .rp-phome-week-row:first-child { border-top: 0; }

.rp-phome-week-when {
  width: 84px;
  flex-shrink: 0;
  font-size: 13px;
  color: var(--muted-foreground);
  font-variant-numeric: tabular-nums;
}

.rp-phome-week-body { flex: 1; min-width: 0; }
.rp-phome-week-title { font-size: 13.5px; font-weight: 600; }
.rp-phome-week-child { font-size: 12.5px; color: var(--muted-foreground); }
.rp-phome-week-none { font-size: 13px; color: var(--muted-foreground); }

.rp-phome-empty { font-size: 14px; color: var(--muted-foreground); margin: 0; }

@media (max-width: 768px) {
  .rp-phome-grid { grid-template-columns: 1fr; margin-bottom: 0; }
  /* Мокап: недельная карточка есть только на десктопе — на мобиле карточки детей несут ту же
     информацию per-child. */
  .rp-phome-week { display: none; }
}

/* ── Задания детей (/children-homework) — wave 6 Task 4, Задания детей.dc.html ─────────────────── */
/* Per-child filter chips + three status sections on the shared AssignmentList (rp-asg*). */

.rp-chw-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 20px;
}

.rp-chw-chip {
  height: 34px;
  padding: 0 14px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--card);
  color: var(--foreground);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 7px;
}

.rp-chw-chip--active {
  background: var(--accent);
  color: var(--accent-foreground);
  border-color: color-mix(in srgb, var(--primary) 45%, var(--border));
}

/* Chip avatar — 20px initials circle; --warm alternating per-child tint (rp-phome-avatar rule). */
.rp-chw-chip-av {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-foreground);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 9.5px;
  font-weight: 700;
  flex-shrink: 0;
}

.rp-chw-chip-av--warm {
  background: var(--warning-muted);
  color: var(--warning-muted-foreground);
}

.rp-chw-sec { margin-bottom: 22px; }

.rp-chw-sec-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}

.rp-chw-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--muted-foreground);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* Section-tone counter badge («Требуют внимания» destructive / «На проверке» info / «Готово» success). */
.rp-chw-count {
  min-width: 19px;
  height: 19px;
  padding: 0 6px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.rp-chw-count--danger  { background: var(--destructive-muted); color: var(--destructive-muted-foreground); }
.rp-chw-count--info    { background: var(--info-muted);        color: var(--info-muted-foreground); }
.rp-chw-count--success { background: var(--success-muted);     color: var(--success-muted-foreground); }

@media (max-width: 640px) {
  .rp-chw-chip {
    height: 32px;
    padding: 0 12px;
    font-size: 12.5px;
  }
  /* LOCKED-12: одна разметка — аватар фильтр-чипа прячется на мобиле (аватар СТРОКИ остаётся). */
  .rp-chw-chip-av { display: none; }
  .rp-chw-sec { margin-bottom: 16px; }
  .rp-chw-label { font-size: 11px; }
  .rp-chw-count {
    min-width: 17px;
    height: 17px;
    padding: 0 5px;
    font-size: 10.5px;
  }
}

/* ── Wave 6 Task 6 — /child/{id}/homework/block/{id}, parent read-only submission view
   (Задания детей.dc.html detail frame). Chrome only: the engine cards below are
   HomeworkSubmissionDetail's own. Back link mirrors .rp-les-back (Занятие page). ── */
.rp-chw-sub { max-width: 720px; margin: 0 auto; }

.rp-chw-sub-back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--muted-foreground);
  text-decoration: none;
  margin-bottom: 16px;
}
.rp-chw-sub-back:hover { color: var(--foreground); }

.rp-chw-sub-badge { margin-bottom: 16px; }

/* ══════════════════════════════════════════════════════════════════════════════════════════════
   ParentModeBadge (wave 6 Task 5 — Режим родителя.dc.html, П-14)
   Explicit parent-mode context on shared entity pages: the inline pill next to the /my-lessons
   title, the full-width read-only banner above /lesson/{id} content, and the LOCKED-10 info card.
   ══════════════════════════════════════════════════════════════════════════════════════════════ */

.rp-pbadge-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 26px;
  padding: 0 11px;
  border-radius: 999px;
  background: var(--info-muted);
  color: var(--info-muted-foreground);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}

.rp-pbadge-banner {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 14px;
  background: var(--info-muted);
  color: var(--info-muted-foreground);
  border-bottom: 1px solid var(--border);
  font-size: 12px;
  font-weight: 600;
}

.rp-pbadge-banner-text { min-width: 0; }

/* LOCKED-10 info card: neutral card tone (the banner already carries the info tint). */
.rp-pbadge-info {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--card);
  padding: 13px 15px;
  margin-bottom: 12px;
}

.rp-pbadge-info-ico {
  display: inline-flex;
  flex-shrink: 0;
  margin-top: 2px;
  color: var(--muted-foreground);
}

.rp-pbadge-info-text {
  font-size: 12.5px;
  color: var(--muted-foreground);
  line-height: 1.55;
}

/* ══════════════════════════════════════════════════════════════════════════════════════════════
   /profile (wave 6 Task 7 — Профиль.dc.html, П-10 «только личное»)
   A centered 640px column of section cards: «Личные данные» (Rp Mud inputs inside a Bp card —
   the MixedState engine is untouched), «Пароль» (dialog trigger), the manager-only info pointer,
   and the «Аккаунт» card (export row + delete zone). The 152-ФЗ consequences block and the
   code-confirm flow reuse the rp-set-danger-star and rp-btn-danger-star chrome from TenantPanel.
   ══════════════════════════════════════════════════════════════════════════════════════════════ */

.rp-prof {
  max-width: 640px;
  margin: 0 auto;
}

.rp-prof-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--card);
  padding: 22px;
  margin-bottom: 16px;
}

.rp-prof-card-title {
  font-size: 14px;
  font-weight: 700;
  margin-bottom: 16px;
}

.rp-prof-avatar { margin-bottom: 4px; }

/* neutral outline action button (mockup: «Сменить пароль», «Запросить архив»).
   Also worn by <label><InputFile/></label> picker buttons (RpImageUpload/RpImageField)
   — a label doesn't center its content the way a button does, hence the
   explicit inline-flex centering; gap spaces the optional leading icon. */
.rp-prof-btn {
  height: 38px;
  justify-content: center;
  gap: 8px;
  padding: 0 14px;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--foreground);
  font: inherit;
  font-size: 13px;
  white-space: nowrap;
  flex-shrink: 0;
}
.rp-prof-btn:disabled { opacity: 0.6; cursor: not-allowed; }

.rp-prof-text {
  font-size: 12.5px;
  color: var(--muted-foreground);
  line-height: 1.55;
  margin: 0 0 14px;
}

/* info-muted plate: the «Ищете настройки площадки…» pointer between the cards and (--flow) the
   owner closure-first plate inside the delete zone. */
.rp-prof-hint {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--info-muted);
  color: var(--info-muted-foreground);
  padding: 13px 16px;
  margin-bottom: 16px;
}
.rp-prof-hint--flow { margin-bottom: 0; }
.rp-prof-hint-ico { display: inline-flex; flex-shrink: 0; margin-top: 1px; }
.rp-prof-hint-text { font-size: 13px; line-height: 1.55; }
.rp-prof-hint-text a { color: var(--info-muted-foreground); font-weight: 600; }

/* «Аккаунт» card action rows */
.rp-prof-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 14px;
}
.rp-prof-row-main { flex: 1; min-width: 0; }
.rp-prof-row-title { font-size: 13.5px; font-weight: 600; }
.rp-prof-row-title--danger { color: var(--destructive); }
.rp-prof-row-sub {
  font-size: 12.5px;
  color: var(--muted-foreground);
  line-height: 1.5;
}

/* delete zone (the second «Аккаунт» row grown into the inline UC-22 flow) */
.rp-prof-del > .rp-prof-row-title--danger { margin-bottom: 6px; }
.rp-prof-del-lead { margin-bottom: 12px; }
.rp-prof-warn-title2 { margin-top: 8px; }

.rp-prof-check {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  font-size: 13px;
  line-height: 1.5;
  margin: 12px 0;
  cursor: pointer;
}
.rp-prof-check input {
  width: 16px;
  height: 16px;
  margin: 1px 0 0;
  accent-color: var(--destructive);
  cursor: pointer;
  flex-shrink: 0;
}

/* Marketing-consent toggle («Получать новости и советы», the «Рассылка» card) — same layout as
   .rp-prof-check but a DELIBERATELY separate class with the ordinary primary accent: that one is a
   danger consent (destructive red), this one is a preference. */
.rp-mkt-check {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  font-size: 13.5px;
  line-height: 1.5;
  margin: 4px 0 10px;
  cursor: pointer;
}
.rp-mkt-check input {
  width: 16px;
  height: 16px;
  margin: 1px 0 0;
  accent-color: var(--primary);
  cursor: pointer;
  flex-shrink: 0;
}

@media (max-width: 600px) {
  .rp-prof-card { padding: 16px; }

  /* Mobile mockup centers the avatar block; RpImageUpload's own layout is Mud utility flex —
     restack its root row into a centered column without touching the shared component. */
  .rp-prof-avatar > div {
    flex-direction: column;
    align-items: center;
    text-align: center;
  }
  .rp-prof-avatar > div > div { align-items: center; }

  .rp-prof-row { flex-direction: column; align-items: stretch; }
  .rp-prof-btn { width: 100%; height: 44px; }
  .rp-prof-del .rp-btn-danger-outline { width: 100%; height: 44px; }
}

/* ---------- RoomChatPanel (wave 7 Task 2) ---------- */
/* Compact «Чат занятия» panel for /room/{LessonId} — see the header inventory comment for the full
   rationale. RoomPage (T4) owns show/hide + desktop-column vs mobile-sheet placement around this
   markup; the panel itself is a plain flex column that fills whatever box it's given. */
.rp-rchat {
  display: flex;
  flex-direction: column;
  min-height: 0;
  height: 100%;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.rp-rchat-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
  font-weight: 600;
  flex-shrink: 0;
}
.rp-rchat-head-title { flex: 1; }

.rp-rchat-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.rp-rchat-empty {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted-foreground);
  font-size: 13px;
  text-align: center;
  padding: 20px;
}
/* Loading state: a spinner over a --card ground takes the muted tone — same override
   .rp-deckpick-loading .rp-spin applies below for the identical shape. */
.rp-rchat-empty .rp-spin {
  border-color: color-mix(in srgb, var(--muted-foreground) 30%, transparent);
  border-top-color: var(--muted-foreground);
}

.rp-rchat-msg { display: flex; flex-direction: column; align-items: flex-start; }
.rp-rchat-msg--mine { align-items: flex-end; }
.rp-rchat-msg-meta { font-size: 11.5px; color: var(--muted-foreground); margin-bottom: 2px; }

.rp-rchat-bubble {
  display: inline-block;
  max-width: 90%;
  padding: 7px 11px;
  border-radius: 12px;
  background: var(--secondary);
  color: var(--secondary-foreground);
  font-size: 13px;
  line-height: 1.45;
  overflow-wrap: anywhere;
  word-break: break-word;
}
/* Own bubble — accent-filled, mirrors rp-msg-bubble--mine's own-message convention. */
.rp-rchat-bubble--mine { background: var(--primary); color: var(--primary-foreground); }
/* Tombstone for a removed message — muted/dashed, no fill (rp-msg-bubble--removed's compact cousin). */
.rp-rchat-bubble--removed { background: transparent; border: 1px dashed var(--border); color: var(--muted-foreground); font-style: italic; }

/* Attachments inside a room bubble. Deliberately NOT the chat page's rp-msg-att-* set: that one is
   sized for a 700px conversation column, while this bubble lives in a ~320px rail beside the video.
   A file is one line (icon + name, truncated), an image a small preview — and a message with no text
   at all is exactly why this exists: without it the bubble rendered as an empty coloured rectangle. */
.rp-rchat-text { display: block; }
.rp-rchat-text + .rp-rchat-att,
.rp-rchat-text + .rp-rchat-att-img { margin-top: 6px; }
.rp-rchat-att {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.rp-rchat-att + .rp-rchat-att,
.rp-rchat-att-img + .rp-rchat-att,
.rp-rchat-att + .rp-rchat-att-img,
.rp-rchat-att-img + .rp-rchat-att-img { margin-top: 6px; }
.rp-rchat-att-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* A file the chat TTL already swept: no link, no underline — the name plus why it is gone. */
.rp-rchat-att--gone { flex-wrap: wrap; text-decoration: none; opacity: 0.8; }
.rp-rchat-att-note { font-size: 11.5px; font-style: italic; }
.rp-rchat-att-img { display: block; }
.rp-rchat-att-img img { display: block; max-width: 100%; max-height: 140px; border-radius: 8px; }

.rp-rchat-composer {
  display: flex;
  gap: 8px;
  padding: 10px;
  border-top: 1px solid var(--border);
  flex-shrink: 0;
}
/* Read-only lesson room (ChatMessagesWindow.CanReply == false — the archive flipped ReadOnly):
   the composer is replaced by this notice, same footprint as the composer row. */
.rp-rchat-closed {
  padding: 12px;
  border-top: 1px solid var(--border);
  flex-shrink: 0;
  color: var(--muted-foreground);
  font-size: 13px;
  text-align: center;
}
/* «Чат недоступен» — OpenLessonChat refused at join (a first-opens serialization race). Sits in
   the chat host's place; the retry re-runs ONLY the chat command, never the video join. */
.rp-room-chaterror {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin: 12px;
  padding: 14px 12px;
  border: 1px dashed var(--border);
  border-radius: var(--radius-md);
  color: var(--muted-foreground);
  font-size: 13px;
}
.rp-room-chaterror-retry {
  padding: 6px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--secondary);
  color: var(--secondary-foreground);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
}
.rp-room-chaterror-retry:disabled { opacity: 0.6; cursor: default; }
.rp-rchat-input {
  flex: 1;
  height: 36px;
  padding: 0 12px;
  border: 1px solid var(--input);
  border-radius: var(--radius-md);
  background: var(--card);
  color: var(--foreground);
  font: inherit;
  font-size: 13px;
}
.rp-rchat-send {
  width: 36px;
  height: 36px;
  border: 0;
  border-radius: var(--radius-md);
  background: var(--primary);
  color: var(--primary-foreground);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
}
.rp-rchat-send:disabled { opacity: 0.5; cursor: default; }

/* ---------- RoomToolRail (wave 7 Task 3) ---------- */
/* Board tool palette extracted out of WhiteboardSurface into its own always-visible rail — see the
   header inventory comment for the full rationale. Default orientation is a vertical 52px column
   (desktop / phone-landscape); RoomPage (T4) applies rp-rtool--row for the mobile/tablet horizontal
   layout. Every button calls repetitumBoard.* directly — this component owns no canvas. */
.rp-rtool {
  width: 52px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 10px 0;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}
/* Horizontal arm (mobile/tablet). `overflow-x: auto` is a structural guarantee, not a nicety: 2 tools +
   6 swatches + 2 actions + separators measured 392px against 349px of available width on a 375px phone,
   and because the parent column resolves overflow-x to `auto`, that 43px spilled into a page-wide
   horizontal scroll. The rail now scrolls inside itself; the sizes below (32px buttons, 22px swatches)
   make that scroll unnecessary at 375px, and it stays correct for whatever the palette grows into. */
.rp-rtool--row {
  width: auto;
  max-width: 100%;
  flex-direction: row;
  padding: 5px 8px;
  gap: 4px;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  justify-content: center;
}
.rp-rtool--row::-webkit-scrollbar { display: none; }
.rp-rtool--row .rp-rtool-btn { width: 32px; height: 32px; }
.rp-rtool--row .rp-rtool-color { width: 22px; height: 22px; }

.rp-rtool-btn {
  width: 36px;
  height: 36px;
  flex-shrink: 0;
  border: 0;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--muted-foreground);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
/* Active pen/eraser tool — accent fill, mirrors the stageTabs/boardTools active treatment in the
   mockup's demo script. */
.rp-rtool-btn--active { background: var(--accent); color: var(--accent-foreground); }
.rp-rtool-btn:disabled { opacity: 0.4; cursor: default; }

.rp-rtool-sep { width: 26px; height: 1px; background: var(--border); margin: 4px 0; flex-shrink: 0; }
.rp-rtool--row .rp-rtool-sep { width: 1px; height: 22px; margin: 0 6px; }

.rp-rtool-color {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  border-radius: 50%;
  border: 2px solid transparent;
  padding: 0;
  cursor: pointer;
}
/* The ring is a UI-chrome token; the swatch fill itself is the inline hex stroke color (LOCKED-1). */
.rp-rtool-color--active { border-color: var(--primary); }
.rp-rtool-color:disabled { opacity: 0.4; cursor: default; }

/* ---------- RoomPage chrome ---------- */
/* Full rationale in the header inventory comment. */

/* All teaching surfaces use the same width-relative composition, independent of viewport/DPR. */
.rp-teaching-frame {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 4px;
  width: 100%;
  max-width: min(100%, var(--rp-teaching-max-width, 100%));
  min-width: 0;
  flex-shrink: 0;
}
.rp-teaching-sheet {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  container-type: size;
  overflow: hidden;
  box-sizing: border-box;
  border: 0;
  outline: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--wb-paper);
  color: var(--wb-ink);
}
.rp-teaching-footer { display: flex; justify-content: center; min-width: 0; }
.rp-teaching-footer:empty, .rp-teaching-footer[hidden] { display: none; }
.rp-room-slide {
  position: absolute; inset: 0; overflow: hidden; touch-action: none;
  background: var(--wb-paper); color: var(--wb-ink);
}
.rp-slide-composition { min-height: 100%; padding: 3cqw 4cqw; box-sizing: border-box; }
.rp-slide-scroll-help { position: absolute; top: 0; right: 4px; font-size: 11px; line-height: 1.4; background: var(--wb-paper); color: var(--wb-ink); pointer-events: none; }
.rp-room-slide-title { margin: 0 0 .3em; font-size: 5cqw; font-weight: 600; line-height: 1.2; }
.rp-room-slide-content { min-width: 0; }
.rp-room-slide-body.rp-markdown { font-size: 3.2cqw; line-height: 1.4; }
.rp-room-slide-body > :first-child { margin-top: 0; }
.rp-room-slide-body > :last-child { margin-bottom: 0; }
.rp-room-slide-body.rp-markdown :is(ul,ol) { margin-block: 0; padding-left: 1.2em; }
.rp-room-slide-body.rp-markdown li { margin: 0; }
.rp-room-slide-has-image .rp-room-slide-content {
  display: grid; grid-template-columns: 45% 55%; align-items: start;
}
.rp-room-slide-image { display: block; width: 100%; height: 35cqw; object-fit: contain; }
.rp-room-slide-has-image .rp-room-slide-body { padding-left: 2cqw; }
.rp-room-slide--image-only .rp-slide-composition { height: 100%; padding: 0; }
.rp-room-slide--image-only .rp-room-slide-content { display: block; height: 100%; }
.rp-room-slide--image-only .rp-room-slide-image { width: 100%; height: 100%; }

/* Демонстрация экрана — тот же слой, что слайд: абсолютный лист на весь кадр. `contain`, а не
   `cover`: экран учителя почти никогда не 1:1, и обрезать у него края значит обрезать то самое, что
   он показывает. Чёрный фон — поля вокруг вписанной картинки. Элемент всегда в DOM (JS цепляет трек
   раньше, чем Blazor успел бы его создать).
   `visibility: hidden`, а НЕ `display: none` — и не по причине `.wb-surface` ниже (та боится потерять
   canvas backing store). Здесь причина другая: LiveKit adaptive stream решает, виден ли элемент, через
   isElementInViewport (по сути IntersectionObserver), а тот читает display:none как «невидимо» СРАЗУ,
   на первом же наблюдении — дебаунс updateVisibility сравнивается с нулевой временной меткой и не
   успевает применяться. RemoteTrackPublication в ответ шлёт SFU UpdateTrackSettings{disabled:true} и
   отключает трек, который сам только что подписал: до первого рендера Blazor (когда элемент станет
   display:block) зритель видит отключение-включение и ждёт нового ключевого кадра. `visibility`
   IntersectionObserver не замечает — элемент читается видимым всё время, кадры идут без сбоя, а
   `position:absolute; inset:0` держит нулевую цену по layout в обоих состояниях. */
.rp-room-screen { position: absolute; inset: 0; width: 100%; height: 100%;
    object-fit: contain; background: #000; visibility: hidden; }
.rp-room-square--screen .rp-room-screen { visibility: visible; }
/* Пока идёт показ, доска и слайд прячутся, но НЕ размонтируются: WhiteboardSurface.DisposeAsync
   зовёт repetitumBoard.unmount(), а тот делает strokes.clear() — снятие с дерева стёрло бы доску
   безвозвратно, ресинк штрихов запрашивается только при входе в комнату. Навигация по слайдам и
   пикер (и его клик-ловящая подложка) прячутся вместе со слайдом: они относятся к нему. */
.rp-room-square--screen .rp-room-slide,
.rp-room-square--screen .rp-room-stagenav,
.rp-room-square--screen .rp-room-picker,
.rp-room-square--screen .rp-room-pickerbackdrop { display: none; }
/* `.wb-surface` deliberately does NOT join the `display: none` list above — do not "tidy" it back in.
   whiteboard.js measures the real rect through an owner-keyed ResizeObserver; display:none collapses
   that rect to zero and leaves no meaningful projection. `visibility: hidden` keeps the layout box
   (real rect, real canvas size) while still dropping the board from paint and hit-testing, which is
   all "no drawing over the screen" needs. */
.rp-room-square--screen .wb-surface { visibility: hidden; }

/* Full-viewport flex-column shell for /room/{lessonId} (ReaderLayout, no sidebar/appbar). This base rule
   must live in bp.css, not app.css: app.css loads AFTER bp.css, so a base `.rp-room{display:flex}` there
   would outrank the phone-landscape `.rp-room{display:grid}` below by source order (equal 0,1,0
   specificity) and the landscape grid would never apply. In-file, the later landscape block wins the
   tie — the intended cascade. */
.rp-room { display: flex; flex-direction: column; height: 100dvh; background: var(--background);
    position: relative; overflow: hidden; }

/* Top bar: title/subtitle, timer pill (rp-chip--success, reused), scene controls, participant count. */
.rp-room-top {
  display: flex;
  align-items: center;
  gap: 14px;
  height: 52px;
  padding: 0 16px;
  background: var(--card);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
/* The title is the ONLY element in the bar allowed to give up width (every chip is flex-shrink:0 via the
   primitive) — so a long lesson note ellipsises instead of squeezing the status chips into wrapping. */
.rp-room-top-title { line-height: 1.2; min-width: 0; flex: 0 1 auto; }
.rp-room-top-name {
  font-size: 13.5px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rp-room-top-sub { font-size: 11.5px; color: var(--muted-foreground); white-space: nowrap; }
.rp-room-top-spacer { flex: 1 1 0; min-width: 0; }
.rp-room-top-users {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  color: var(--muted-foreground);
  flex-shrink: 0;
}

/* Countdown pill — tabular figures + a floor on the label box so the chip keeps ONE width for the whole
   lesson. Paired with RemainingLabel's zero-padded mm:ss: proportional digits alone still shifted the
   pill (and every sibling after it) on each tick, which read as the header "twitching". */
.rp-room-timer {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  min-width: 74px;
  justify-content: center;
}

/* Recording badge — the consent indicator every participant sees while a recording runs. Deliberately
   NOT the shared `.rp-chip-dot`: that dot is `currentColor`, and here it must stay unmistakably red
   even where the chip's own colour is muted, since it is the one mark a person scans the bar for.
   The pulse is what separates «recording now» from a static label; it is dropped under
   prefers-reduced-motion, where the red dot alone still carries the message. */
.rp-room-recbadge { flex-shrink: 0; white-space: nowrap; }
.rp-room-recbadge-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--destructive);
  flex-shrink: 0;
  animation: rp-room-recpulse 2s ease-in-out infinite;
}
@keyframes rp-room-recpulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.35; }
}
@media (prefers-reduced-motion: reduce) {
  .rp-room-recbadge-dot { animation: none; }
}

/* Connection chip — a button so a touch device can reach the detail line it can't hover for. */
.rp-room-net {
  border: 0;
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  padding: 5px 12px;
  border-radius: 999px;
}

/* Scene controls (board/slides segment + the «‹ Слайд N / M ›» control, or the student's read-only
   stage badge) — ONE RenderFragment, rendered in two static CSS-gated positions (desktop:
   rp-room-top-scene; mobile: rp-room-scenerow, its own row right under the square) so the page never
   needs a duplicate-instance guard the way RoomChatPanel does (this fragment has no autonomous side
   effects) — the picker popup underneath is duplicated the same safe way. */
.rp-room-scenegroup { display: flex; align-items: center; gap: 8px; min-width: 0; }
.rp-room-scenetab-lbl { white-space: nowrap; }

/* ---------- Frame-owned slide nav, outside the logical paper ---------- */
.rp-room-stagenav {
  position: relative;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 3px;
  border-radius: 999px;
  background: var(--card);
  border: 1px solid var(--border);
  max-width: 100%;
  box-sizing: border-box;
}
.rp-room-stagenav > * { pointer-events: auto; }
.rp-room-stagenav-btn {
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--foreground);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.rp-room-stagenav-btn:hover:not(:disabled) { background: var(--secondary); }
.rp-room-stagenav-btn:disabled { opacity: 0.35; cursor: default; }
.rp-room-stagenav-count {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 12px;
  flex-shrink: 0;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--foreground);
  font: inherit;
  cursor: pointer;
}
.rp-room-stagenav-count:hover { background: var(--secondary); }
.rp-room-stagenav-count--static { cursor: default; padding: 0 14px; }
.rp-room-stagenav-count--static:hover { background: transparent; }
/* Tabular figures + a width floor: a 12-slide deck must not resize its own control on «9 / 12» →
   «10 / 12», which on the stage would visibly nudge the arrows apart mid-presentation. */
.rp-room-slide-counter {
  font-size: 13.5px;
  font-weight: 600;
  color: inherit;
  min-width: 52px;
  text-align: center;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  white-space: nowrap;
}

/* One picker above the external pager. It can use the paper's full height now that navigation
   no longer reserves an overlay band inside the content rectangle. Its grid scrolls independently. */
.rp-room-picker {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  bottom: 4px;
  z-index: 13;
  /* border-box so the 14px padding + 1px border are inside the width/max-height budgeted against the
     stage — under content-box a "320px" panel laid out at 350px and its max-height overshot the square's
     top edge, so it was silently clipped by the stage's overflow:hidden on a 375px phone. */
  box-sizing: border-box;
  width: min(320px, calc(100% - 24px));
  max-height: calc(100% - 8px);
  display: flex;
  flex-direction: column;
  padding: 14px;
  background: var(--popover);
  color: var(--popover-foreground);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
.rp-room-picker-head { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; flex-shrink: 0; }
.rp-room-picker-title {
  flex: 1;
  min-width: 0;
  font-size: 13px;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rp-room-picker-changedeck {
  height: 28px;
  padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--secondary);
  color: var(--secondary-foreground);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}
/* Always visible now that the picker is an in-stage panel on every breakpoint: the stage must never dim
   (LOCKED), so there is no dimming backdrop to tap through and the ✕ is the explicit way out. (The
   transparent rp-room-pickerbackdrop still closes it on an outside click.) */
.rp-room-picker-close {
  display: inline-flex;
  width: 26px;
  height: 26px;
  flex-shrink: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--secondary);
  color: var(--secondary-foreground);
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
/* align-content:start keeps row height column-driven: the panel has a definite (tall) max-height, and a
   stretched row would re-derive cell WIDTH from the stretched height via aspect-ratio:1/1 and overflow. */
.rp-room-picker-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  align-content: start;
  overflow-y: auto;
  min-height: 0;
}
.rp-room-picker-num {
  aspect-ratio: 1 / 1;
  border: 2px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--muted);
  color: var(--muted-foreground);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.rp-room-picker-num--active { border-color: var(--primary); color: var(--primary); }

/* Transparent click-catcher closing the picker on an outside click. Scoped to the stage (absolute inside
   `.rp-room-square`, not fixed over the room) on EVERY breakpoint now — the picker is an in-stage panel,
   so "outside" means "elsewhere on the stage", and the bottom bar / tiles / chat stay live behind it. */
.rp-room-pickerbackdrop { position: absolute; inset: 0; z-index: 11; }

/* SlideDeckPickerDialog body (T5) — the dialog chrome itself (head/title/close, empty state) reuses the
   generic rp-covw-dlg/-empty shell shared across the cabinet; only the tree list below is new. */
/* Дерево курсов из прежнего пикера колод снято вместе с GetMyDecksTree (task 15): колоду выбирают
   в общем списке материалов (.rp-matpick-*, 02-student.css). Загрузчик ниже остался — он общий. */
.rp-deckpick-loading { display: flex; justify-content: center; padding: 24px 0; }
.rp-deckpick-loading .rp-spin {
  border-color: color-mix(in srgb, var(--muted-foreground) 30%, transparent);
  border-top-color: var(--muted-foreground);
}

.rp-room-scenerow { display: none; }

/* Content row: 52px rail / flexible teaching slot / 260–340px side column on desktop (CSS Grid auto-placement —
   the mobile-only rp-room-scenerow is display:none there so it never consumes a track); a single ordered
   flex column on mobile. */
.rp-room-main {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 52px 1fr minmax(260px, 340px);
  gap: 12px;
  padding: 12px;
}

/* The room slot owns the actual budget; the common fitter centers paper and footer together. */
.rp-room-stage-slot {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
}
/* When a slide is shown the whiteboard surface must be transparent so the slide shows through — WhiteboardSurface
   mounts unconditionally alongside SlideStage (both are position/z-index:auto "positioned" descendants painted in
   tree order, so it paints AFTER and would otherwise fully occlude the slide beneath it). */
.rp-room-square .wb-surface { background: transparent; }
/* Transient notices — reconnecting / waiting / floor-granted / raised hand — stack in one centered
   column at the top of the stage. A column, not per-notice `top` offsets: two notices can be live at
   once (a raised hand during a reconnect), and the old fixed `top:12px`/`top:56px` pair placed them by
   hand, so any third notice needed another magic number and any two that shared an offset overlapped.
   The column never takes pointer input; its children do. */
.rp-room-overlays {
  position: absolute;
  top: 12px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 10;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  max-width: calc(100% - 24px);
  pointer-events: none;
}
.rp-room-overlays > * { pointer-events: auto; max-width: 100%; }

/* Every padded overlay that caps itself against the stage must measure border-box. There is no global
   reset in this stylesheet, so a `max-width` is a CONTENT cap by default and the element's own padding
   and border spill past it: the raised-hand banner laid out at 384px inside the 364px column it was
   supposed to fit, on a 390px stage. Harmless for a short name, a clipped control for a long one — and
   the same trap that produced a 2px page-wide horizontal scroll on the stage itself and a clipped slide
   picker, so it is collected here rather than patched a fourth time. */
.rp-room-overlays,
.rp-room-overlays > *,
.rp-room-stagenav,
.rp-room-tile-name { box-sizing: border-box; }
/* The stage is arbitrary tutor content — and the slide sheet is white in BOTH themes (--wb-paper), so a
   chip sitting on it must announce itself as chrome rather than as a line of the slide. A toneless chip
   used to be fully transparent here, which is how «Ученики ещё не подключились» ended up reading as part
   of the slide copy; the fill alone doesn't finish the job either, since every chip surface (--secondary
   and the --*-muted tones alike) is a pale tint that measures ~1.1:1 against white paper.
   The ring does the separating: `currentColor` is the tone's own foreground, so one rule gives every
   variant a tone-coloured outline — neutral grey, amber for a warning, green for success — without
   restating a border colour per modifier or overriding the fill (which would cost the tone signal). At
   50% it measures 4.3:1 against white paper in the light theme (16:1 in dark) for every tone, clearing
   the 3:1 WCAG minimum for a UI-component boundary. */
.rp-room-overlay-chip {
  border: 2px solid color-mix(in srgb, currentColor 50%, transparent);
  box-shadow: var(--shadow-md);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}

.rp-room-side {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-height: 0;
  min-width: 0;
}

/* Tiles: 2-column grid on desktop, horizontal-scroll strip on mobile — same markup, CSS-only reflow. */
.rp-room-tiles {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

.rp-room-tile {
  position: relative;
  aspect-ratio: 16 / 10;
  background: var(--muted);
  border: 2px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Active speaker — primary ring, mirrors the mockup's active-speaker treatment. */
.rp-room-tile--speaking { border-color: var(--primary); }
.rp-room-tile video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Self-view mirror: flip only the local participant's camera (selfie-style), not remote tiles. */
.rp-room-tile--self video { transform: scaleX(-1); }
.rp-room-tile-avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--secondary);
  color: var(--secondary-foreground);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 600;
}
.rp-room-tile-name {
  position: absolute;
  left: 6px;
  bottom: 5px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 7px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--foreground) 78%, transparent);
  color: var(--background);
  font-size: 10.5px;
  font-weight: 600;
  max-width: calc(100% - 12px);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rp-room-tile-micoff {
  position: absolute;
  right: 6px;
  bottom: 5px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--foreground) 78%, transparent);
  color: var(--background);
  display: flex;
  align-items: center;
  justify-content: center;
}
.rp-room-tile-hand {
  position: absolute;
  right: 6px;
  top: 5px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--warning);
  color: var(--warning-foreground);
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Moderation stays below the video: visible touch/keyboard actions must not cover the hand,
   camera or media indicators, including when a participant has both speech and drawing rights. */
.rp-room-person { min-width: 0; }
.rp-room-tile-actions { display: flex; flex-wrap: wrap; gap: 4px; padding-top: 5px; }
.rp-room-tile-act {
  min-height: 44px;
  flex: 1 1 auto;
  padding: 5px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--foreground);
  font: inherit;
  font-size: 11px;
  line-height: 1.25;
  font-weight: 600;
  cursor: pointer;
}
.rp-room-tile-act--primary { border-color: var(--primary); background: var(--primary); color: var(--primary-foreground); }
.rp-room-tile-act:disabled { opacity: 0.6; cursor: wait; }
.rp-room-tile-act:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.rp-room-floor-badge {
  position: absolute; left: 5px; top: 5px;
  padding: 3px 6px; border-radius: var(--radius-sm);
  background: var(--success-muted); color: var(--success-muted-foreground);
  font-size: 10px; font-weight: 600;
}
.rp-room-speaking {
  display: flex; flex: 0 0 auto; align-items: center; flex-wrap: wrap;
  gap: 6px 14px; padding: 8px 16px;
  background: var(--card); border-bottom: 1px solid var(--border);
  font-size: 12px; min-width: 0;
}
.rp-room-speaking .rp-sel { min-width: 0; max-width: 100%; }
.rp-room-speaking .rp-sel-host { min-width: 0; }
.rp-room-speaking .rp-sel-btn, .rp-room-speaking .rp-sel-native { min-height: 44px; }
.rp-room-speaking-guidance { color: var(--muted-foreground); }
.rp-room-speaking-error { color: var(--destructive); flex-basis: 100%; }
.rp-room-hand-hint { font-size: 11px; }

/* The single raised-hand banner (LOCKED-3) — only the first raiser is named, "и ещё N" covers the rest.
   Tutor-only, and a stage notice rather than a row in the side column: on a phone the column below the
   stage is fully spoken for, so the banner landed under the fold — the tutor had to scroll a live lesson
   to find out someone had a question. As a stage notice it is unmissable and costs the column nothing.
   Rounded like the chips it stacks with, and shadowed for the same reason (it sits over tutor content). */
.rp-room-hand {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  padding: 6px 6px 6px 12px;
  background: var(--warning-muted);
  border: 1px solid color-mix(in srgb, var(--warning) 30%, transparent);
  border-radius: 999px;
  box-shadow: var(--shadow-md);
  color: var(--warning-muted-foreground);
}
.rp-room-hand-text {
  flex: 0 1 auto;
  min-width: 0;
  font-size: 13px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* flex-shrink:0 + nowrap: the text beside it flexes, so a long «Рука поднята: Александра и ещё 2» used
   to squeeze this button until «Дать слово» broke onto a second line inside a 30px pill. */
.rp-room-hand-btn { flex: 0 0 auto; height: 30px; padding: 0 14px; font-size: 12.5px; white-space: nowrap; }

/* The ONE RoomChatPanel host (LOCKED: never two instances) — desktop: a normal column; narrow portrait:
   a full-screen panel that slides up on the --open modifier (RoomPage's `_chatOpen`); phone landscape:
   an absolute inset:0 panel over the side column (see the landscape media query near the end of this
   file). The panel is always mounted; only its CSS position/visibility differs.
   The `@media` blocks below are the TRUE COMPLEMENT of the narrow-portrait condition further down —
   `(orientation: landscape), (min-width: 960px)` — so the two never both apply and never leave a gap.
   `min-width: 960px` (not 961) pairs with the portrait block's `max-width: 959.98px`: the .02px split at
   the Sm|Md boundary, so a viewport of exactly 960px is `_isNarrow == false` desktop and lands here.
   Narrow LANDSCAPE also matches the first arm, but the landscape block near the end of the file
   re-overrides these later in the cascade — intended. These blocks hide `.rp-room-chat-close-wrap`
   because a static desktop column has nothing to close; wherever the panel is an overlay the ✕ is the
   only dismissal, since nothing here ever dims the stage (LOCKED). */
.rp-room-chathost {
  display: flex;
  flex-direction: column;
  min-height: 0;
}
@media (orientation: landscape), (min-width: 960px) {
  .rp-room-chathost { flex: 1; }
}
.rp-room-chat-close-wrap { display: inline-flex; }
.rp-room-chat-close {
  width: 26px;
  height: 26px;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--secondary);
  color: var(--secondary-foreground);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
@media (orientation: landscape), (min-width: 960px) {
  .rp-room-chat-close-wrap { display: none; }
}

/* The «Материалы» panel (RoomMaterialsPanel) shares the chat's host shape: always mounted, placed and
   shown purely here. Unlike the chat it is never a permanent column — it exists only while opened —
   so its base state is display:none at every size. On a desktop it takes the chat's column
   (.rp-room-side--materials hides the chat host underneath it); the narrow blocks further down turn it
   into the same full-screen / side-column overlay the chat becomes there. */
.rp-room-materialshost {
  display: none;
  flex-direction: column;
  min-height: 0;
}
.rp-room-materialshost--open { display: flex; }
@media (orientation: landscape), (min-width: 960px) {
  .rp-room-materialshost { flex: 1; }
}
.rp-room-side--materials .rp-room-chathost,
.rp-room-side--materials .rp-room-chaterror { display: none; }
/* The desktop bar has no chat button (the chat is a column); while the materials cover that column the
   button is the way back to it, unread dot included. */
.rp-room-bar--materials .rp-room-bar-chat { display: inline-flex; }
.rp-room-bar-materials--active {
  border-color: color-mix(in srgb, var(--primary) 45%, transparent);
  background: var(--secondary);
  color: var(--foreground);
}

/* Same card as .rp-rchat, so the two panels read as one family when they swap in the same column. */
.rp-room-materials {
  display: flex;
  flex-direction: column;
  min-height: 0;
  height: 100%;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.rp-room-materials-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
  font-weight: 600;
  flex-shrink: 0;
}
.rp-room-materials-title { flex: 1; }
.rp-room-materials-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.rp-room-materials-item { min-width: 0; }
.rp-room-materials-item + .rp-room-materials-item {
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
.rp-room-materials-empty {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted-foreground);
  font-size: 13px;
  text-align: center;
  padding: 20px;
}
/* A spinner over a --card ground takes the muted tone — the .rp-rchat-empty override, same reason. */
.rp-room-materials-empty .rp-spin {
  border-color: color-mix(in srgb, var(--muted-foreground) 30%, transparent);
  border-top-color: var(--muted-foreground);
}
.rp-room-materials-foot {
  flex-shrink: 0;
  display: flex;
  padding: 10px 14px;
  border-top: 1px solid var(--border);
}
.rp-room-materials-foot .rp-btn-outline { width: 100%; }
/* Bottom controls bar — labeled pills on desktop, circular icon-only + a mobile-only chat FAB ≤768px. */
.rp-room-bar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 10px;
  height: 64px;
  padding: 0 16px;
  background: var(--card);
  border-top: 1px solid var(--border);
}
.rp-room-bar-spacer { flex: 1; }
/* nowrap + flex-shrink:0 across the whole bar: these are fixed-content controls, and a label breaking
   onto a second line inside a 40px pill is never the right answer — the bar wraps or scrolls instead. */
.rp-room-bar-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 40px;
  padding: 0 14px;
  flex-shrink: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--card);
  color: var(--foreground);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
}
/* Mic/cam off tone — labels stay "Микрофон"/"Камера" always (LOCKED-9); only the icon + this tone change. */
.rp-room-bar-btn--off {
  border-color: color-mix(in srgb, var(--destructive) 40%, transparent);
  background: var(--destructive-muted);
  color: var(--destructive-muted-foreground);
}
.rp-room-bar-hand--active {
  border-color: color-mix(in srgb, var(--warning) 45%, transparent);
  background: var(--warning-muted);
  color: var(--warning-muted-foreground);
}
.rp-room-bar-screen--active {
  border-color: color-mix(in srgb, var(--success) 45%, transparent);
  background: var(--success-muted);
  color: var(--success-muted-foreground);
}
/* Recording, active — the destructive tone, the same one the badge in the top bar wears: the two are
   the same fact seen from the two sides of the room, and a green «recording» would read as a state
   the tutor may leave running. */
.rp-room-recbtn--active {
  border-color: color-mix(in srgb, var(--destructive) 45%, transparent);
  background: var(--destructive-muted);
  color: var(--destructive-muted-foreground);
}
.rp-room-recbtn[disabled] { opacity: 0.6; cursor: default; }
.rp-room-bar-chat {
  display: none;
  position: relative;
  flex-shrink: 0;
  width: 46px;
  height: 46px;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: var(--card);
  color: var(--foreground);
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.rp-room-bar-chat-dot {
  position: absolute;
  top: 0;
  right: 0;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--destructive);
  border: 2px solid var(--card);
}
.rp-room-bar-leave {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 40px;
  padding: 0 16px;
  flex-shrink: 0;
  border: 0;
  border-radius: var(--radius-md);
  background: var(--destructive);
  color: var(--destructive-foreground);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
}

/* State cards: unsupported-browser / join-error full-page fallbacks. */
.rp-room-state {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100dvh;
  padding: 24px;
}
.rp-room-state-card {
  width: 100%;
  max-width: 440px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  text-align: center;
  padding: 44px 32px;
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  background: var(--background);
  box-shadow: var(--shadow-md);
}
.rp-room-state-title { font-size: 16px; font-weight: 700; }
.rp-room-state-body { font-size: 13.5px; color: var(--muted-foreground); line-height: 1.6; }
.rp-room-state-actions { display: flex; gap: 10px; margin-top: 16px; flex-wrap: wrap; justify-content: center; }

/* ---------- Mobile/tablet portrait (orientation: portrait, <960px — wave 7 Task 6) ---------- */
/* Widened from the shell's flat `max-width:768px` (Видеокомната.dc.html "Планшет · вертикально", 834px)
   to `(orientation:portrait) and (max-width:959.98px)` — the SAME cutoff `_isNarrow`'s MudBlazor
   Sm breakpoint uses (RoomPage.razor), so the CSS layout and the C#-driven RoomChatPanel/RoomToolRail
   visibility contracts never disagree (959.98 not 960: MudBlazor's Md bracket starts AT 960, so a
   viewport of exactly 960px is `_isNarrow == false` desktop and must get the desktop CSS too — fix
   round 2, Minor-4; the .02px split is the Bootstrap/MudBlazor convention at breakpoint boundaries).
   Before this widening there was a real 769–959px gap: `_isNarrow` was already "narrow" there (Sm
   bracket, <960) so the chat sheet/mobile chat-FAB rendered, but this block's CSS didn't apply yet
   (still desktop-shaped `.rp-room-main` grid) — a tablet in portrait fell through the crack. Gating on
   `orientation:portrait` (not just width) also means a genuinely landscape-oriented narrow window
   (e.g. a resized short-but-wide desktop browser) no longer gets this stacked-square treatment — see
   the narrow-landscape block near the end of this file instead. Everything inside stays width-driven
   (vw-based), so it needs no change to keep working at tablet widths — only the trigger condition
   widened. */
@media (orientation: portrait) and (max-width: 959.98px) {
  .rp-room-top { height: 44px; padding: 0 12px; gap: 8px; }
  .rp-room-top-scene { display: none; }
  /* The subtitle repeats the lesson's time window, which the countdown chip already conveys; on a phone
     it was the second line that pushed the title block to 44px inside a 48px bar. */
  .rp-room-top-sub { display: none; }
  .rp-room-top-users { font-size: 12px; }

  .rp-room-scenerow {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    order: 2;
    flex: 0 0 auto;
    min-width: 0;
  }
  .rp-room-scenerow .rp-seg { width: auto; }
  .rp-room-scenerow .rp-seg-tab { flex: 0 0 auto; padding: 7px 14px; white-space: nowrap; }

  /* `overflow-x: hidden` is explicit and load-bearing: `overflow-y:auto` alone leaves overflow-x
     computed as `auto` (a `visible` on one axis becomes `auto` when the other isn't), so ANY too-wide
     child — the tool-rail row, the tile strip — turned the whole content column into a horizontally
     scrollable page. Wide children now scroll inside themselves instead. */
  .rp-room-main {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 8px 12px 10px;
    overflow-y: auto;
    overflow-x: hidden;
  }
  .rp-room-main > * { min-width: 0; }

  .rp-room-stage-slot { order: 1; flex: 1 1 0; width: 100%; }

  .rp-room-main > .rp-rtool { order: 3; flex: 0 0 auto; }

  .rp-room-side { order: 4; flex: 0 0 auto; gap: 8px; }

  /* Fixed pixel size, not aspect-ratio + flex-basis: the tile's height used to be derived from the
     strip's line height, so once the column ran out of room the whole strip collapsed. */
  .rp-room-tiles {
    display: flex;
    flex-direction: row;
    gap: 6px;
    overflow-x: auto;
    overflow-y: hidden;
    flex: 0 0 auto;
    scrollbar-width: none;
  }
  .rp-room-tiles::-webkit-scrollbar { display: none; }
  .rp-room-person { flex: 0 0 168px; width: 168px; }
  /* The 16:10 border box leaves at least 100px of actual video inside its two borders. */
  .rp-room-tiles .rp-room-tile { width: 168px; height: 105px; aspect-ratio: auto; }
  .rp-room-speaking { padding: 6px 12px; gap: 5px 10px; }
  .rp-room-speaking-rule, .rp-room-speaking-guidance { flex-basis: 100%; }
  .rp-room-speaking .rp-sel { width: 100%; }

  .rp-room-hand { padding: 8px 10px; gap: 8px; }
  .rp-room-hand-text {
    font-size: 12.5px;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* Chat is a FULL-SCREEN panel here, not a bottom sheet clinging to the stage's lower edge. The sheet
     had to derive its top from the square's rendered height (the old `--room-sheet-top: 100vw + 40px`
     magic), which stopped being true the moment the square gained a height cap — and on a 667px phone
     it left the chat ~250px tall anyway. A panel you deliberately opened, with its own ✕, may cover the
     stage; that is the ordinary mobile-chat shape and it needs no baseline arithmetic. */
  .rp-room-chathost {
    position: absolute;
    inset: 0;
    height: auto;
    z-index: 30;
    box-shadow: var(--shadow-lg);
    background: var(--card);
    transform: translateY(100%);
    /* visibility, not just pointer-events: `pointer-events: none` stops the mouse but leaves the closed
       panel in the TAB ORDER, and the panel is now a full-viewport box parked one screen below the room
       (`.rp-room`'s scrollHeight is exactly 2×100dvh). Tabbing into its message input would scroll the
       room a full viewport down to reveal the focused field — and since `.rp-room` is overflow:hidden,
       the lesson would just go blank with no scrollbar to explain it. `visibility: hidden` takes it out
       of the tab order, so nothing can focus into it and nothing can trigger that scroll. (The off-screen
       box still counts toward scrollable overflow; that is harmless once it is unreachable.)
       Zero-duration visibility with a DELAY, not a transitioned one: the panel must be visible for the
       whole slide-in (delay 0 when opening) and stay painted for the whole slide-out (delay = the
       transform's duration when closing). Interpolating visibility instead leaves what it reads
       mid-animation up to the engine. */
    visibility: hidden;
    transition: transform 0.2s ease, visibility 0s linear 0.2s;
    pointer-events: none;
  }
  .rp-room-chathost--open {
    transform: translateY(0);
    visibility: visible;
    transition: transform 0.2s ease, visibility 0s linear 0s;
    pointer-events: auto;
  }
  /* The materials are the chat's full-screen panel here too, minus the slide: display:none while closed
     already keeps them out of the tab order, which is what the chat's visibility dance exists for. */
  .rp-room-materialshost {
    position: absolute;
    inset: 0;
    height: auto;
    z-index: 30;
    box-shadow: var(--shadow-lg);
    background: var(--card);
  }

  .rp-room-bar { justify-content: center; gap: 10px; padding: 9px 14px 12px; height: auto; }
  .rp-room-bar-spacer { display: none; }
  .rp-room-bar-btn {
    width: 46px;
    height: 46px;
    padding: 0;
    border-radius: 50%;
    justify-content: center;
  }
  .rp-room-bar-lbl { display: none; }
  .rp-room-bar-chat { display: inline-flex; }
  .rp-room-bar-leave {
    width: 56px;
    height: 46px;
    padding: 0;
    justify-content: center;
    border-radius: 999px;
  }
}

/* The tutor's portrait bar carries seven controls (mic, camera, screen, record, «Материалы», chat, leave):
   at 46px rounds with 10px gaps that is ~390px of content, so a 375px phone clipped the mic and «Покинуть»
   off both edges. On a phone-width portrait screen the bar takes the landscape phone's control sizes
   (40px rounds, a 48px leave) with tighter gaps, which fits seven controls down to a 360px screen. */
@media (orientation: portrait) and (max-width: 430px) {
  .rp-room-bar { gap: 6px; padding: 8px 12px 12px; }
  .rp-room-bar-btn,
  .rp-room-bar-chat { width: 40px; height: 40px; }
  .rp-room-bar-leave { width: 48px; height: 40px; }
}

/* The connection chip's label is 14–20 characters («Отличная связь · TCP») — on a phone top bar sharing
   375px with a title, a countdown and a participant count there is no width for it. The dot carries the
   tone, `title`/`aria-label` carry the detail, and tapping the chip toasts the same line (RoomPage) since
   a touch device can't hover. Width-only (not orientation-gated): a 390px landscape phone has the same
   problem. */
@media (max-width: 600px) {
  .rp-room-net-lbl { display: none; }
  .rp-room-net { padding: 8px; }
  .rp-room-timer { min-width: 0; padding: 5px 10px; }
  /* The badge gives up its word, never its dot: the top bar has no width for another label here, and
     an indicator that disappears on a phone is an indicator that is not there for half the room. */
  .rp-room-recbadge-lbl { display: none; }
  .rp-room-recbadge { padding: 8px; }
}

/* ---------- Phone/narrow landscape (wave 7 Task 6, widened by the T6 re-review) ---------- */
/* Narrow landscape: the unchanged DOM dissolves .rp-room-main into the room grid. The stage slot
   spans all rows, while the real header, speaking rule, scrolling participants and wrapping controls
   share the 240px side column. The tool rail stays vertical independently of the width-only C# signal. */
@media (orientation: landscape) and (max-width: 959.98px) {
  .rp-room {
    display: grid;
    grid-template-columns: 48px minmax(0, 1fr) 240px;
    /* Extremely short/keyboard viewports may need to scroll the controls rather than clip exit. */
    overflow-y: auto;
    grid-template-rows: auto auto 1fr auto;
    grid-template-areas:
      "rail stage top"
      "rail stage speaking"
      "rail stage side"
      "rail stage bar";
  }
  .rp-room-main { display: contents; }
  .rp-room-speaking { grid-area: speaking; padding: 5px 10px; }

  .rp-room-main > .rp-rtool {
    grid-area: rail;
    position: sticky;
    top: 0;
    max-height: 100dvh;
    width: 48px;
    flex-direction: column;
    padding: 8px 0;
    border: 0;
    border-right: 1px solid var(--border);
    border-radius: 0;
    overflow-y: auto;
    min-height: 0;
  }
  .rp-room-main > .rp-rtool .rp-rtool-sep { width: 26px; height: 1px; margin: 4px 0; }

  .rp-room-stage-slot {
    grid-area: stage;
    position: sticky;
    top: 0;
    width: 100%;
    height: min(100%, 100dvh);
    align-self: start;
  }

  .rp-room-top {
    grid-area: top;
    min-width: 0;
    height: auto;
    padding: 8px;
    gap: 4px;
    /* The header column is narrow (width − rail − stage); title + timer + scene tabs don't fit on one
       line. Wrapping keeps every control reachable — without it the nowrap flex row's max-content width
       inflates the 1fr track and the whole grid overflows .rp-room (smoke find). The two spacers must
       NOT hold a line open here, so they collapse. */
    flex-wrap: wrap;
  }
  /* The spacers must not survive here: a flex-grow item on a WRAPPED line eats that line's remainder and
     pushes the next control onto a line of its own — with both spacers alive the header column grew to
     three lines (title / segment / chips) and 125px of a 375px-tall screen. */
  .rp-room-top .rp-room-top-spacer { display: none; }
  /* The lesson title is the first thing to go in this layout, on the same reasoning that already drops
     the participant count below: the header column is only `100vw − rail − stage` wide (244px on a
     667×375 handset), every line it wraps to is a line taken from the video tiles under it, and the
     title is the one item you don't need mid-lesson — you know which lesson you are in, and portrait,
     desktop and every screen you arrive from all show it. Dropping it buys a whole line back (125px →
     87px at 667×375, 92px → 54px at 844×390) and lets the stage tabs keep their LABELS, which for this
     audience is the trade worth making.
     Taken out of FLOW, not out of the document (bb-compat.css's .sr-only geometry): `display:none` would
     also take it out of the accessibility tree, so rotating the phone would stop a screen reader from
     ever reaching the lesson name. Absolute positioning removes it from the flex line just as
     completely. */
  .rp-room-top-title {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  /* Compact status chips: the connection chip keeps its tone dot and drops the 20-character label, same
     as on a phone in portrait (the 600px width query doesn't reach an 844px landscape handset), and the
     countdown gives up the width floor it holds elsewhere — tabular figures alone keep it from twitching
     once it is the only thing on its line. */
  .rp-room-net-lbl { display: none; }
  .rp-room-net { padding: 8px; }
  .rp-room-timer { min-width: 0; padding: 5px 10px; }
  .rp-room-recbadge-lbl { display: none; }
  .rp-room-recbadge { padding: 8px; }
  /* Icon-only stage tabs. With labels the segment alone is 204px of a 244px column, so tabs + countdown
     + connection dot could not share a line no matter what else was dropped — the header stayed two
     lines and the second one came out of the video tiles. Icons take the segment to ~84px and the whole
     header to one line. The buttons carry aria-label/title (RoomPage.razor) precisely because this rule
     removes their only accessible name; the label markup stays in the DOM for every other breakpoint. */
  .rp-room-top-scene .rp-room-scenetab-lbl { display: none; }
  .rp-room-top-scene .rp-seg-tab { padding: 8px 12px; }
  /* Wrapping stays as the safety net for whatever a future control adds to this column, even though the
     icon-only segment above now fits on one line at the narrowest size in range (667×375). */
  .rp-room-top-scene { flex-wrap: wrap; min-width: 0; }
  .rp-room-top-scene .rp-seg { min-width: 0; max-width: 100%; }
  .rp-room-top-scene .rp-seg-tab { min-width: 0; }
  .rp-room-top-users { display: none; } /* dropped for space — not shown in the mockup's compact header */

  .rp-room-side {
    grid-area: side;
    position: relative;
    min-width: 0;
    overflow-y: auto;
  }
  .rp-room-tiles { grid-template-columns: 1fr; justify-items: center; gap: 6px; overflow-y: auto; flex: 0 0 auto; }
  /* 208×117 preserves 16:9 and leaves 113px of video inside the decorative borders. */
  .rp-room-tiles .rp-room-person { width: 208px; max-width: 100%; }
  .rp-room-tile { aspect-ratio: 16 / 9; } /* LOCKED: 16:9 here, unlike desktop/portrait's 16:10 */

  .rp-room-bar {
    grid-area: bar;
    min-width: 0;
    height: auto;
    justify-content: center;
    gap: 8px;
    padding: 6px 12px 10px;
    flex-wrap: wrap;
  }
  .rp-room-bar-spacer { display: none; }
  .rp-room-bar-btn { width: 40px; height: 40px; padding: 0; border-radius: 50%; justify-content: center; }
  .rp-room-bar-lbl { display: none; }
  .rp-room-bar-chat { display: inline-flex; width: 40px; height: 40px; }
  .rp-room-bar-leave { width: 48px; height: 40px; padding: 0; justify-content: center; }

  /* A wide paper leaves only a short participant column on phones. Chat/materials use the same
     full-room narrow sheet interaction as portrait; closed chat stays mounted and out of focus. */
  .rp-room-chathost {
    display: none;
    position: fixed;
    inset: 0;
    border: 0;
    border-left: 1px solid var(--border);
    border-radius: 0;
    box-shadow: none;
    z-index: 21;
  }
  .rp-room-chathost.rp-room-chathost--open { display: flex; }
  /* Chat-error notice: the same inset:0 panel as the chat host (they render mutually exclusively) —
     a flow-styled card would be cut by the side column's height the moment the sheet layout takes over. */
  .rp-room-chaterror {
    position: absolute;
    inset: 0;
    margin: 0;
    border: 0;
    border-radius: 0;
    background: var(--card);
    z-index: 21;
  }
  /* Materials share the full-room narrow panel, retaining their mount-on-open media behavior. */
  .rp-room-materialshost {
    position: fixed;
    inset: 0;
    border-left: 1px solid var(--border);
    background: var(--card);
    z-index: 21;
  }
  .rp-room-chat-close-wrap { display: inline-flex; } /* re-shown — the landscape-arm complement above hides it */

  /* A phone-landscape stage is height-bound and short (390px on an 844×390 handset): pull the on-stage
     slide nav tighter so it doesn't eat the slide's bottom line. */
  .rp-room-stagenav { gap: 2px; }
  .rp-room-stagenav-btn { width: 32px; height: 32px; }
  .rp-room-stagenav-count { height: 32px; padding: 0 10px; }
  .rp-room-picker { bottom: 4px; }
}


/* A keyboard-sized landscape window scrolls the right column as a room, while paper/tools stay put.
   Preserve enough side viewport for one camera and its first 44px action together. */
@media (orientation: landscape) and (max-width: 959.98px) and (max-height: 300px) {
  .rp-room-side { min-height: 166px; }
}
