/* 09-admin.css — part 09/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. */

/* ── Admin shell (rp-adm*, wave 8 Task 3 — AdminPageHeader + hub-page CSS-каркас for T4–T8,
   Админ-обзор.dc.html) ──────────────────────────────────────────────────────────────────── */

.rp-adm-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 20px;
}
.rp-adm-head h1 {
  margin: 0;
  font-size: 18px;
  font-weight: 700;
}
.rp-adm-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 11.5px;
  font-weight: 600;
  background: var(--warning-muted);
  color: var(--warning-muted-foreground);
  white-space: nowrap;
}
.rp-adm-head__spacer { flex: 1; }

/* KPI card grid (/admin Обзор — the 4 top-level stat tiles). */
.rp-adm-stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
  margin-bottom: 14px;
}

/* Stat tile — the whole card is a link (Админ-обзор.dc.html §stats). */
.rp-adm-tile {
  display: block;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--card);
  padding: 16px 18px;
  text-decoration: none;
  color: var(--foreground);
  transition: border-color 0.15s ease;
}
.rp-adm-tile:hover { border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); }
.rp-adm-tile__label {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--muted-foreground);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 6px;
}
.rp-adm-tile__row { display: flex; align-items: baseline; gap: 8px; }
.rp-adm-tile__value {
  font-size: 26px;
  font-weight: 700;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.rp-adm-tile__sub { font-size: 12.5px; font-weight: 600; }
.rp-adm-tile__sub--success { color: var(--success-muted-foreground); }
.rp-adm-tile__sub--muted   { color: var(--muted-foreground); }
.rp-adm-tile__sub--danger  { color: var(--destructive-muted-foreground); }

/* Email-failures banner-link (visible only when EmailFailures > 0). */
.rp-adm-alert {
  display: flex;
  align-items: center;
  gap: 12px;
  border: 1px solid color-mix(in srgb, var(--warning) 40%, var(--border));
  background: var(--warning-muted);
  color: var(--warning-muted-foreground);
  border-radius: var(--radius-lg);
  padding: 11px 16px;
  margin-bottom: 22px;
  text-decoration: none;
}
.rp-adm-alert__text { flex: 1; font-size: 13px; }
.rp-adm-alert__cta { font-size: 12.5px; font-weight: 600; white-space: nowrap; }

/* "Новые тенанты" / "Последние ошибки" — two bordered list-cards, side by side on desktop. */
.rp-adm-lists { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.rp-adm-list {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--card);
  overflow: hidden;
}
.rp-adm-list__head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 13px 18px;
  border-bottom: 1px solid var(--border);
}
.rp-adm-list__title { font-size: 14px; font-weight: 700; flex: 1; }
.rp-adm-list__link { font-size: 12.5px; font-weight: 600; color: var(--primary); text-decoration: none; white-space: nowrap; }
.rp-adm-list-empty { padding: 16px 18px; font-size: 13px; color: var(--muted-foreground); }

/* One row skin for both list kinds: tenant rows use -avatar/-plan, error rows use -dot; both share
   -body/-title/-sub/-meta. Both are `<a>` (clickable to their own detail page — T8 made the
   «Новые площадки» rows link into /admin/tenants/{id}, matching the error rows' existing anchor). */
.rp-adm-list-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 18px;
  border-bottom: 1px solid var(--border);
  text-decoration: none;
  color: var(--foreground);
}
.rp-adm-list-row:last-child { border-bottom: 0; }
a.rp-adm-list-row:hover { background: var(--secondary); }
.rp-adm-list-row__avatar {
  width: 30px;
  height: 30px;
  flex-shrink: 0;
  border-radius: var(--radius-md);
  background: var(--accent);
  color: var(--accent-foreground);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
}
.rp-adm-list-row__dot {
  width: 8px;
  height: 8px;
  flex-shrink: 0;
  border-radius: 999px;
  background: var(--border);
}
.rp-adm-list-row__dot--active { background: var(--destructive); }
.rp-adm-list-row__body { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.rp-adm-list-row__title {
  font-size: 13.5px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rp-adm-list-row__title--mono { font-family: var(--font-mono); font-size: 13px; }
.rp-adm-list-row__sub {
  font-size: 12px;
  color: var(--muted-foreground);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rp-adm-list-row__plan {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  background: var(--muted);
  color: var(--muted-foreground);
  white-space: nowrap;
  /* Long plan names («Профессиональный») exceed the grid column: without max-width+ellipsis the
     pill gets hard-clipped mid-letter by the cell (wave-8 live smoke finding). */
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: bottom;
}
.rp-adm-list-row__meta {
  font-size: 12px;
  color: var(--muted-foreground);
  white-space: nowrap;
  flex-shrink: 0;
}

/* Generic grid-таблица shell for hub pages (T5 «Пользователи», T6 «Подписки», T7 «Ошибки») —
   each page sets its own column widths via a `--adm-cols` custom property on a modifier class
   (e.g. `.rp-adm-table--tenants { --adm-cols: 100px 1fr 120px 90px; }`) instead of a bespoke
   grid-template-columns per hub, mirroring rp-fin-table/-thead/-row. */
.rp-adm-table {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--card);
  overflow: hidden;
}
.rp-adm-table__head,
.rp-adm-table__row {
  display: grid;
  grid-template-columns: var(--adm-cols, 1fr);
  gap: 12px;
  align-items: center;
  padding: 13px 18px;
  border-bottom: 1px solid var(--border);
}
.rp-adm-table__head {
  padding: 10px 18px;
  font-size: 11.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted-foreground);
}
.rp-adm-table__row { text-decoration: none; color: var(--foreground); }
.rp-adm-table__row:last-child { border-bottom: 0; }
.rp-adm-table__row:hover { background: var(--secondary); }

/* Mobile card fallback for rp-adm-table (same per-hub-modifier pattern, mirrors rp-fin-cards). */
.rp-adm-cards { display: none; flex-direction: column; gap: 9px; }
.rp-adm-card {
  display: block;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--card);
  padding: 13px 15px;
}

/* ── /admin/tenants hub (T5) ──────────────────────────────────────────────────────────────── */

.rp-adm-toolbar { display: flex; align-items: center; gap: 10px; margin-bottom: 16px; }
.rp-adm-search {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  max-width: 340px;
  height: 38px;
  padding: 0 12px;
  border: 1px solid var(--input);
  border-radius: var(--radius-md);
  background: var(--card);
  color: var(--muted-foreground);
}
.rp-adm-search-input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: none;
  background: transparent;
  color: var(--foreground);
  font: inherit;
  font-size: 13.5px;
}
.rp-adm-toolbar-spacer { flex: 1; }
.rp-adm-count { font-size: 12.5px; color: var(--muted-foreground); white-space: nowrap; }

/* Per-hub column widths for the three /admin/tenants tabs (last column = kebab, omitted for the
   read-only «Ученики» tab). */
.rp-adm-table--tenants  { --adm-cols: 1.5fr 1fr 116px 104px 112px 120px 132px 40px; }
.rp-adm-table--users    { --adm-cols: 1.3fr 1.4fr 1.3fr 1fr 100px 40px; }
.rp-adm-table--students { --adm-cols: 1.3fr 1fr 110px 130px 110px; }
/* /admin/resources — «кто занимает место». */
.rp-adm-table--resources { --adm-cols: 1.6fr 110px 90px 160px; }
.rp-adm-table--refusals { --adm-cols: 1.6fr 110px 110px; }
.rp-adm-table--tcourses { --adm-cols: 1.8fr 100px 90px 100px 80px 90px 110px; }
.rp-adm-table--ttests { --adm-cols: 1.8fr 110px 100px 90px 90px 120px; }
/* Записи занятий в уроках: урок/курс, длительность, источник, кто подтвердил, «Снять». */
.rp-adm-table--trecordings { --adm-cols: 1.6fr 100px 1.3fr 1.2fr 80px; }

/* Свёрнутая группа полей внутри карточки плана (Потолки). Свёрнута по умолчанию: сегодня все её
   поля пусты, и развёрнутая она удвоила бы высоту карточки ради четырёх «без ограничений». */
.rp-adm-plan-more { margin-top: 4px; }
.rp-adm-plan-more > summary { cursor: pointer; font-size: 12.5px; color: var(--muted-foreground); padding: 4px 0; }
.rp-adm-plan-more > summary:hover { color: var(--foreground); }

/* Действия и пояснение внутри карточки блока площадки (Личные потолки). */
.rp-adm-card-actions { display: flex; align-items: center; gap: 10px; margin-top: 12px; flex-wrap: wrap; }
.rp-adm-card-hint { margin-top: 8px; font-size: 12px; line-height: 1.45; color: var(--muted-foreground); }

/* Generic cell content, reused across the three tables. */
.rp-adm-cell-stack { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.rp-adm-cell-main {
  font-size: 13.5px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rp-adm-cell-sub {
  font-size: 12px;
  color: var(--muted-foreground);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Money that is owed or stopped. The only two registers the «Платит нам» subline has — a fuller
   tone vocabulary here would start competing with the status chip's five. */
.rp-adm-cell-sub--warn { color: var(--warning-muted-foreground); }

/* ── Плитки-сегменты: каждая И ЕСТЬ выборка ─────────────────────────────────────────────────
   Не разбиение множества: «Платят» пересекает остальные, потому что это другая ось.
   Класс СВОЙ (rp-adm-segtile), а не rp-adm-tile: тот уже носят KPI-плитки на четырёх админских
   экранах, и вторая декларация того же селектора в этом же файле молча переписала бы им паддинг и
   повесила курсор-палец на неклика­бельные div'ы. CssHygieneTests такое не ловит — он сравнивает
   ЧАСТИ бандла, а обе декларации оказались бы в части 09. */
.rp-adm-segtiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(152px, 1fr));
  gap: 10px;
  margin-bottom: 12px;
}

.rp-adm-segtile {
  display: block;
  text-align: left;
  padding: 13px 15px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--card);
  color: var(--foreground);
  font: inherit;
  cursor: pointer;
}

.rp-adm-segtile--on {
  border-color: var(--primary);
  box-shadow: 0 0 0 1px var(--primary) inset;
}

.rp-adm-segtile__label {
  display: block;
  font-size: 11.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted-foreground);
  margin-bottom: 6px;
}

.rp-adm-segtile__line { display: flex; align-items: baseline; gap: 7px; }
.rp-adm-segtile__count { font-size: 22px; font-weight: 700; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.rp-adm-segtile__share { font-size: 12px; font-weight: 600; color: var(--muted-foreground); }
.rp-adm-segtile__note { display: block; font-size: 11.5px; color: var(--muted-foreground); margin-top: 4px; }

/* Ярлык ритма. Тонов четыре — ровно столько, сколько значений у TenantRhythmKind; платёжное
   состояние сюда НЕ подмешивается, у него свой чип в колонке «Статус». */
.rp-adm-rhythm { font-size: 12.5px; font-weight: 600; }
.rp-adm-rhythm--alive { color: var(--success-muted-foreground); }
.rp-adm-rhythm--growing { color: var(--primary); }
.rp-adm-rhythm--fading { color: var(--warning-muted-foreground); }
.rp-adm-rhythm--abandoned { color: var(--muted-foreground); }
.rp-adm-rhythm--none { color: var(--muted-foreground); }

/* ── Метки: полоска-фильтр, чип в строке, каталог ────────────────────────────────────────────
   Цвет метки — ДАННЫЕ (палитра в AdminTagsDialog.Palette), поэтому он приходит инлайновым style,
   а не классом: класс на каждый цвет означал бы миграцию ради нового оттенка. */
.rp-adm-tagstrip {
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}

.rp-adm-tagstrip__label {
  font-size: 11.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted-foreground);
  margin-right: 2px;
}

.rp-adm-tagstrip__chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 28px;
  padding: 0 11px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--card);
  color: var(--foreground);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}

/* Цвет метки приходит переменной --adm-tag (AdminTagsDialog.ChipStyle), а не готовым color: палитра
   подобрана под светлую тему, и тёмно-зелёный #136B3E прямо на тёмной карточке не читается —
   в тёмной теме текст подмешивается к --foreground ниже, что инлайновый color перебить не дал бы. */
.rp-adm-tagstrip__chip--on {
  border-color: currentColor;
  background: color-mix(in srgb, var(--adm-tag, var(--foreground)) 10%, transparent);
  color: var(--adm-tag, var(--foreground));
}
.rp-adm-tagstrip__dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.rp-adm-tagstrip__count { font-weight: 500; opacity: .7; }

/* Чип метки в строке списка и в шторке. */
.rp-adm-tag-chip {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 10.5px;
  font-weight: 700;
  white-space: nowrap;
  flex-shrink: 0;
  background: color-mix(in srgb, var(--adm-tag, var(--foreground)) 10%, transparent);
  color: var(--adm-tag, var(--foreground));
}
.dark .rp-adm-tag-chip,
.dark .rp-adm-tagstrip__chip--on {
  background: color-mix(in srgb, var(--adm-tag, var(--foreground)) 22%, transparent);
  color: color-mix(in srgb, var(--adm-tag, var(--foreground)) 45%, var(--foreground));
}

/* Имя площадки и её метки в одну строку; имя ужимается, метки — нет. */
.rp-adm-cell-nameline {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

.rp-adm-cell-nameline .rp-adm-cell-main { min-width: 0; }
.rp-adm-drawer-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 16px; }

/* Каталог меток. */
.rp-adm-tags-list { display: flex; flex-direction: column; gap: 6px; margin: 10px 0 14px; }
.rp-adm-tags-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.rp-adm-tags-usage { font-size: 12px; color: var(--muted-foreground); }
.rp-adm-tags-spacer { flex: 1; }
.rp-adm-tags-del { color: var(--destructive); }
.rp-adm-tags-empty { font-size: 13px; color: var(--muted-foreground); }
.rp-adm-tags-new {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}

.rp-adm-tags-name { flex: 1 1 180px; min-width: 0; }
.rp-adm-tags-palette { display: inline-flex; align-items: center; gap: 4px; }
.rp-adm-tags-swatch {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 2px solid transparent;
  padding: 0;
  cursor: pointer;
}

.rp-adm-tags-swatch--on { border-color: var(--foreground); }

/* Тело шторки быстрого просмотра (оболочка — общий RpRowDrawer в 01-core.css). Сетка 2×N с
   разделителями из фона: одна рамка вокруг и зазор в 1px дают линии без border на каждой ячейке. */
.rp-adm-drawer-chips {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}

.rp-adm-drawer-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  margin-bottom: 16px;
}

.rp-adm-drawer-cell {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 11px 13px;
  background: var(--card);
  min-width: 0;
}

.rp-adm-drawer-cell__label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted-foreground);
}

.rp-adm-drawer-cell__value {
  font-size: 15px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.rp-adm-drawer-cell__note { font-size: 11px; color: var(--muted-foreground); }

.rp-adm-drawer-label {
  font-size: 11.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted-foreground);
  margin-bottom: 7px;
}

.rp-adm-drawer-owner {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 13px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  margin-bottom: 16px;
}

.rp-adm-drawer-domains {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-bottom: 16px;
  font-size: 12px;
  color: var(--muted-foreground);
}

/* Выбранная строка: полоса слева, а не заливка — заливка спорит с наведением и с тонами чипов.
   Курсор-палец ТОЛЬКО у таблицы площадок: класс .rp-adm-table__row носят ещё двенадцать админских
   таблиц, и в одиннадцати из них строка не кликается вовсе — палец обещал бы им клик, которого нет. */
.rp-adm-table__row { position: relative; }
.rp-adm-table--tenants .rp-adm-table__row { cursor: pointer; }
.rp-adm-card--sel { border-color: var(--primary); }
.rp-adm-table__row--sel::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  background: var(--primary);
}

/* «42 / 100» plus how full that is. The bar is decoration for a number already printed above it,
   hence aria-hidden at the call site: a screen reader reading «полоса 84 процента» after «42 из 100»
   says the same thing twice. */
.rp-adm-seats { gap: 5px; }
.rp-adm-seatbar {
  display: block;
  width: 100%;
  height: 4px;
  border-radius: 999px;
  background: var(--muted);
  overflow: hidden;
}
.rp-adm-seatbar__fill {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--success);
}
.rp-adm-seatbar__fill--near { background: var(--warning); }
.rp-adm-seatbar__fill--full { background: var(--destructive, #A31D1D); }
.rp-adm-cell-mono { font-family: var(--font-mono); }
.rp-adm-cell-right { text-align: right; font-variant-numeric: tabular-nums; }
.rp-adm-cell-user { display: flex; align-items: center; gap: 10px; min-width: 0; }
.rp-adm-avatar {
  width: 28px;
  height: 28px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--muted);
  color: var(--muted-foreground);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
}
.rp-adm-rolechips { display: flex; gap: 4px; flex-wrap: wrap; }

/* Row action cell — a BbDropdownMenu trigger, mirrors rp-tm-kebab (TestsPage). */
.rp-adm-rowact { display: flex; justify-content: center; }
.rp-adm-kebab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  flex-shrink: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--muted-foreground);
  cursor: pointer;
}
.rp-adm-kebab:hover { background: var(--secondary); color: var(--foreground); }

/* "Показать ещё" — RpShowMore, the one pagination affordance (grows the caller's local `take`
   and re-fires ComputeState). Was six per-page copies of this exact recipe (rp-adm-more,
   rp-pay-more, rp-ann-more, rp-tm-more, rp-course-enr-more, rp-fin-more) plus three
   rp-btn-textlink variants; all render this class now. */
.rp-more {
  display: block;
  width: 100%;
  margin-top: 10px;
  padding: 10px;
  border: 1px dashed var(--border);
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--muted-foreground);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  text-align: center;
}
.rp-more:hover { background: var(--secondary); color: var(--foreground); }

/* Mobile card body (rp-adm-card's own content — T4 only sets the outer card shell above). */
.rp-adm-card-top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.rp-adm-card-title {
  font-size: 13.5px;
  font-weight: 600;
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rp-adm-card-sub { font-size: 12px; color: var(--muted-foreground); margin-top: 3px; }

/* Tenant-name links into /admin/tenants/{id} — inherit cell colour, underline on hover only. */
.rp-adm-tenant-link { color: inherit; text-decoration: none; }
.rp-adm-tenant-link:hover { text-decoration: underline; }

/* Balance-of-lessons figure — bold weight (unlike the plain rp-adm-cell-right student-count column);
   zero tints destructive-muted (mockup's balColor rule). */
.rp-adm-balance { font-weight: 600; }
.rp-adm-balance--zero { color: var(--destructive-muted-foreground); }

/* «Приглашения» collapsed section on the «Ученики» tab — native <details>, no JS. */
.rp-adm-accordion {
  margin-top: 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--card);
  overflow: hidden;
}
.rp-adm-accordion-summary {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 13px 18px;
  cursor: pointer;
  font-size: 14px;
  font-weight: 700;
  list-style: none;
}
.rp-adm-accordion-summary::-webkit-details-marker { display: none; }
.rp-adm-accordion-count { font-weight: 500; color: var(--muted-foreground); }
.rp-adm-accordion-body { border-top: 1px solid var(--border); padding: 4px 0; }

.rp-adm-invtable { display: flex; flex-direction: column; }
.rp-adm-invtable__head,
.rp-adm-invtable__row {
  display: grid;
  grid-template-columns: 1.3fr 1fr 100px 100px 100px;
  gap: 12px;
  align-items: center;
  padding: 9px 18px;
}
.rp-adm-invtable__head {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted-foreground);
}
.rp-adm-invtable__row { border-top: 1px solid var(--border); font-size: 12.5px; }

@media (max-width: 640px) {
  /* Две плитки в ряд на 360px — это ~160px на плитку, поэтому здесь тише и отступы, и кегль числа:
     десктопные 16/18px padding при подписи в две строки давали плитку в 110px высотой ради одной
     цифры, и четыре KPI занимали экран целиком. */
  .rp-adm-stats { grid-template-columns: repeat(2, 1fr); gap: 10px; }
  .rp-adm-tile { padding: 12px 14px; }
  .rp-adm-tile__label { letter-spacing: 0.03em; margin-bottom: 4px; }
  .rp-adm-tile__value { font-size: 22px; }

  /* Строка списка на телефоне — сетка, а не один ряд флексов. Во флексе имя (body: flex 1, то есть
     базис 0) отдавало всю ширину соседям с собственной шириной: пилюля плана забирала 120px, дата
     ещё 65, и на САМОЕ важное поле оставалось 44px — «Влад…». Здесь имя и дата делят первую строку,
     а пилюля плана уходит на вторую: обрезаться нечему. */
  .rp-adm-list-row {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    column-gap: 10px;
    row-gap: 4px;
  }
  .rp-adm-list-row__avatar,
  .rp-adm-list-row__dot { grid-column: 1; grid-row: 1; }
  .rp-adm-list-row__body { grid-column: 2; grid-row: 1; }
  .rp-adm-list-row__meta { grid-column: 3; grid-row: 1; }
  .rp-adm-list-row__plan { grid-column: 2 / -1; grid-row: 2; justify-self: start; }

  .rp-adm-table { display: none; }
  .rp-adm-cards { display: flex; }
  .rp-adm-lists { grid-template-columns: 1fr; }

  .rp-adm-search { max-width: none; }
  .rp-adm-count { display: none; }

  /* Панель инструментов не переносилась: поиск (201px) + «Скопировать адреса» (168px) вылезали
     за 328px содержимого, и страница «Вовлечение» прокручивалась вбок. */
  .rp-adm-toolbar { flex-wrap: wrap; }
  .rp-adm-toolbar .rp-btn-outline { flex: 1 1 100%; }

  /* Заголовок карточки — flex: 1 при базисе 0, поэтому пара чипов справа («Информация» +
     «Активен» = 202px) оставляла ему 78px и обрезала «Активный бан…». Заголовок занимает строку
     целиком, чипы встают под ним. */
  .rp-adm-card-top .rp-adm-card-title { flex: 1 1 100%; }

  .rp-adm-invtable__head { display: none; }
  .rp-adm-invtable__row {
    grid-template-columns: 1fr;
    gap: 2px;
    padding: 10px 16px;
  }
}

/* ── /admin/finance hub (T6) ──────────────────────────────────────────────────────────────── */

/* «Подписки» tab: 4 KPI tiles reuse rp-adm-stats/-tile as plain divs (no href — no per-tile drill
   target here, unlike /admin Обзор's tiles). A tile with a single figure and no delta gets its tone
   on the VALUE itself rather than on a -sub caption (there's nothing to caption). */
.rp-adm-tile__value--warning { color: var(--warning-muted-foreground); }
.rp-adm-tile__value--danger  { color: var(--destructive-muted-foreground); }

.rp-adm-filterbar {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  background: var(--muted);
  border-radius: var(--radius-md);
}
.rp-adm-filter {
  padding: 6px 12px;
  border: 0;
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: 12.5px;
  font-weight: 500;
  background: transparent;
  color: var(--muted-foreground);
  cursor: pointer;
}
.rp-adm-filter--active {
  font-weight: 600;
  background: var(--card);
  color: var(--foreground);
  box-shadow: var(--shadow-xs);
}

/* «План» column is minmax so long plan names («Профессиональный») get room before the pill
   falls back to its own ellipsis (wave-8 live smoke finding). */
.rp-adm-table--subs { --adm-cols: 1.4fr minmax(100px, max-content) 130px 130px 110px 40px; }

/* «Оплачено до» cell tone — mirrors the row's status tone (rp-adm-cell-sub is the neutral default). */
.rp-adm-cell-tone--warning { color: var(--warning-muted-foreground); }
.rp-adm-cell-tone--danger  { color: var(--destructive-muted-foreground); }

/* ── «Планы и монетизация» tab ────────────────────────────────────────────────────────────── */

.rp-adm-plans-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
  max-width: 920px;
  margin-bottom: 10px;
}
.rp-adm-plan-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--card);
  padding: 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.rp-adm-plan-head { display: flex; align-items: center; gap: 8px; }
.rp-adm-plan-name { font-size: 14.5px; font-weight: 700; flex: 1; }
.rp-adm-plan-count { font-size: 12px; color: var(--muted-foreground); white-space: nowrap; }

.rp-adm-plan-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }
.rp-adm-plan-chip {
  display: inline-flex;
  align-items: center;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  background: var(--muted);
  color: var(--muted-foreground);
}

.rp-adm-plans-savebar { margin: 12px 0 4px; }
.rp-adm-plans-savebtn {
  height: 38px;
  padding: 0 18px;
  border: 0;
  border-radius: var(--radius-md);
  background: var(--primary);
  color: var(--primary-foreground);
  font: inherit;
  font-size: 13.5px;
  font-weight: 600;
  cursor: pointer;
}
.rp-adm-plans-savebtn:disabled { opacity: 0.6; cursor: default; }
.rp-adm-plans-caption { font-size: 12px; color: var(--muted-foreground); margin-top: 8px; }

/* Generic labelled-input field pair — plan cards + the bottom AI-billing trio. */
.rp-adm-field { display: block; min-width: 0; }
.rp-adm-field-label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  margin-bottom: 4px;
  color: var(--muted-foreground);
}
.rp-adm-field-input {
  width: 100%;
  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: 13.5px;
  font-variant-numeric: tabular-nums;
}
.rp-adm-field-hint { font-size: 12px; color: var(--muted-foreground); margin-top: 4px; }

/* Section headers shared by packs / promos / AI-billing. */
.rp-adm-section { margin-bottom: 28px; }
.rp-adm-section-head { display: flex; align-items: center; margin-bottom: 12px; gap: 12px; }
.rp-adm-section-title { font-size: 15px; font-weight: 700; }
.rp-adm-section-sub { font-size: 12.5px; color: var(--muted-foreground); margin-top: 2px; }
.rp-adm-addbtn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 36px;
  padding: 0 14px;
  border: 0;
  border-radius: var(--radius-md);
  background: var(--primary);
  color: var(--primary-foreground);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}
.rp-adm-addbtn:hover { opacity: 0.92; }

.rp-adm-table--packs  { --adm-cols: 1fr 110px 110px 70px 40px; }
.rp-adm-table--promos { --adm-cols: 130px 1fr 120px 105px 100px 70px 40px; }

.rp-adm-billing-fields { display: flex; align-items: flex-end; gap: 16px; flex-wrap: wrap; max-width: 720px; }
.rp-adm-billing-fields .rp-adm-field { flex: 1; min-width: 160px; }

/* Hand-rolled 36×21 switch (RpAdminSwitch.razor) — see П-9 note on the component. */
/* .rp-adm-switch geometry is in the canonical toggle block (global controls section); only the
   disabled state is component-specific. */
.rp-adm-switch:disabled { cursor: not-allowed; opacity: 0.6; }

/* A dialog's own "Активен" field: label + switch as a flex row inside one rp-scard-dlg-field cell. */
.rp-adm-switchrow { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.rp-adm-switchrow .rp-sched-dlg-label { margin-bottom: 0; }

@media (max-width: 640px) {
  .rp-adm-plans-grid { grid-template-columns: 1fr; }
  .rp-adm-section-head { flex-wrap: wrap; }
}

/* ── /admin/errors hub (T7) ───────────────────────────────────────────────────────────────── */

/* «Ошибки» tab (Ошибки и Email-сбои.dc.html): reuses rp-adm-filterbar/-filter(--active) verbatim
   for the Новые/Все/Решённые segment (T6 precedent) plus a compact native select (rp-adm-select)
   for the ErrorSource filter — the old MudToggleGroup's "Все/API/WASM/MAUI" labels, kept as a
   select per the task brief rather than a second segment row (no room for two segment bars on
   mobile); rp-adm-toolbar--wrap lets that combined toolbar row wrap under rp-adm-toolbar without
   touching the class every other hub's toolbar shares. rp-adm-table gains --adm-cols modifier
   rp-adm-table--errors (7 cols: when / exception+message / route / tenant / count / status /
   chevron); the trailing chevron cell (rp-adm-chevron, a centered muted glyph) is purely
   decorative — the row itself is the click target, an anchor wrapping rp-adm-table__row exactly
   like AdminIndex's rp-adm-list-row. Mobile cards reuse rp-adm-card verbatim, also wrapped in an
   anchor — a.rp-adm-card resets link styling (text-decoration/color) the same way a.rp-adm-list-row
   already does. rp-adm-note is the small "показаны первые N из M" honest-truncation caption (no
   "Показать ещё" here per the brief — take is a fixed 100).
   Деталь (ErrorDetail.razor): rp-adm-back is the "← Ошибки" pill button; rp-adm-detail-head/
   -title-wrap/-title/-msg lay out the ExceptionType(mono)+Message header next to the "Отметить
   решённой" button (reuses rp-adm-addbtn — same primary-filled recipe as the packs/promos "+"
   button, T6). rp-adm-metachips/-metachip(-k/-v) is the bordered pill row for non-empty meta
   fields (Маршрут/Тенант/Пользователь/Источник/Браузер/CorrelationId/Когда) — a chip only renders
   when its field is non-null (ErrorDetail.razor's own filter), never shown empty. rp-adm-panel-card
   (-head/-title/-body) is the generic bordered-card shell reused by both the Stack trace block
   (rp-adm-stacktrace + rp-adm-copybtn) and the "Повторы этой группы" block (rp-adm-repeats-row +
   rp-adm-repeats-more "Показать все N →" link, which expands the already-fetched list client-side —
   no second read).
   «Email-сбои» tab: rp-adm-table--email is its --adm-cols modifier (6 cols); rp-adm-rowbtn is the
   per-row "Повторить" button (also reused, full-width, on the ≤640px card); rp-adm-retryall is the
   toolbar's "Повторить все неотправленные" button (same bordered recipe as rp-adm-rowbtn plus an
   icon gap + disabled-while-busy dimming). rp-adm-empty-success(-icon/-title) is a dedicated
   success-toned empty state ("Все письма доставлены") — NOT the dashed rp-empty2/RpEmpty look;
   mirrors rp-asg-empty's success-circle recipe (Задания.dc.html) but kept in this file's rp-adm-*
   namespace since it's a different feature. */

.rp-adm-toolbar--wrap { flex-wrap: wrap; row-gap: 8px; }

.rp-adm-select {
  height: 34px;
  padding: 0 10px;
  border: 1px solid var(--input);
  border-radius: var(--radius-md);
  background: var(--card);
  color: var(--foreground);
  font: inherit;
  font-size: 12.5px;
  cursor: pointer;
}

.rp-adm-table--errors { --adm-cols: 110px 1.8fr 1fr 1fr 70px 110px 24px; }
.rp-adm-table--email  { --adm-cols: 110px 1.3fr 1.1fr 1.5fr 80px 110px; }

.rp-adm-chevron { display: flex; justify-content: center; color: var(--muted-foreground); }

a.rp-adm-card { text-decoration: none; color: inherit; cursor: pointer; display: block; }

.rp-adm-note { font-size: 12px; color: var(--muted-foreground); margin: 12px 2px 0; }

/* Second-echelon pagination (Task 7): the honest cap note that replaces "Показать ещё" once a
   growing admin list page hits the mirrored client-side AdminPageCap (500, matching the server's
   Math.Clamp(take, 1, 500)) — see AdminUsersPanel/AdminTenantsPanel/AdminStudentsPanel/
   AdminSubscriptionsPanel. Deliberately its own class (not rp-adm-note) per the task brief, even
   though the look is the same recipe. */
.rp-admin-cap-note { color: var(--muted-foreground); font-size: .85rem; padding: 8px 0; }

.rp-adm-back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--card);
  color: var(--muted-foreground);
  font: inherit;
  font-size: 12.5px;
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
  margin-bottom: 12px;
}
.rp-adm-back:hover { color: var(--foreground); background: var(--secondary); }

.rp-adm-detail-head { display: flex; align-items: flex-start; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; }
.rp-adm-detail-title-wrap { flex: 1; min-width: 260px; }
.rp-adm-detail-title { font-size: 17px; font-weight: 700; font-family: var(--font-mono); letter-spacing: -0.01em; }
.rp-adm-detail-msg { font-size: 13.5px; color: var(--muted-foreground); margin-top: 3px; }

.rp-adm-metachips { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }
.rp-adm-metachip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 11px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--card);
  font-size: 12px;
}
.rp-adm-metachip-k { color: var(--muted-foreground); }
.rp-adm-metachip-v { font-weight: 600; font-family: var(--font-mono); font-size: 11.5px; }

.rp-adm-panel-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--card);
  overflow: hidden;
  margin-bottom: 14px;
}
.rp-adm-panel-card-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 11px 18px;
  border-bottom: 1px solid var(--border);
}
.rp-adm-panel-card-title { font-size: 13px; font-weight: 700; flex: 1; }
.rp-adm-panel-card-sub { font-size: 11.5px; color: var(--muted-foreground); }
.rp-adm-panel-card-body { padding: 14px 18px; }

/* Compact three-column rows inside a panel card: when, what, how much. Used by the payments tail
   and the AI-credit ledger. Both markups shipped referencing these names with nothing defining
   them, so the two lists rendered as unstyled inline spans running together on one line. */
.rp-adm-detail-rows { display: flex; flex-direction: column; }
.rp-adm-detail-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 0;
  border-top: 1px solid var(--border);
  font-size: 12.5px;
}
.rp-adm-detail-rows > .rp-adm-detail-row:first-child { border-top: 0; }
.rp-adm-detail-row__meta {
  flex-shrink: 0;
  width: 62px;
  color: var(--muted-foreground);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
}
.rp-adm-detail-row__body {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rp-adm-detail-row__amount {
  flex-shrink: 0;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* The tab strip and the window switcher share one row: the period governs every number on the
   page, so it must never look like a control belonging to whichever tab is open. */
.rp-adm-tabrow {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 18px;
}
/* The strip is a flex ITEM here, so its own bottom gap would both grow the row and push the
   period switcher off the tabs' centre line — the row carries the gap instead. */
.rp-adm-tabrow .rp-tabs-underline,
.rp-adm-tabrow .rp-tabs-chips,
.rp-adm-tabrow .rp-tabs-seg { margin-bottom: 0; }
.rp-adm-tabrow-tabs { flex: 1; min-width: 240px; }
.rp-adm-tabrow-label { font-size: 12px; color: var(--muted-foreground); }

/* Occupancy meter: a label, «34 из 50», and a bar whose colour escalates with the fill. The tone
   is on the fill rather than the container so several meters can stack in one card, each speaking
   for its own limit. */
.rp-adm-meters { display: flex; flex-direction: column; gap: 14px; }
.rp-adm-meter-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 6px;
}
.rp-adm-meter-label { flex: 1; font-size: 13px; font-weight: 600; }
.rp-adm-meter-value {
  font-size: 12.5px;
  color: var(--muted-foreground);
  font-variant-numeric: tabular-nums;
}
.rp-adm-meter-track {
  height: 8px;
  border-radius: 999px;
  background: var(--muted);
  overflow: hidden;
}
.rp-adm-meter-fill { height: 100%; border-radius: 999px; background: var(--success); }
.rp-adm-meter-fill--warning { background: var(--warning); }
.rp-adm-meter-fill--danger { background: var(--destructive); }
.rp-adm-meter-note { font-size: 11.5px; color: var(--muted-foreground); margin-top: 4px; }

/* Chart legend, in the card head rather than inside the SVG: the plot is viewBox-scaled, so text
   drawn in it would shrink with the card while the card's own type stayed put. */
.rp-adm-legend { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.rp-adm-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  color: var(--muted-foreground);
}
.rp-adm-legend-dot { width: 8px; height: 8px; border-radius: 2px; flex-shrink: 0; }

/* Week heatmap: a label column plus one column per OCCUPIED hour (the component crops the empty
   night away and sets --adm-heat-cols). Cells carry their tint inline — the scale is relative to the
   busiest hour of this particular grid, which no static class can express. */
.rp-adm-heat {
  display: grid;
  grid-template-columns: 34px repeat(var(--adm-heat-cols, 13), minmax(0, 1fr));
  gap: 4px;
  align-items: center;
  overflow-x: auto;
}
.rp-adm-heat-corner { display: block; }
.rp-adm-heat-hour { font-size: 10px; color: var(--muted-foreground); text-align: center; }
.rp-adm-heat-day { font-size: 11px; color: var(--muted-foreground); }
.rp-adm-heat-cell { display: block; height: 20px; border-radius: 3px; }
.rp-adm-heat-cell--empty { background: var(--muted); }

/* An observation under the card it is about. Sits INSIDE the card body, so it reads as a note on
   those numbers rather than as a page-level banner. */
.rp-adm-insight {
  display: flex;
  gap: 10px;
  margin-top: 14px;
  padding: 11px 13px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--muted);
}
.rp-adm-insight--warning {
  border-color: var(--warning);
  background: var(--warning-muted, var(--muted));
}
.rp-adm-insight-icon { flex-shrink: 0; color: var(--muted-foreground); line-height: 1; }
.rp-adm-insight--warning .rp-adm-insight-icon { color: var(--warning-muted-foreground, var(--warning)); }
.rp-adm-insight-body { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.rp-adm-insight-title { font-size: 13px; font-weight: 600; }
.rp-adm-insight-text { font-size: 12.5px; color: var(--muted-foreground); }

/* Owner presence: one square per day. Three states, not two — «ещё не наблюдали» must not look like
   «не заходил», or the strip accuses every owner of the period before collection existed. */
.rp-adm-strip { display: flex; flex-wrap: wrap; gap: 3px; }
.rp-adm-strip-cell {
  width: 13px;
  height: 13px;
  border-radius: 3px;
  background: var(--muted);
  border: 1px solid var(--border);
}
.rp-adm-strip-cell--on { background: var(--primary); border-color: transparent; }
.rp-adm-strip-cell--unknown { background: transparent; border-style: dashed; }

.rp-adm-copybtn {
  height: 28px;
  padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--muted-foreground);
  font: inherit;
  font-size: 11.5px;
  font-weight: 500;
  cursor: pointer;
}
.rp-adm-copybtn:hover { background: var(--secondary); color: var(--foreground); }

.rp-adm-stacktrace {
  margin: 0;
  padding: 16px 18px;
  font-family: var(--font-mono);
  font-size: 11.5px;
  line-height: 1.7;
  color: var(--muted-foreground);
  overflow-x: auto;
  background: var(--background);
  white-space: pre;
}

.rp-adm-repeats-row {
  font-size: 12.5px;
  color: var(--muted-foreground);
  padding: 3px 0;
}
.rp-adm-repeats-more {
  display: block;
  font-size: 12.5px;
  color: var(--primary);
  font-weight: 600;
  cursor: pointer;
  background: none;
  border: 0;
  padding: 3px 0;
  font-family: inherit;
  text-align: left;
}

.rp-adm-retryall {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 34px;
  padding: 0 13px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--card);
  color: var(--foreground);
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}
.rp-adm-retryall:hover { background: var(--secondary); }
.rp-adm-retryall:disabled { opacity: 0.6; cursor: default; }

.rp-adm-rowbtn {
  height: 30px;
  padding: 0 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--card);
  color: var(--foreground);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}
.rp-adm-rowbtn:hover { border-color: var(--primary); color: var(--primary); }
.rp-adm-rowbtn:disabled { opacity: 0.6; cursor: default; }

.rp-adm-empty-success {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 40px 24px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--card);
}
.rp-adm-empty-success-icon {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--success-muted);
  color: var(--success-muted-foreground);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 14px;
}
.rp-adm-empty-success-title { font-size: 15px; font-weight: 700; }

/* Телефон. Паспорт площадки/ошибки на 360px разъезжался: каждая пилюля-факт занимала строку
   целиком, кебаб переносился на СВОЮ строку под ними (полоса пустоты во весь экран), а «Период»
   оставался висеть справа от вкладок. Здесь шапка — сетка (заголовок · кебаб в одной строке, факты
   под ними во всю ширину), а сами факты — плотная пара «ключ → значение» вместо столбика пилюль:
   тот же набор фактов, вчетверо меньше высоты. Пилюльный вид остаётся десктопным. */
@media (max-width: 640px) {
  .rp-adm-detail-head {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: start;
    gap: 10px;
    margin-bottom: 12px;
  }
  .rp-adm-detail-title-wrap { grid-column: 1; grid-row: 1; min-width: 0; }
  .rp-adm-detail-head > .rp-adm-kebab { grid-column: 2; grid-row: 1; }
  .rp-adm-detail-head > .rp-adm-metachips { grid-column: 1 / -1; grid-row: 2; margin-bottom: 0; }
  .rp-adm-back { margin-bottom: 10px; }

  /* display: contents на пилюле — ключ и значение становятся ячейками ОБЩЕЙ сетки, поэтому
     значения выстраиваются в колонку и читаются как паспорт, а не как разбросанные пилюли.
     Обёртка при этом теряет рамку и padding — ради этого и сделано. */
  .rp-adm-metachips {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: 4px 10px;
    align-items: baseline;
  }
  .rp-adm-metachip { display: contents; }
  .rp-adm-metachip-v { overflow-wrap: anywhere; }

  /* «Период» подписывает пилюли 7/30/90, которые и так называют себя; на телефоне подпись только
     ломала ряд вкладок. Вкладки занимают строку целиком, переключатель окна — следующую. */
  .rp-adm-tabrow { gap: 8px; }
  .rp-adm-tabrow-tabs { flex: 1 1 100%; min-width: 0; }
  .rp-adm-tabrow-label { display: none; }

  /* Заголовок карточки и легенда графика не помещаются в один ряд: легенда не переносится
     пословно, поэтому весь дефицит доставался заголовку — «Уроки по дням» в три строки по слову.
     Переносим сам ряд: заголовок занимает строку целиком, легенда встаёт под ним. (Правило стои́т
     именно в этом, позднем медиа-блоке: .rp-adm-panel-card-title объявлен НИЖЕ раннего блока и при
     равной специфичности перебил бы его.) */
  .rp-adm-panel-card-head { flex-wrap: wrap; row-gap: 6px; }
  .rp-adm-panel-card-title { flex: 1 1 100%; }
}

/* ── PlatformBannerCard (rp-banner-card*, wave 8 Task 8 — Баннеры.dc.html) ───────────────────
   Shared banner look, deliberately its own prefix rather than rp-adm* — PlatformBannerCard.razor
   is reused OUTSIDE /admin too (PlatformBanner.razor in MainLayout, every cabinet page). Tone
   modifiers rp-banner-card--info/--warning (background/foreground/border from the --info-muted
   and --warning-muted token pairs + a color-mix border tint, matching the mockup's preview alert box); -icon
   (leading Lucide triangle-alert/info), -body (title+text stack), -title/-text with a --placeholder
   modifier for the admin publish page's live-preview empty state (muted italic "Заголовок баннера"/
   "Текст баннера" so the preview never looks broken while the form is empty — the real MainLayout
   consumer never hits this branch), -close (the dismiss crestik, rendered only when the caller wires
   OnDismiss). PlatformBanner.razor wraps its list in rp-banner-list (flex column, gap — per-card
   spacing the shared component itself doesn't assume, since the admin preview renders a single card
   with no list wrapper at all). */
.rp-banner-list { display: flex; flex-direction: column; gap: 10px; margin-bottom: 16px; }

.rp-banner-card {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  border-radius: var(--radius-md);
  padding: 10px 14px;
}
.rp-banner-card--warning {
  border: 1px solid color-mix(in srgb, var(--warning) 40%, var(--border));
  background: var(--warning-muted);
  color: var(--warning-muted-foreground);
}
.rp-banner-card--info {
  border: 1px solid color-mix(in srgb, var(--info) 40%, var(--border));
  background: var(--info-muted);
  color: var(--info-muted-foreground);
}
/* Whole-card click target (SubscriptionBanner → /subscription): the outlined button stays the
   visible affordance, the cursor is the only extra hint — no hover repaint on a tinted card. */
.rp-banner-card--clickable { cursor: pointer; }
.rp-banner-card__icon { flex-shrink: 0; display: inline-flex; margin-top: 1px; }
.rp-banner-card__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.rp-banner-card__title { font-size: 13px; font-weight: 700; line-height: 1.4; }
.rp-banner-card__text { font-size: 13px; line-height: 1.5; }
.rp-banner-card__text p { margin: 0; }
.rp-banner-card__title--placeholder,
.rp-banner-card__text--placeholder { opacity: 0.65; font-style: italic; }
.rp-banner-card__close {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border: 0;
  background: transparent;
  color: inherit;
  padding: 0;
  cursor: pointer;
  opacity: 0.7;
}
.rp-banner-card__close:hover { opacity: 1; }

/* На грубом указателе крестик получает настоящую цель: 20×20 — это меньше любого минимума (WCAG 2.5.8
   просит 24×24), а плашки на телефоне закрывают чаще всего именно пальцем. Растёт ПОЛЕ, не рисунок:
   иконка внутри та же, отрицательное поле не даёт ряду подрасти. */
@media (pointer: coarse) {
  .rp-banner-card__close { width: 40px; height: 40px; margin: -10px -10px -10px 0; }
}
/* Outline-CTA под текстом баннера (__body — flex column): не растягивать на всю ширину и дать
   небольшой отступ от текста. */
.rp-banner-card__body .rp-btn-outline { align-self: flex-start; margin-top: 4px; }

/* ── /admin/platform-announcements «Баннеры» (rp-ban*, wave 8 Task 8) ────────────────────────
   Two-column publish layout (SiteAppearancePanel's controls/preview split, reused for a banner
   instead of a whole landing page): rp-ban-grid (420px/1fr, collapses to one column <760px per the
   task brief — the dedicated breakpoint below, distinct from the shell's 768px / the rp-adm-table
   640px table-to-cards cutoff). rp-ban-form wraps the form in the generic rp-adm-panel-card shell;
   rp-ban-form-row is the Тип/Аудитория two-up sub-grid. rp-adm-field-input gains a --textarea
   modifier (auto height, resize:vertical, line-height) reused by the "Текст" field. rp-ban-preview
   (-eyebrow/-frame/-note) hosts the live PlatformBannerCard plus the mockup's dimmed page-skeleton
   (rp-ban-preview-skeleton/-skel-thumb/-skel-lines/-skel-line, opacity .45 + per-line width
   modifiers --60/--85/--70, exactly the mockup's "rest of the page" placeholder under the banner).
   History reuses rp-adm-table with a new --adm-cols modifier rp-adm-table--banners (Текст/Тип/
   Аудитория/Период/Статус/kebab) — mobile cards are read-only (no action), matching both the
   mockup and the T5/T6 no-kebab-on-mobile-card precedent (AdminTenantsPanel/AdminPlansPanel). */
.rp-ban-grid {
  display: grid;
  grid-template-columns: minmax(0, 420px) 1fr;
  gap: 20px;
  margin-bottom: 26px;
  align-items: start;
}

.rp-ban-form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

.rp-adm-field-input--textarea { height: auto; padding: 10px 12px; resize: vertical; line-height: 1.5; }

.rp-ban-preview-eyebrow {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted-foreground);
  margin-bottom: 10px;
}
.rp-ban-preview-frame {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--background);
  box-shadow: var(--shadow-xs);
  padding: 14px;
}
.rp-ban-preview-skeleton { display: flex; gap: 10px; opacity: 0.45; margin-top: 10px; }
.rp-ban-preview-skel-thumb {
  width: 130px;
  height: 88px;
  flex-shrink: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--card);
}
.rp-ban-preview-skel-lines { flex: 1; display: flex; flex-direction: column; gap: 8px; padding-top: 4px; }
.rp-ban-preview-skel-line { height: 10px; background: var(--muted); border-radius: 4px; }
.rp-ban-preview-skel-line--60 { height: 14px; width: 60%; }
.rp-ban-preview-skel-line--85 { width: 85%; }
.rp-ban-preview-skel-line--70 { width: 70%; }
.rp-ban-preview-note { font-size: 12px; color: var(--muted-foreground); line-height: 1.6; margin: 10px 2px 0; }

.rp-adm-table--banners { --adm-cols: 1.8fr 130px 130px 150px 90px 40px; }

@media (max-width: 760px) {
  .rp-ban-grid { grid-template-columns: 1fr; }
}

/* ── rp-banner-card--success/--danger (wave 9 Task 1) ─────────────────────────────────────────
   The --warning/--info tone modifiers above predate wave 9; --success/--danger complete the set
   so PlatformBannerCard (and any wave-9 replacement of a MudBlazor success/error Alert) can reuse
   the same card shape for a positive or destructive tone, matching the --success/--destructive
   muted token pairs used elsewhere (rp-chip--success/--danger, rp-prod-kind--success/--danger). */
.rp-banner-card--success {
  border: 1px solid color-mix(in srgb, var(--success) 40%, var(--border));
  background: var(--success-muted);
  color: var(--success-muted-foreground);
}
.rp-banner-card--danger {
  border: 1px solid color-mix(in srgb, var(--destructive) 40%, var(--border));
  background: var(--destructive-muted);
  color: var(--destructive-muted-foreground);
}


/* ── «Сменить адрес сайта» dialog (AdminRenameSlugDialog) ─────────────────────────────────────
   Input + static «.repetitum.ru» suffix, mirroring the sign-up slug group: the visible suffix is
   what keeps an admin from pasting the full domain into the slug field (the incident this feature
   exists for). The input reuses the shared rp-sched-dlg-input surface. */
.rp-adm-slugrow { display: flex; align-items: stretch; }
.rp-adm-slugrow .rp-sched-dlg-input {
  flex: 1;
  min-width: 0;
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}
.rp-adm-slugsuffix {
  display: flex;
  align-items: center;
  padding: 0 12px;
  border: 1px solid var(--input);
  border-left: 0;
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
  background: var(--muted);
  color: var(--muted-foreground);
  font-size: 14px;
  white-space: nowrap;
}
.rp-adm-slughint {
  font-size: 13px;
  color: var(--muted-foreground);
  line-height: 1.5;
  margin-top: 8px;
}

/* ── «Управление подпиской» dialog (AdminSubscriptionDialog) ──────────────────────────────────
   Four action labels («Продлить пробный период», «Оплата вне системы», …) don't fit the base
   inline-flex/nowrap .rp-seg in one row inside the 420px rp-sched-dlg — the control overflowed
   and the [role="dialog"] overflow:auto cap turned that into a horizontal scrollbar. Lay the
   segments out as a 2×2 grid with wrapping labels instead. */
.rp-adm-subdlg .rp-seg {
  display: grid;
  grid-template-columns: 1fr 1fr;
  width: 100%;
  margin-bottom: 14px;
}
.rp-adm-subdlg .rp-seg-tab {
  white-space: normal;
  text-align: center;
  line-height: 1.3;
  padding: 7px 10px;
  min-width: 0;
}

/* «Сменить план» → бесплатный: the hint that a live paid remainder is about to be discarded without
   any way back — the base .rp-sched-dlg-sub is a quiet muted-foreground caption, too easy to skim
   past for a warning that names lost money. */
.rp-sched-dlg-sub--danger { color: var(--destructive); }

/* Support conversations (/admin/support) — the left list column of the shared .rp-chat-shell grid.
   The right pane reuses .rp-convo-pane (RoomChatPanel brings its own inner chrome). */
.rp-sup-listcol {
  overflow-y: auto;
  background: var(--card);
  border-right: 1px solid var(--border);
  padding: 12px;
  min-height: 0;
}

/* .rp-adm-cards is the MOBILE fallback of rp-adm-table (display:none until ≤640px above) — but the
   support list has no table twin and renders cards at EVERY width, so re-enable them here. Without
   this the /admin/support list is present in the DOM yet invisible on any desktop viewport. */
.rp-sup-listcol .rp-adm-cards { display: flex; }

/* The support card is a <button> (other admin hubs use <a>/<div>), so undo the user-agent button
   look: full row width, left-aligned text; the owner/last-message subs are spans — stack them. */
.rp-sup-listcol .rp-adm-card {
  width: 100%;
  text-align: left;
  cursor: pointer;
  font: inherit;
}
.rp-sup-listcol .rp-adm-card:hover { background: var(--secondary); }
.rp-sup-listcol .rp-adm-card--active { border-color: var(--primary); background: var(--secondary); }
.rp-sup-listcol .rp-adm-card-sub {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The support hub stacks .rp-chat-shell BELOW an .rp-adm-head, which the shell's fixed
   height: calc(100vh - 64px - 56px) (03-chat.css, written for the header-less /chat page) knows
   nothing about — topbar + padding + head + shell summed past the viewport, so the DOCUMENT grew
   a scrollbar and the shell reserved more height than was actually left. Same fix as the mobile
   chat block in 03-chat.css: make the surrounding chrome one non-scrolling viewport box and let
   the shell flex-fill whatever the head leaves, instead of a calc that overshoots. Only
   .rp-convo-body / .rp-sup-listcol scroll. Desktop only — ≤768px is already covered there
   (its rules key off .rp-chat-shell, which this page also carries). */
@media (min-width: 769px) {
  .rp-shell:has(.rp-sup-listcol) { min-height: 0; height: 100vh; overflow: hidden; }
  .rp-shell__content:has(.rp-sup-listcol) {
    flex: none;                        /* stop growing to fill .rp-shell__main */
    height: calc(100vh - 64px);        /* viewport − sticky topbar */
    min-height: 0;
    overflow: hidden;
    display: flex;
  }
  .rp-shell__content:has(.rp-sup-listcol) .rp-shell__content-inner {
    flex: 1; min-width: 0; min-height: 0;
    display: flex; flex-direction: column;
  }
  .rp-chat-shell:has(.rp-sup-listcol) { flex: 1; height: auto; min-height: 0; }
}

/* «Помощь со входом» dialog — three gestures stacked softest-first, each a titled step with its
   own hint and action. Separated by a rule rather than cards: they are one ladder, not a menu. */
.rp-adm-help-step {
  padding: 12px 0;
  border-top: 1px solid var(--border);
}
.rp-adm-help-step:first-of-type { border-top: 0; }
.rp-adm-help-step-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--foreground);
  margin-bottom: 4px;
}
.rp-adm-help-hint {
  font-size: 13px;
  color: var(--muted-foreground);
  margin-bottom: 10px;
}
.rp-adm-help-row {
  display: flex;
  gap: 8px;
  align-items: center;
}
.rp-adm-help-row .rp-sched-dlg-input {
  flex: 1;
  min-width: 0;
  margin-bottom: 0;
}
.rp-adm-help-step .rp-sched-dlg-btn { margin-top: 10px; }

/* ── /admin/engagement «Воронка» (AdminFunnelPanel): the 5 stage tiles double as FILTERS —
   clicking one narrows the segment list to tenants stuck exactly at that stage. ─────────── */
.rp-adm-stats--funnel { grid-template-columns: repeat(5, 1fr); }
.rp-adm-tile--btn {
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  width: 100%;
}
.rp-adm-tile--active {
  border-color: var(--primary);
  box-shadow: inset 0 0 0 1px var(--primary);
}
/* Orthogonal filter chips are togglable and plentiful — let the bar wrap instead of overflowing. */
.rp-adm-filterbar--wrap { flex-wrap: wrap; }
.rp-adm-table--engage { --adm-cols: 1.3fr 1.4fr 150px 100px 100px 130px; }
@media (max-width: 640px) {
  .rp-adm-stats--funnel { grid-template-columns: repeat(2, 1fr); }
}

/* ── /admin/engagement «Кампании» (AdminCampaignsPanel + CampaignDialog) ─────────────────── */
.rp-adm-table--campaigns { --adm-cols: 1.8fr 130px 110px 110px 100px 44px; }
/* The row title doubles as the open/edit affordance — a real button for keyboard reach. */
.rp-adm-cmp-open {
  border: 0;
  background: transparent;
  padding: 0;
  font: inherit;
  font-weight: 600;
  color: var(--foreground);
  text-align: left;
  cursor: pointer;
}
.rp-adm-cmp-open:hover { color: var(--primary); }
/* Campaign editor dialog: wider than the 420px rp-scard-dlg — it carries a body textarea. */
.rp-adm-cmp-dlg { width: 640px; max-width: calc(100vw - 32px); }
.rp-adm-cmp-row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
/* Read-only view of a sent campaign: label/value rows, body text keeps its paragraphs. */
.rp-adm-cmp-view { display: flex; flex-direction: column; gap: 10px; margin-bottom: 16px; }
.rp-adm-cmp-view-row { display: flex; flex-direction: column; gap: 2px; font-size: 13.5px; }
.rp-adm-cmp-view-label { font-size: 12px; color: var(--muted-foreground); }
.rp-adm-cmp-view-body { white-space: pre-wrap; line-height: 1.5; }
@media (max-width: 640px) {
  .rp-adm-cmp-row2 { grid-template-columns: 1fr; }
}
