/* ===== CG Community — Global Styles ===== */

/* ===== Custom Fonts ===== */
@font-face {
  font-family: 'VelaSans';
  src: url('/fonts/VelaSans-Regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'VelaSans';
  src: url('/fonts/VelaSans-Medium.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'VelaSans';
  src: url('/fonts/VelaSans-SemiBold.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'VelaSans';
  src: url('/fonts/VelaSans-Bold.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Bounded';
  src: url('/fonts/Bounded-Regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Bounded';
  src: url('/fonts/Bounded-Black.woff2') format('woff2');
  font-weight: 900;
  font-style: normal;
  font-display: swap;
}

:root {
  --bg-primary: #000000;
  --bg-secondary: #121214;
  --bg-card: #1a1a1c;
  --bg-input: #121214;
  --gold: rgb(201, 166, 96);
  --gold-light: rgb(227, 200, 140);
  --gold-dark: rgb(165, 124, 61);
  --gold-1: rgb(189, 154, 89);
  --gold-2: rgb(201, 166, 96);
  --gold-3: rgb(165, 124, 61);
  --gold-4: rgb(227, 200, 140);
  --gold-gradient: linear-gradient(135deg, rgb(165,124,61), rgb(201,166,96), rgb(227,200,140), rgb(201,166,96));
  --white: #ffffff;
  --text-primary: #FFFFFF;
  --text-secondary: #999999;
  /* SPA Phase 8 a11y: #6c6c80 не проходил WCAG AA (4.5:1) на тёмном фоне
     (3.39 на --bg-card #1a1a1c). #8a8a9c — AA-pass на всех фонах (card 5.13,
     modal 5.52, black 6.20), сохраняет холодный оттенок (отличим от
     --text-secondary). Один токен → ~25 правил + .text-muted утилиты. */
  --text-muted: #8a8a9c;
  --border: rgba(201, 166, 96, 0.2);
  --border-color: rgba(201, 166, 96, 0.2);
  --success: #4caf50;
  --danger: #e74c3c;
  --warning: #f39c12;
  --radius: 12px;
  --radius-sm: 8px;
  --shadow: 0 4px 24px rgba(0, 0, 0, 0.3);
  --transition: all 0.3s ease;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* SPA Phase 8 a11y: видимое кольцо фокуса для клавиатурной навигации.
   :focus-visible — только при keyboard-focus (не на mouse-клик), поэтому
   мышиные клики по кнопкам кольца не показывают. Селектор по элементам
   (специфичность 0,1,1) перебивает базовые `.btn`/`.form-control { outline:none }`
   (0,1,0). Для base-правил той же специфичности (0,1,1) — напр.
   `.participants-search input { outline:none }` — нужен явный override (ниже).
   Цвет — брендбук золото (контраст 8.11 на чёрном). */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}
/* override для base-правил (0,1,1) с element-level outline:none — иначе
   tie по специфичности проигрывает по порядку правил, и кольцо не видно. */
.participants-search input:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

body {
  font-family: 'VelaSans', -apple-system, BlinkMacSystemFont, sans-serif;
  background: var(--bg-primary);
  color: var(--text-primary);
  min-height: 100vh;
  line-height: 1.6;
}

h1, h2, h3 {
  font-family: 'Bounded', sans-serif;
}

a {
  color: var(--gold);
  text-decoration: none;
  transition: var(--transition);
}

a:hover {
  color: var(--gold-light);
}

/* ===== Header ===== */
.header {
  background: #121214;
  border-bottom: 1px solid rgba(201, 166, 96, 0.2);
  padding: 0 24px;
  height: 80px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: sticky;
  top: 0;
  z-index: 100;
  backdrop-filter: blur(12px);
}

.logo {
  font-size: 1.4rem;
  font-weight: 700;
  color: var(--white);
  letter-spacing: 0.5px;
  display: flex;
  align-items: center;
}

.logo span {
  color: var(--gold);
}

.logo img {
  height: 72px;
  display: block;
}

.header-nav {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: nowrap;
}

@media (max-width: 768px) {
  /* M5-W1 (5): mobile header переработан.
     - env(safe-area-inset-top) добавляется к padding-top, чтобы content
       не уходил под iOS statusbar (Dynamic Island / notch).
     - На auth-страницах (`:has(#logoutBtn)`) — скрываем logo + logout,
       nav рендерится в single-row под statusbar с адаптивным сжатием
       кнопок (flex: 1 1 auto + min/max-width).
     - На public-страницах (login/register/legal/set-password/select-topics)
       — сохраняем legacy layout (logo + text-link nav-row), только
       добавляем safe-area-inset-top.
     `:has()` selector supported в iOS Safari 15.4+, Chrome 105+, Firefox 121+. */
  .header {
    /* Sticky на mobile (та же стратегия что на desktop). До этого был
       position: relative — хедер скроллился с контентом, что ломало iOS
       edge-swipe back: при scroll'нутом вниз состоянии iOS не находил
       привычной «золотой шапки» в верху viewport и показывал чёрный peek.
       z-index/backdrop-filter наследуются из базового .header правила. */
    position: sticky;
    top: 0;
    flex-wrap: wrap;
    /* «Интерфейс заезжает за часы»: заход по пушу = полная перезагрузка документа,
       и WKWebView отдаёт env(safe-area-inset-top)=0 до следующего runloop → шапка
       налезала на статус-бар. Берём max(env, var(--safe-top)) — safe-top.js сеет
       --safe-top синхронно из localStorage в <head>, первый кадр уже с инсетом
       (тот же приём, что в messaging.css --sat). */
    padding: calc(max(env(safe-area-inset-top, 0px), var(--safe-top, 0px)) + 8px) 16px 8px;
    gap: 8px;
    height: auto;
    min-height: 60px;
  }
  .header .logo {
    flex: 1;
  }
  .header .logo img {
    height: 52px;
  }
  .container-wide, .container-narrow, .container {
    padding-top: 16px;
  }

  /* === Public-mobile (login/register/legal/etc) — legacy layout === */
  .header:not(:has(#logoutBtn)) .header-nav {
    order: 3;
    width: 100%;
    justify-content: center;
    gap: 8px;
    padding: 8px 0;
    border-top: 1px solid var(--border);
    flex-wrap: wrap;
  }

  /* === Auth-mobile (с #logoutBtn) — single-row nav под statusbar === */
  .header:has(#logoutBtn) .logo,
  .header:has(#logoutBtn) #logoutBtn {
    display: none;
  }
  .header:has(#logoutBtn) {
    /* Padding-bottom симметричен top для compact header. */
    padding-bottom: 8px;
    gap: 0;
  }
  .header:has(#logoutBtn) .header-nav {
    width: 100%;
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    justify-content: space-around;
    align-items: center;
    gap: 4px;
    padding: 0;
    border-top: none;
  }
  .header:has(#logoutBtn) .header-nav > a,
  .header:has(#logoutBtn) .header-nav > button {
    /* Адаптивное сжатие: min 30px (iPhone SE 320px), max ~44px на широких.
       aspect-ratio: 1/1 гарантирует квадрат → border-radius: 50% даёт
       идеальный круг (без aspect-ratio было 44×40 = эллипс).
       8 × 30 + 28 = 268 влезает на 320 SE; max-width 44 + flex шriнка
       7×4gap дают ~380px на iPhone Pro Max (430). aspect-ratio
       supported в iOS Safari 15.4+ / Chrome 88+ — тот же baseline что
       :has() в этом правиле. */
    flex: 1 1 auto;
    min-width: 30px;
    max-width: 44px;
    /* FIX-M5-NAV-CIRCLE-SHAPE: aspect-ratio: 1/1 без явного height
       не срабатывает — flex parent зажимал height по контенту иконки
       (≈38px) → 44×38 эллипс. min-height: 44px = max-width даёт
       квадрат на iPhone Pro Max; на узких screen ширина сжимается
       flex'ом, height тоже подстраивается через aspect-ratio. */
    min-height: 44px;
    aspect-ratio: 1 / 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
  }
}

.header-nav a,
.header-nav button {
  color: var(--text-secondary);
  font-size: 0.9rem;
  background: none;
  border: none;
  cursor: pointer;
  font-family: inherit;
  transition: var(--transition);
}

.header-nav a:hover,
.header-nav button:hover {
  color: var(--gold);
}

/* ===== Container ===== */
.container {
  max-width: 960px;
  margin: 0 auto;
  padding: 40px 24px;
}

.container-narrow {
  max-width: 520px;
  margin: 0 auto;
  padding: 40px 24px;
}

.container-wide {
  max-width: 1200px;
  margin: 0 auto;
  padding: 40px 24px;
}
/* Страница статьи: первый элемент — маленькая кнопка «Назад», поэтому базовый
   padding-top 40px смотрится пустым провалом. Скоуп по :has(.article-back-btn)
   (класс только на /article) → остальные .container-wide страницы не трогаем. */
.container-wide:has(.article-back-btn) { padding-top: 16px; }

/* ===== Cards ===== */
.card {
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 32px;
  box-shadow: var(--shadow);
}

.card-header {
  margin-bottom: 24px;
}

.card-header h1,
.card-header h2 {
  font-size: 1.5rem;
  font-weight: 600;
  margin-bottom: 8px;
}

.card-header p {
  color: var(--text-secondary);
  font-size: 0.95rem;
}

/* ===== Forms ===== */
.form-group {
  margin-bottom: 20px;
}

.form-group label {
  display: block;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--text-secondary);
  margin-bottom: 6px;
}

.form-group label .required {
  color: var(--gold);
  margin-left: 2px;
}

.form-control {
  width: 100%;
  padding: 12px 16px;
  background: var(--bg-input);
  border: 1px solid rgba(201, 166, 96, 0.3);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  font-size: 0.95rem;
  font-family: inherit;
  transition: var(--transition);
  outline: none;
}

.form-control:focus {
  border-color: rgb(201, 166, 96);
  box-shadow: 0 0 0 3px rgba(201, 166, 96, 0.15);
}

/* Автозаполнение Chrome/Safari: по умолчанию навязывает свой шрифт + жёлтый
   фон, пока поле не в фокусе. Форсируем брендовый VelaSans, белый текст и
   тёмный фон, чтобы автозаполненные поля выглядели как обычные. */
.form-control:-webkit-autofill,
.form-control:-webkit-autofill:hover,
.form-control:-webkit-autofill:focus {
  font-family: 'VelaSans', -apple-system, BlinkMacSystemFont, sans-serif;
  -webkit-text-fill-color: var(--text-primary);
  caret-color: var(--text-primary);
  -webkit-box-shadow: 0 0 0 1000px var(--bg-input) inset;
  transition: background-color 9999s ease-out 0s;
}

.form-control::placeholder {
  color: var(--text-muted);
}

textarea.form-control {
  resize: vertical;
  min-height: 100px;
}

select.form-control {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23999999' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 36px;
}

/* Конференции → Участники: inline-селекты таблицы (Тип/Роль) были без form-control →
   браузерно-белые. Приводим к тёмной теме интерфейса + тёмный список опций у всех
   фильтр-селектов раздела (Тип/Роль/Тема). Аудит 2026-06-17 #4. */
.p-type, .p-cert-role {
  appearance: none;
  background-color: var(--bg-input);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23999999' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 8px center;
  border: 1px solid rgba(201, 166, 96, 0.3);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  font-family: inherit;
}
.p-type option, .p-cert-role option, .p-colf option, .p-rule-f option {
  background: var(--bg-card);
  color: var(--text-primary);
}

.phone-group {
  display: flex;
  gap: 8px;
}

.phone-group select {
  width: 140px;
  flex-shrink: 0;
}

.phone-group input {
  flex: 1;
}

/* Checkboxes */
.checkbox-group {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  cursor: pointer;
}

.checkbox-group input[type="checkbox"] {
  width: 18px;
  height: 18px;
  margin-top: 2px;
  accent-color: var(--gold);
  flex-shrink: 0;
  cursor: pointer;
}

.checkbox-group label {
  font-size: 0.9rem;
  color: var(--text-secondary);
  cursor: pointer;
  margin-bottom: 0;
}

/* ===== Buttons ===== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 24px;
  border: none;
  border-radius: 6px;
  font-size: 0.95rem;
  font-weight: 600;
  font-family: 'VelaSans', sans-serif;
  cursor: pointer;
  transition: var(--transition);
  outline: none;
}

.btn-primary {
  background: linear-gradient(to right, rgb(227,200,140), rgb(201,166,96), rgb(165,124,61));
  color: #000000;
}

.btn-primary:hover {
  background: linear-gradient(to right, rgb(240,218,160), rgb(227,200,140), rgb(201,166,96));
  transform: translateY(-1px);
  box-shadow: 0 4px 16px rgba(201, 166, 96, 0.3);
}

.btn-primary:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

.btn-secondary {
  background: transparent;
  border: 1px solid rgb(201, 166, 96);
  color: rgb(201, 166, 96);
}

.btn-secondary:hover {
  background: rgba(201, 166, 96, 0.1);
}

.btn-success {
  background: var(--success);
  color: white;
  padding: 8px 16px;
  font-size: 0.85rem;
}

.btn-success:hover {
  background: #43a047;
}

.btn-danger {
  background: var(--danger);
  color: white;
  padding: 8px 16px;
  font-size: 0.85rem;
}

.btn-danger:hover {
  background: #c0392b;
}

.btn-gold {
  background: rgb(201,166,96);
  color: #1a1a1a;
}
.btn-gold:hover:not(:disabled) {
  background: rgb(227,200,140);
}
.btn-gold:disabled {
  background: #555;
  color: #999;
  cursor: not-allowed;
  opacity: 1;
}

.btn-outline {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-secondary);
  padding: 8px 16px;
  font-size: 0.85rem;
}

.btn-outline:hover {
  border-color: var(--gold);
  color: var(--gold);
}

.btn-full {
  width: 100%;
}

/* ===== Alerts ===== */
.alert {
  padding: 16px 20px;
  border-radius: var(--radius-sm);
  margin-bottom: 20px;
  font-size: 0.9rem;
}

.alert-success {
  background: rgba(76, 175, 80, 0.12);
  border: 1px solid rgba(76, 175, 80, 0.3);
  color: #81c784;
}

.alert-error {
  background: rgba(231, 76, 60, 0.12);
  border: 1px solid rgba(231, 76, 60, 0.3);
  color: #ef9a9a;
}

.alert-info {
  background: rgba(201, 166, 96, 0.1);
  border: 1px solid rgba(201, 166, 96, 0.25);
  color: var(--gold-light);
}

/* ===== Success Screen ===== */
.success-screen {
  text-align: center;
  padding: 60px 20px;
}

.success-icon {
  width: 80px;
  height: 80px;
  border-radius: 50%;
  background: rgba(76, 175, 80, 0.15);
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 24px;
  font-size: 2.5rem;
}

.success-screen h2 {
  font-size: 1.5rem;
  margin-bottom: 12px;
}

.success-screen p {
  color: var(--text-secondary);
  max-width: 400px;
  margin: 0 auto;
}

/* ===== Badge ===== */
.badge {
  display: inline-block;
  padding: 4px 10px;
  border-radius: 20px;
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.badge-pending {
  background: rgba(243, 156, 18, 0.15);
  color: var(--warning);
}

.badge-approved {
  background: rgba(76, 175, 80, 0.15);
  color: var(--success);
}

.badge-rejected {
  background: rgba(231, 76, 60, 0.15);
  color: var(--danger);
}

/* ===== Table ===== */
.table-wrapper {
  overflow-x: auto;
  margin-top: 20px;
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
}

table th {
  text-align: left;
  padding: 12px 16px;
  background: #1a1a1c;
  color: var(--text-secondary);
  font-weight: 600;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  white-space: nowrap;
}

table td {
  padding: 12px 16px;
  border-top: 1px solid var(--border);
  vertical-align: top;
}

table tr:hover td {
  background: rgba(201, 166, 96, 0.05);
}

.actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

/* ===== Tabs ===== */
.tabs {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 24px;
}

.tab {
  padding: 12px 20px;
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 0.9rem;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  border-bottom: 2px solid transparent;
  transition: var(--transition);
}

.tab:hover {
  color: var(--text-secondary);
}

.tab.active {
  color: rgb(201, 166, 96);
  border-bottom-color: rgb(201, 166, 96);
}

.tab-content {
  display: none;
}

.tab-content.active {
  display: block;
}

/* ===== Chat ===== */
.chat-container {
  display: flex;
  flex-direction: column;
  height: 500px;
}

.chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  background: var(--bg-input);
  border-radius: var(--radius-sm);
  margin-bottom: 12px;
}

.chat-msg {
  max-width: 80%;
}

.chat-msg.own {
  align-self: flex-end;
}

.chat-msg-header {
  font-size: 0.75rem;
  color: var(--text-muted);
  margin-bottom: 4px;
}

.chat-msg-header strong {
  color: var(--gold);
  font-weight: 600;
}

.chat-msg-body {
  background: var(--bg-secondary);
  padding: 10px 14px;
  border-radius: 12px;
  font-size: 0.9rem;
  line-height: 1.5;
  word-wrap: break-word;
}

.chat-msg.own .chat-msg-body {
  background: rgba(201, 166, 96, 0.15);
}

.chat-input {
  display: flex;
  gap: 8px;
}

.chat-input input {
  flex: 1;
}

.chat-input .btn {
  flex-shrink: 0;
}

.chat-empty {
  text-align: center;
  color: var(--text-muted);
  padding: 40px;
  font-size: 0.9rem;
}

/* ===== Notifications ===== */
.notification-item {
  padding: 16px;
  background: var(--bg-input);
  border-radius: var(--radius-sm);
  margin-bottom: 12px;
  border-left: 3px solid var(--gold);
}

.notification-item h4 {
  font-size: 0.95rem;
  margin-bottom: 6px;
}

.notification-item p {
  color: var(--text-secondary);
  font-size: 0.875rem;
}

.notification-item .date {
  font-size: 0.75rem;
  color: var(--text-muted);
  margin-top: 8px;
}

/* ===== Empty State ===== */
.empty-state {
  text-align: center;
  padding: 60px 20px;
  color: var(--text-muted);
}

.empty-state-icon {
  font-size: 3rem;
  margin-bottom: 16px;
  opacity: 0.5;
}

.empty-state p {
  font-size: 0.95rem;
}

/* ===== Dashboard Welcome ===== */
.welcome-banner {
  background: linear-gradient(135deg, var(--bg-card), var(--bg-secondary));
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 32px;
  margin-bottom: 32px;
}

.welcome-banner h1 {
  font-size: 1.5rem;
  margin-bottom: 8px;
}

.welcome-banner h1 span {
  color: var(--gold);
}

.welcome-banner p {
  color: var(--text-secondary);
}

/* ===== Modal ===== */
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.7);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: 20px;
  opacity: 0;
  visibility: hidden;
  transition: var(--transition);
}

.modal-overlay.active {
  opacity: 1;
  visibility: visible;
}

.modal {
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 32px;
  max-width: 480px;
  width: 100%;
  transform: translateY(20px);
  transition: var(--transition);
}

.modal-overlay.active .modal {
  transform: translateY(0);
}

.modal h3 {
  font-size: 1.2rem;
  margin-bottom: 16px;
}

.modal .btn-group {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  margin-top: 20px;
}

.modal--scroll {
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  padding: 24px;
}

.modal--scroll .modal-body {
  overflow-y: auto;
  flex: 1;
  min-height: 0;
  padding-right: 8px;
}

.modal--scroll .modal-footer {
  flex-shrink: 0;
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  padding-top: 16px;
  border-top: 1px solid rgba(255,255,255,0.1);
  margin-top: 16px;
}

/* ===== Модалки на нативке: внутренний скролл + учёт клавиатуры (аудит модалок) =====
   Базовые .modal-overlay/.modal не имели ни max-height/скролла, ни реакции на
   клавиатуру, ни замка фона: кнопка «Отправить» уходила под клавиатуру, а тач
   скроллил фон. Правка централизованная — лечит ВСЕ наследующие класс модалки
   (запрос на общение, дизлайк/предложить-тему, знакомства, walk-in, апелляция…).
   Скролл-замок фона — modal-scroll-lock.js. Веб не трогаем (native-гейт). */
/* :not(.modal--scroll) — у .modal--scroll свой max-height:90vh + .modal-body
   overflow-y:auto; не задваиваем скролл-контейнер. share-article — display:flex
   с внутренним скроллом списка, но flex удерживает детей в max-height, поэтому
   overflow-y родителя не активируется (двойного скролла нет). */
html.cap-ios .modal:not(.modal--scroll),
html.cap-android .modal:not(.modal--scroll) {
  max-height: calc(100dvh - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px) - 40px);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}
/* iOS: клавиатура не сжимает вьюпорт (resize:none) — поднимаем окно к верху и
   ужимаем по высоте над клавиатурой, чтобы кнопка была видна и докручивалась. */
html.cap-ios.kb-open .modal-overlay {
  align-items: flex-start;
  padding-top: calc(env(safe-area-inset-top, 0px) + 12px);
}
html.cap-ios.kb-open .modal {
  max-height: calc(100dvh - env(safe-area-inset-top, 0px) - var(--keyboard-height, 0px) - 24px);
}
/* Мессенджер-модалки — bottom-sheet: держим у низа НАД клавиатурой.
   Гейт — html.msg-lock (ставит/снимает жизненный цикл messages-page):
   прежний :has(.msg-container) с живым DOM разделов матчил скрытую
   обёртку и утекал на все страницы (аудит клавиатуры 2026-07-22). */
html.cap-ios.kb-open.msg-lock .modal-overlay {
  align-items: flex-end;
  padding-top: 0;
  padding-bottom: var(--keyboard-height, 0px);
}
html.cap-ios.kb-open.msg-lock .modal {
  max-height: calc(90vh - var(--keyboard-height, 0px));
}

/* ===== Share-article modal (контакт-пикер) ===== */
/* Кап высоты КЛАССОМ, не inline: inline max-height бил все каскадные
   клавиатурные правила (html.cap-ios.kb-open .modal и msg-lock-шиты) —
   окно не ужималось над клавиатурой, поле сообщения уходило под неё
   (аудит клавиатуры 2026-07-22). То же — .cpp-modal (панель ПМ). */
.share-modal { max-height: calc(100vh - 40px); }
.cpp-modal { max-height: 85vh; }
/* Аватар менеджера конференции: размер задаёт обёртка, картинка её заполняет.
   Идёт через cgAvatar (нативная абсолютизация пути + байт-стор), поэтому свой
   inline-стиль на <img> не ставим — только этот класс. */
.cpp-ava { width: 100%; height: 100%; object-fit: cover; display: block; border-radius: 50%; }
.share-contact-list {
  flex: 0 1 auto;
  min-height: 0;
  max-height: 50vh;
  overflow-y: auto;
  overscroll-behavior: contain; /* скролл списка не «протекает» на фон (iOS) */
  border: 1px solid var(--border);
  border-radius: 8px;
}
.share-contact-row {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 12px;
  background: none;
  border: none;
  border-bottom: 1px solid rgba(255,255,255,0.04);
  color: var(--text-primary);
  font-family: inherit;
  font-size: 0.9rem;
  text-align: left;
  cursor: pointer;
}
.share-contact-row:hover { background: rgba(255,255,255,0.03); }
.share-contact-row.selected { background: rgba(201,166,96,0.1); }
.share-contact-avatar {
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  border-radius: 8px;
  overflow: hidden;
  background: #0f0f12;
  border: 1px solid rgba(201,166,96,0.2);
}
.share-contact-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.share-contact-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.share-contact-check {
  flex-shrink: 0;
  display: inline-flex;
  color: rgb(201,166,96);
  opacity: 0;
}
.share-contact-row.selected .share-contact-check { opacity: 1; }
.share-empty {
  padding: 24px 12px;
  text-align: center;
  color: var(--text-muted);
  font-size: 0.85rem;
}

/* ===== Admin Stats ===== */
.stats-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 16px;
  margin-bottom: 24px;
}

.stat-card {
  background: var(--bg-input);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 20px;
  text-align: center;
}

.stat-card .stat-number {
  font-size: 2rem;
  font-weight: 700;
  color: var(--gold);
}

.stat-card .stat-label {
  font-size: 0.8rem;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-top: 4px;
}

/* ===== Admin Notification Form ===== */
.admin-section {
  margin-top: 32px;
}

.admin-section h3 {
  font-size: 1.1rem;
  margin-bottom: 16px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
}

/* ===== Loader ===== */
.loader {
  display: inline-block;
  width: 20px;
  height: 20px;
  border: 2px solid var(--border);
  border-top-color: var(--gold);
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

/* ===== Skeleton (SPA Phase 2) =====
   Generic-классы: per-page разметка под собственную сетку для нулевого
   layout shift при подмене на реальные карточки. */
.skel {
  background:
    linear-gradient(90deg,
      rgba(255,255,255,0.04) 0%,
      rgba(201,166,96,0.10) 50%,
      rgba(255,255,255,0.04) 100%);
  background-size: 200% 100%;
  animation: skel-shimmer 1.4s ease-in-out infinite;
  border-radius: 6px;
}
/* skel-text и skel-avatar были определены, но не использовались — удалены
   при audit cleanup. Avatar-форму страницы делают через inline border-radius:50%
   на .skel (см. participants/profile/notifications). */
.skel-line { height: 14px; margin-bottom: 8px; }
.skel-line.skel-line--short { width: 40%; }
.skel-line.skel-line--mid { width: 70%; }
.skel-card {
  height: 84px;
  border: 1px solid var(--border);
  border-radius: 10px;
  margin-bottom: 10px;
}
.skel-chart { height: 220px; }

@keyframes skel-shimmer {
  0%   { background-position: 100% 0; }
  100% { background-position: -100% 0; }
}

@media (prefers-reduced-motion: reduce) {
  .skel { animation: none; }
}

/* ===== Responsive ===== */
@media (max-width: 768px) {
  /* M5-W1 follow-up: legacy `.header { padding: 0 16px }` удалён —
     перезаписывал M5-W1 правило выше (env(safe-area-inset-top) +
     8px), из-за чего nav-кнопки на iPhone PWA не отступали от
     statusbar (часы/WiFi/батарея перекрывали первые кнопки).
     Padding теперь единая SoT в строке ~157. */

  .container,
  .container-narrow,
  .container-wide {
    padding: 24px 16px;
  }

  /* M5-W2-bis (9): bottom-sheet модалки на mobile, ТОЛЬКО на messenger-
     странице. Гейт — html.msg-lock (жизненный цикл messages-page):
     прежний :has(.msg-container) с живым DOM разделов матчил скрытую
     обёртку и делал шитами модалки ВСЕХ страниц (аудит клавиатуры
     2026-07-22). padding-bottom поднимает шит над клавиатурой в вебе —
     --keyboard-height на странице мессенджера пишет vv-хук.
     CSS-only — HTML/JS обработчики не трогаются. */
  html.msg-lock .modal-overlay {
    align-items: flex-end;
    padding: 0;
    padding-bottom: var(--keyboard-height, 0px);
  }
  html.msg-lock .modal {
    max-width: 100%;
    width: 100%;
    border-radius: 20px 20px 0 0;
    max-height: 90vh;
    overflow-y: auto;
    margin: 0;
    transform: translateY(100%);
    transition: transform 0.25s ease-out;
  }
  html.msg-lock .modal-overlay.active .modal {
    transform: translateY(0);
  }

  .card {
    padding: 24px 20px;
  }

  .phone-group {
    flex-direction: column;
  }

  .phone-group select {
    width: 100%;
  }

  .stats-row {
    grid-template-columns: repeat(2, 1fr);
  }

  table {
    font-size: 0.8rem;
  }

  table th,
  table td {
    padding: 8px 10px;
  }

  .actions {
    flex-direction: column;
  }

  .chat-container {
    height: 400px;
  }

  .chat-msg {
    max-width: 90%;
  }

  .tabs {
    overflow-x: auto;
  }

  .tab {
    padding: 10px 14px;
    font-size: 0.85rem;
    white-space: nowrap;
  }
}

@media (max-width: 480px) {
  .logo {
    font-size: 1.2rem;
  }

  .header-nav a,
  .header-nav button {
    font-size: 0.8rem;
  }

  .stats-row {
    grid-template-columns: 1fr 1fr;
  }
}

/* ===== Scrollbar ===== */
::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

::-webkit-scrollbar-track {
  background: var(--bg-primary);
}

::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 3px;
}

::-webkit-scrollbar-thumb:hover {
  background: var(--text-muted);
}

/* ===== Page transition =====
   Фаза 7 плавности: единая моторика всех разделов (включая мессенджер).
   Короткий фейд 0.18s — быстрая анимация читается как отзывчивость, долгая
   (был 0.4s) — как ожидание. prefers-reduced-motion уважаем полностью. */
.page-enter {
  animation: fadeIn 0.18s ease-out;
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .page-enter {
    animation: none;
  }
}

/* ── Nav icon buttons (Phase 4-F) ── */
.header-nav .nav-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: var(--radius);
  background: rgba(201,166,96,0.08);
  border: 1px solid rgba(201,166,96,0.2);
  transition: var(--transition);
}
/* hover только для устройств с реальным указателем (мышь). На тач (вкл. iOS
   standalone PWA) :hover «залипает» на последнем тапнутом элементе и даёт
   паразитную тусклую подсветку рядом с активным разделом (.nav-icon--active). */
@media (hover: hover) {
  .header-nav .nav-icon:hover {
    background: rgba(201,166,96,0.18);
  }
}
.header-nav .nav-icon--active {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: var(--radius);
  background: rgba(201,166,96,0.25);
  border: 1px solid rgba(201,166,96,0.6);
  transition: var(--transition);
  position: relative;
}
.header-nav .nav-icon--danger {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: var(--radius);
  background: rgba(201,166,96,0.08);
  border: 1px solid rgba(201,166,96,0.2);
  transition: var(--transition);
}
@media (hover: hover) {
  .header-nav .nav-icon--danger:hover {
    background: rgba(244,67,54,0.15);
    border-color: rgba(244,67,54,0.4);
  }
}

/* ── Custom tooltip (мгновенный, стилизованный в палитре) ──
   Sprint /participants redesign: обобщили механизм. Любой элемент с
   классом .has-tooltip + атрибутом data-tooltip получает custom tooltip
   с 80ms opacity transition — визуально мгновенное появление. Native
   browser tooltip (~700ms delay) не появляется т.к. на nav-иконки
   injector lib/nav-tooltip-injector.js переименовывает title= →
   data-tooltip=, а карточки рендерятся клиентом сразу с data-tooltip
   без title=. Позиция выбирается через модификатор:
     .tooltip-pos-below — под элементом (для иконок шапки)
     .tooltip-pos-left  — слева от элемента (для actions в правом
                          верхнем углу карточки участника) */
.has-tooltip {
  position: relative;
}
.has-tooltip[data-tooltip]::after,
.has-tooltip[data-tooltip]::before {
  opacity: 0;
  pointer-events: none;
  transition: opacity 80ms ease-out;
  z-index: 9999;
}
.has-tooltip[data-tooltip]::after {
  content: attr(data-tooltip);
  position: absolute;
  padding: 5px 10px;
  background: var(--bg-card);
  color: var(--gold);
  border: 1px solid rgba(201,166,96,0.3);
  border-radius: 6px;
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.2px;
  white-space: nowrap;
  box-shadow: 0 4px 12px rgba(0,0,0,0.4);
}
.has-tooltip[data-tooltip]::before {
  content: '';
  position: absolute;
  width: 0;
  height: 0;
}
.has-tooltip:hover[data-tooltip]::after,
.has-tooltip:hover[data-tooltip]::before {
  opacity: 1;
}

/* Position: below (треугольник остриём вверх к элементу). */
.tooltip-pos-below[data-tooltip]::after {
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  margin-top: 10px;
}
.tooltip-pos-below[data-tooltip]::before {
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  margin-top: 4px;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-bottom: 5px solid rgba(201,166,96,0.3);
}

/* Position: left (треугольник остриём вправо к элементу). */
.tooltip-pos-left[data-tooltip]::after {
  right: 100%;
  top: 50%;
  transform: translateY(-50%);
  margin-right: 10px;
}
.tooltip-pos-left[data-tooltip]::before {
  right: 100%;
  top: 50%;
  transform: translateY(-50%);
  margin-right: 4px;
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
  border-left: 5px solid rgba(201,166,96,0.3);
}

/* Edge: последние 2 иконки шапки (Настройки/Выйти) на правом краю —
   tooltip может переполнить viewport справа. Якорим к правому краю. */
.header-nav > a.tooltip-pos-below:nth-last-child(-n+2)[data-tooltip]::after {
  left: auto;
  right: 0;
  transform: none;
}
.header-nav > a.tooltip-pos-below:nth-last-child(-n+2)[data-tooltip]::before {
  left: auto;
  right: 14px;
  transform: none;
}

/* Mobile: hover не работает на touch — tooltip не нужен и может мешать. */
@media (max-width: 768px) {
  .has-tooltip[data-tooltip]::after,
  .has-tooltip[data-tooltip]::before {
    display: none;
  }
}

.dash-request-card { transition: border-color 0.2s; }
.dash-request-card:hover { border-color: rgba(201,166,96,0.4); }

/* ========== UTILITY CLASSES (Phase A — inline style migration) ========== */

/* Display */
.hidden { display: none; }

/* Targeted overrides: page-level <style> blocks define overlays with display:flex
   and come after styles.css in the cascade, so we need specificity + !important
   to ensure .hidden wins over .avatar-crop-overlay etc. */
.avatar-crop-overlay.hidden,
.user-stats-overlay.hidden,
.admin-cover-crop-overlay.hidden,
.admin-cover-crop-modal.hidden,
.cover-crop-overlay.hidden,
.moderation-modal.hidden,
.moderation-overlay.hidden,
.stats-modal.hidden,
.stats-modal-overlay.hidden,
.block-modal-overlay.hidden,
.modal-overlay.hidden,
.notif-badge.hidden { display: none !important; }

/* Phase 5-D: класс для скрытия nav-иконок на admin-страницах. Нужен !important
   потому что .header-nav a[href] в нескольких admin HTML имеет display: flex !important.
   Дополнительный селектор .header-nav a[href].nav-hidden имеет специфичность (0,0,3,1) —
   побеждает .header-nav a[href] (0,0,2,1) когда оба правила c !important. */
.nav-hidden, .header-nav a[href].nav-hidden { display: none !important; }

/* Phase 5-D fix Bug 2 (FOUC): прячем nav-icons с data-section до первого check'а.
   admin-auth.js добавляет body.nav-checked после hideInaccessibleNavItems →
   разрешённые иконки появляются, .nav-hidden остаётся скрытым через display:none. */
body:not(.nav-checked) .header-nav a[href][data-section] { visibility: hidden; }

.notif-badge {
  position: absolute;
  top: -4px;
  right: -4px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: #e74c3c;
  color: #fff;
  border-radius: 50%;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  font-size: 0.7rem;
  font-weight: 700;
  line-height: 1;
  pointer-events: none;
}

/* Spacing */
.m-0 { margin: 0; }
.mb-4 { margin-bottom: 4px; }
.mb-8 { margin-bottom: 8px; }
.mb-12 { margin-bottom: 12px; }
.mb-16 { margin-bottom: 16px; }
.mb-20 { margin-bottom: 20px; }
.mb-24 { margin-bottom: 24px; }
.mt-8 { margin-top: 8px; }
.mt-16 { margin-top: 16px; }
.mr-12 { margin-right: 12px; }

/* Typography */
.text-sm { font-size: 0.85rem; }
.text-xs { font-size: 0.78rem; }
.text-muted { color: var(--text-muted); }
.text-secondary { color: var(--text-secondary); }
.text-sm-muted { font-size: 0.85rem; color: var(--text-muted); }
.text-sm-secondary { font-size: 0.85rem; color: var(--text-secondary); }
.text-xs-muted { font-size: 0.78rem; color: var(--text-muted); }
.text-bold { font-weight: 600; }
.text-center { text-align: center; }

/* Flex */
.flex { display: flex; }
.flex-col { flex-direction: column; }
.flex-1 { flex: 1; }
.flex-wrap { flex-wrap: wrap; }
.flex-shrink-0 { flex-shrink: 0; }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }
.gap-6 { gap: 6px; }
.gap-8 { gap: 8px; }
.gap-10 { gap: 10px; }
.gap-12 { gap: 12px; }
.gap-16 { gap: 16px; }

/* Width */
.w-full { width: 100%; }

/* Logo */
.header .logo img { height: 72px; }

/* Admin label */
.admin-label {
  margin-left: 12px;
  font-family: 'VelaSans', sans-serif;
  font-size: 0.85rem;
  color: var(--text-secondary);
}

/* Nav badge (notification/request) — унификация 13 одинаковых inline стилей */
.nav-badge {
  display: none;
  position: absolute;
  top: -4px;
  right: -4px;
  background: var(--danger);
  color: #fff;
  font-size: 0.6rem;
  font-weight: 700;
  min-width: 16px;
  height: 16px;
  border-radius: 8px;
  padding: 0 4px;
  align-items: center;
  justify-content: center;
  z-index: 1;
}

/* Section header (back + title) */
.section-header {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 16px;
}

/* Button: remove/delete inline — стандартизация кнопки удаления */
.btn-inline-remove {
  display: none;
  background: none;
  border: 1px solid rgba(220,53,69,0.3);
  border-radius: var(--radius);
  color: rgba(220,53,69,0.7);
  font-size: 0.82rem;
  padding: 7px 14px;
  cursor: pointer;
  font-family: inherit;
}

/* ========== UTILITY CLASSES (Phase B) ========== */

/* Position */
.relative { position: relative; }
.relative-inline { position: relative; display: inline-block; }

/* Typography (additional combos from Phase B analysis) */
.text-base { font-size: 1rem; }
.text-xs-sm { font-size: 0.75rem; }
.text-sm-strong-muted { font-size: 0.82rem; color: var(--text-muted); }
.text-xs-sm-muted { font-size: 0.75rem; color: var(--text-muted); }
.text-sm-bold { font-size: 0.85rem; font-weight: 600; }
.text-sm-gold { font-size: 0.8rem; color: var(--gold); }
.font-bold-mb4 { font-weight: 600; margin-bottom: 4px; }
.form-hint { font-size: 0.78rem; color: var(--text-muted); font-weight: 400; }
.text-xs-muted-mb6 { font-size: 0.78rem; color: var(--text-muted); margin-bottom: 6px; }

/* Layout combos */
.flex-between-center { display: flex; justify-content: space-between; align-items: center; }
.flex-between-mb16 { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
.section-header-mb24 { display: flex; align-items: center; gap: 12px; margin-bottom: 24px; }
.flex-modal-buttons { display: flex; gap: 10px; width: 100%; }

/* Modal action buttons */
.btn-modal-primary {
  flex: 1;
  padding: 10px;
  background: linear-gradient(135deg, #c9a84c, #a07830);
  border: none;
  border-radius: var(--radius);
  color: #000;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
}
.btn-modal-secondary {
  flex: 1;
  padding: 10px;
  background: none;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text-muted);
  font-family: inherit;
  cursor: pointer;
}

/* Square close-X button (used in modal headers) */
.btn-close-square {
  background: none;
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text-muted);
  padding: 4px 12px;
  cursor: pointer;
  font-family: inherit;
}

/* ========== UTILITY CLASSES (Phase C) ========== */

/* Spacing */
.p-8 { padding: 8px; }
.mt-40 { margin-top: 40px; }

/* Color utilities */
.text-danger { color: var(--danger); }
.gold-bold { color: rgb(201,166,96); font-weight: 600; }
.text-white-light { color: rgba(255,255,255,0.4); }

/* Icon align (inline svg before text) */
.icon-aligned { vertical-align: middle; margin-right: 4px; }

/* Range slider with gold accent */
.range-gold { width: 100%; accent-color: rgb(201,166,96); }

/* Modal section title */
.modal-section-title { font-weight: 600; font-size: 0.95rem; align-self: flex-start; }

/* Flex variants */
.flex-gap-8 { display: flex; gap: 8px; }
.flex-gap-8-wrap { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

/* Empty state dashed (placeholder block) */
.empty-state-dashed {
  text-align: center;
  padding: 32px;
  color: var(--text-muted);
  font-size: 0.85rem;
  border: 1px dashed var(--border);
  border-radius: var(--radius);
}

/* Empty state message (loading / no data) */
.empty-state-msg {
  color: var(--text-muted);
  font-size: 0.85rem;
  padding: 20px;
}

/* Menu card row (settings/admin menu cards) */
.menu-card-row {
  margin-bottom: 12px;
  cursor: pointer;
  padding: 20px 24px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

/* Dropdown input (selects in admin tables/filters) */
.dropdown-input {
  padding: 4px 10px;
  background: var(--bg-input);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text-primary);
  font-family: inherit;
  font-size: 0.82rem;
}

/* Btn back pill (for "Назад" buttons) */
.btn-back-pill {
  padding: 7px 16px;
  background: none;
  border: 1px solid var(--border);
  border-radius: 20px;
  color: var(--text-muted);
  font-size: 0.85rem;
  cursor: pointer;
  font-family: inherit;
}

/* ========== TOPIC-CARD (BUG-2) ========== */
/* Компактная версия .topic-card для dashboard-подписок.
   Эталонный крупный `.topic-card` живёт в views/select-topics.html page-style блоке;
   здесь только --sm модификатор используется dashboard'ом и может быть расширен для
   других страниц позже. Клик по карточке toggleит `.selected`, SVG-галочка появляется
   через opacity. Данные собираются через `data-topic` атрибут. */
.topic-card--sm {
  background: var(--bg-input);
  border: 2px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 10px 14px;
  cursor: pointer;
  transition: var(--transition);
  display: flex;
  align-items: center;
  gap: 10px;
  user-select: none;
  font-size: 0.85rem;
}
.topic-card--sm:hover {
  border-color: rgba(201, 166, 96, 0.55);
  background: rgba(201, 166, 96, 0.05);
}
.topic-card--sm.selected {
  border-color: var(--gold);
  background: rgba(201, 166, 96, 0.1);
}
.topic-card--sm .topic-checkbox {
  width: 18px;
  height: 18px;
  border: 2px solid var(--border);
  border-radius: 4px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: var(--transition);
}
.topic-card--sm.selected .topic-checkbox {
  background: var(--gold);
  border-color: var(--gold);
}
.topic-card--sm .topic-checkbox svg {
  width: 11px;
  height: 11px;
  fill: none;
  stroke: var(--bg-primary);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0;
  transition: var(--transition);
}
.topic-card--sm.selected .topic-checkbox svg {
  opacity: 1;
}

/* ========== UTILITY CLASSES (Micro Phase D) ========== */

/* Table column width (admin tables) */
.col-w-90 { width: 90px; }

/* Compact export button padding */
.btn-sm { padding: 6px 16px; font-size: 0.85rem; }

/* Hidden alert with bottom margin (initially hidden, revealed via classList) */
.alert-hidden { display: none; margin-bottom: 16px; }

/* ============ PROFILE PAGE (Фаза 2) ============ */
.profile-hero {
  position: relative;
  display: flex;
  gap: 24px;
  align-items: flex-start;
  padding: 24px;
  padding-right: 76px;       /* place для absolute actions stack на desktop */
  background: #1a1a1c;
  border: 1px solid var(--border);
  border-radius: 12px;
  margin-bottom: 20px;
}
.profile-avatar {
  flex-shrink: 0;
  width: 120px;
  height: 120px;
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid rgba(201,166,96,0.35);
  background: #0f0f12;
  display: flex;
  align-items: center;
  justify-content: center;
}
.profile-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.profile-hero-info {
  flex: 1 1 auto;
  min-width: 0;
}
.profile-name {
  /* Sprint 2 follow-up hotfix: override global h1/h2/h3 Bounded font
     (styles.css:89). .participant-name на /participants — div, наследует
     VelaSans. .profile-name — h1, getComputedStyle показывал Bounded →
     визуально «ужасно жирное». Override на VelaSans для consistency. */
  font-family: 'VelaSans', sans-serif;
  font-size: 1.8rem;
  font-weight: 600;
  margin: 0 0 8px 0;
  color: var(--text-primary);
  line-height: 1.15;
}

/* Sprint 2 follow-up: «N» counter рядом с h2 заголовком секций
   на /profile/<id> (опубликованные статьи, конференции если применимо). */
.profile-section-count {
  color: var(--text-muted);
  font-weight: 500;
  font-size: 0.85em;
  margin-left: 6px;
}

/* Sprint 2 follow-up: read-only metric badges row (views/likes/saves/
   comments) на article cards в профиле чужого пользователя. Все 4
   badges всегда видны (consistency между cards). --active modifier
   даёт золотой accent при count > 0, 0-count остаются muted. */
.news-card-metrics-row {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.news-card-metric {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 8px;
  border-radius: 6px;
  color: var(--text-muted);
  font-size: 0.78rem;
  background: rgba(255,255,255,0.02);
  border: 1px solid rgba(255,255,255,0.04);
  opacity: 0.65;
  transition: opacity 0.15s ease, color 0.15s ease, background 0.15s ease;
  cursor: default;
}
.news-card-metric--active {
  color: rgb(201,166,96);
  opacity: 1;
  background: rgba(201,166,96,0.08);
  border-color: rgba(201,166,96,0.18);
}
.news-card-metric:hover { opacity: 1; }
.news-card-metric-num {
  font-variant-numeric: tabular-nums;
  font-weight: 500;
}

/* Sprint 2 follow-up P2: back-button на /profile/<id> → /participants. */
.profile-back-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  margin-bottom: 16px;
  color: var(--text-muted);
  text-decoration: none;
  font-size: 0.85rem;
  border-radius: 8px;
  transition: color 0.15s ease, background 0.15s ease;
}
.profile-back-btn:hover {
  color: rgb(201,166,96);
  background: rgba(201,166,96,0.08);
}
/* Sprint profile-meta-split: position / org — каждое в своём блоке,
   на одной строке всегда. Separator `·` удалён вместе с .profile-meta
   контейнером + .profile-meta-sep. .profile-city остаётся как был. */
.profile-position,
.profile-org {
  color: var(--text-muted);
  font-size: 0.95rem;
  margin-bottom: 4px;
}
.profile-city {
  color: var(--text-muted);
  font-size: 0.85rem;
  margin-bottom: 16px;
}
/* Sprint profile-mobile: actions stack — absolute top-right на desktop,
   static + margin-left:auto в строке с avatar на mobile (см. @media). */
.profile-actions-stack {
  position: absolute;
  top: 16px;
  right: 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  z-index: 1;
}
.profile-section-title {
  font-size: 1.1rem;
  font-weight: 600;
  margin: 0 0 16px 0;
  color: var(--text-primary);
}

/* Conference chips (regalia) */
.conference-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.conference-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  background: #0f0f12;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 0.85rem;
  color: var(--text-primary);
}
.conference-chip-role {
  font-weight: 600;
  color: rgb(201,166,96);
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
.conference-chip-name { color: var(--text-primary); }
.conference-chip-date { color: var(--text-muted); font-size: 0.78rem; }

/* News-card — горизонтальная карточка (обложка слева, текст справа).
   Применяется и на dashboard (news feed, inline-скопировано), и в профиле
   участника (список опубликованных статей). Зеркало стилей dashboard.html
   блока <style> — вынесено в global для переиспользования в profile.html. */
.news-card {
  display: flex;
  align-items: stretch;
  background: #1a1a1c;
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  margin-bottom: 10px;
  cursor: pointer;
  text-decoration: none;
  color: var(--text-primary);
  transition: border-color 0.2s, background 0.2s;
  min-height: 80px;
}
.news-card:hover {
  border-color: rgba(201,166,96,0.5);
  background: #202022;
}
.news-card-thumb {
  flex: 0 0 150px;
  width: 150px;
  min-height: 80px;
  background: #111;
  overflow: hidden;
  flex-shrink: 0;
}
.news-card-thumb img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}
.news-card-thumb-empty {
  width: 150px;
  min-height: 88px;
  height: 100%;
  background: #111;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.6rem;
  color: rgba(201,166,96,0.15);
}
.news-card-body {
  flex: 1;
  padding: 8px 10px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  min-width: 0;
  overflow: hidden;
}
/* Sprint profile-mobile: убрали global webkit-line-clamp:3 — title статьи
   на /profile показывается full wrap. dashboard.html + admin-news.html
   имеют inline <style> с clamp override — не задеты этим изменением. */
.news-card-excerpt {
  font-size: 0.85rem;
  color: var(--text-primary);
  line-height: 1.5;
  overflow-wrap: break-word;
  word-wrap: break-word;
  margin-bottom: 6px;
}
.news-card-meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  color: var(--text-muted);
  font-size: 0.72rem;
  white-space: nowrap;
}
.news-card-views {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.news-card-date { font-size: 0.72rem; color: var(--text-muted); white-space: nowrap; }

/* Sprint profile-mobile: mobile layout для /profile. Avatar + actions-stack
   в строку (avatar слева 120×120, actions прижаты к правому краю), info-
   блок переносится ПОД avatar через flex: 1 1 100% + order. Title статьи —
   full wrap (без clamp), date + metrics — column row. */
@media (max-width: 768px) {
  .profile-hero {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 16px;
    padding-right: 16px;       /* убираем desktop space — actions переехали в row */
  }
  .profile-actions-stack {
    position: static;
    top: auto;
    right: auto;
    margin-left: auto;          /* прижимаем к правому краю в row с avatar */
  }
  .profile-hero-info {
    flex: 1 1 100%;
    order: 2;
    margin-top: 8px;
  }
  .news-card-meta {
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
  }
  .news-card-metrics-row {
    flex-wrap: nowrap;
    gap: 8px;
  }
  .news-card-metric {
    padding: 3px 6px;
    font-size: 0.72rem;
  }
}

/* ============ ADMIN actionMenu — conferences regalia block (Фаза 2-C) ============ */
.am-conf-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  min-height: 36px;
  padding: 6px;
  background: #0a0a0c;
  border: 1px dashed var(--border);
  border-radius: 8px;
  align-items: center;
}
.am-conf-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 6px 4px 10px;
  background: #1a1a1c;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 0.78rem;
  max-width: 100%;
}
.am-conf-role {
  font-weight: 600;
  color: rgb(201,166,96);
  text-transform: uppercase;
  font-size: 0.68rem;
  letter-spacing: 0.3px;
  white-space: nowrap;
}
.am-conf-name {
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 180px;
}
.am-conf-date {
  color: var(--text-muted);
  font-size: 0.72rem;
  white-space: nowrap;
}
.am-conf-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  padding: 0;
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  border-radius: 50%;
  transition: background 0.15s ease, color 0.15s ease;
}
.am-conf-remove:hover {
  background: rgba(220,53,69,0.15);
  color: #dc3545;
}

/* ============ PARTICIPANTS PAGE (Фаза 3) ============ */
.participants-tabs {
  display: flex;
  gap: 8px;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--border);
}
.participants-tab {
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 0.95rem;
  padding: 10px 18px;
  cursor: pointer;
  font-family: inherit;
  border-bottom: 2px solid transparent;
  transition: var(--transition);
}
.participants-tab:hover { color: var(--text-primary); }
.participants-tab--active {
  color: rgb(201,166,96);
  border-bottom-color: rgb(201,166,96);
}

.participants-search {
  position: relative;
  margin-bottom: 16px;
}
.participants-search-icon {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  pointer-events: none;
}
.participants-search input {
  width: 100%;
  /* padding-right: 38px — место под .participants-search-clear (зеркально
     с padding-left под search-icon). Sprint participants-search-persist. */
  padding: 10px 38px 10px 38px;
  background: #0f0f12;
  border: 1px solid var(--border);
  border-radius: 10px;
  color: var(--text-primary);
  font-family: inherit;
  font-size: 0.95rem;
  outline: none;
  transition: border-color 0.15s ease;
}
.participants-search input:focus { border-color: rgba(201,166,96,0.5); }

/* Sprint participants-search-persist: clear-button внутри input. Pattern
   copy с .msg-search-clear (messaging.css:201-217) в namespaced класс
   чтобы не зависеть от messaging.css на /participants. */
.participants-search-clear {
  position: absolute;
  right: 14px;
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  padding: 4px;
  cursor: pointer;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
}
.participants-search-clear:hover {
  color: var(--text-primary);
  background: rgba(255,255,255,0.05);
}
.participants-search-clear.hidden { display: none; }

.participants-grid {
  display: grid;
  /* min(340px, 100%) — иначе единственная колонка шириной 340px не влезала в
     контейнер узкого телефона (360px минус паддинги) и страница получала
     горизонтальный скролл. */
  grid-template-columns: repeat(auto-fill, minmax(min(340px, 100%), 1fr));
  gap: 16px;
  transition: opacity 0.15s ease;
}
.participant-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px;
  padding-right: 64px;
  /* min-height гарантирует что стек из 2 actions-кнопок справа сверху
     помещается целиком: top 12 + (40+8+40) + bottom 12 = 112 + visual
     padding. Без него у юзеров без position/organization/city карточка
     схлопывается до высоты только-имя и нижняя кнопка торчит за рамку. */
  min-height: 140px;
  background: #1a1a1c;
  border: 1px solid var(--border);
  border-radius: 12px;
  cursor: pointer;
  transition: border-color 0.15s ease, transform 0.15s ease;
}
.participant-card:hover {
  border-color: rgba(201,166,96,0.4);
  transform: translateY(-1px);
}
.participant-card-top {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  flex: 1;
}
.participant-avatar {
  flex-shrink: 0;
  width: 60px;
  height: 60px;
  border-radius: 12px;
  overflow: hidden;
  background: #0f0f12;
  border: 1px solid rgba(201,166,96,0.25);
}
.participant-avatar img { width: 100%; height: 100%; object-fit: cover; }
.participant-body { flex: 1; min-width: 0; }
.participant-name {
  font-size: 1rem;
  font-weight: 600;
  color: var(--text-primary);
  line-height: 1.25;
  margin-bottom: 6px;
  word-wrap: break-word;
}
.participant-position {
  font-size: 0.82rem;
  color: var(--text-primary);
  line-height: 1.35;
  margin-bottom: 2px;
  word-wrap: break-word;
}
.participant-org {
  font-size: 0.8rem;
  color: var(--text-muted);
  line-height: 1.35;
  margin-bottom: 4px;
  word-wrap: break-word;
}
.participant-city {
  font-size: 0.74rem;
  color: var(--text-muted);
  margin-top: 2px;
}
/* Sprint /participants redesign: actions-stack в правом верхнем углу
   карточки. Position: absolute от .participant-card (которая теперь
   position: relative). Стек вертикальный — subscribe сверху, conv-action
   снизу. */
.participant-actions-stack {
  position: absolute;
  top: 12px;
  right: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.participant-iconbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  background: none;
  border: 1px solid rgba(201,166,96,0.4);
  border-radius: 50%;
  color: rgb(201,166,96);
  cursor: pointer;
  font-family: inherit;
  transition: var(--transition);
  flex-shrink: 0;
  text-decoration: none;
}
.participant-iconbtn:hover {
  background: rgba(201,166,96,0.12);
}
.participant-iconbtn--filled {
  background: rgba(201,166,96,0.85);
  color: var(--bg-card);
  border-color: rgba(201,166,96,0.85);
}
.participant-iconbtn--filled:hover {
  background: rgb(201,166,96);
  border-color: rgb(201,166,96);
}
.participant-iconbtn--disabled,
.participant-iconbtn[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}
.participant-iconbtn--disabled:hover,
.participant-iconbtn[disabled]:hover {
  background: none;
}

.participants-pagination {
  display: flex;
  justify-content: center;
  gap: 6px;
  margin-top: 20px;
}
.pag-btn {
  min-width: 32px;
  padding: 6px 10px;
  background: #1a1a1c;
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text-primary);
  font-family: inherit;
  font-size: 0.85rem;
  cursor: pointer;
  transition: var(--transition);
}
.pag-btn:hover:not(:disabled) { border-color: rgba(201,166,96,0.4); }
.pag-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.pag-btn--active {
  background: rgb(201,166,96);
  color: #0f0f1a;
  border-color: rgb(201,166,96);
}

/* ============ /notifications page ============ */
.notif-page-header {
  display: flex;
  align-items: baseline;
  gap: 16px;
  margin-bottom: 16px;
  flex-wrap: wrap;
}
.notif-page-title {
  font-family: 'Bounded', sans-serif;
  font-size: 1.6rem;
  margin: 0;
  color: var(--text-primary);
}
.notif-page-counter {
  font-size: 0.85rem;
  color: rgb(201,166,96);
  font-weight: 600;
}
.notif-page-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin-bottom: 16px;
  flex-wrap: wrap;
}
.notif-page-filters {
  display: flex;
  gap: 8px;
}
.notif-page-filter {
  background: transparent;
  border: 1px solid rgba(201,166,96,0.3);
  color: var(--text-secondary);
  font-size: 0.82rem;
  padding: 6px 14px;
  border-radius: 999px;
  cursor: pointer;
  font-family: inherit;
  transition: var(--transition);
}
.notif-page-filter:hover { background: rgba(201,166,96,0.08); color: var(--text-primary); }
.notif-page-filter--active {
  background: rgb(201,166,96);
  border-color: rgb(201,166,96);
  color: #0f0f1a;
}
.notif-page-actions-bar {
  display: flex;
  gap: 8px;
}
.notif-page-action-btn {
  background: transparent;
  border: 1px solid rgba(201,166,96,0.3);
  color: rgb(201,166,96);
  font-size: 0.8rem;
  padding: 6px 14px;
  border-radius: 999px;
  cursor: pointer;
  font-family: inherit;
  transition: var(--transition);
}
.notif-page-action-btn:hover { background: rgba(201,166,96,0.12); color: var(--text-primary); }
.notif-page-action-btn--danger { border-color: rgba(220,53,69,0.3); color: #e57373; }
.notif-page-action-btn--danger:hover { background: rgba(220,53,69,0.12); color: #ff8a80; border-color: rgba(220,53,69,0.5); }

.notif-page-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.notif-page-card {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 14px 16px;
  background: #1a1a1c;
  border: 1px solid var(--border);
  border-radius: 10px;
  cursor: pointer;
  transition: var(--transition);
}
.notif-page-card:hover { border-color: rgba(201,166,96,0.4); background: #1f1f22; }
.notif-page-card--unread {
  border-left: 3px solid rgb(201,166,96);
  background: rgba(201,166,96,0.04);
}
.notif-page-card--read { opacity: 0.7; }

.notif-page-icon {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(201,166,96,0.12);
  color: rgb(201,166,96);
}
.notif-page-icon--success { background: rgba(40,167,69,0.15); color: #4caf50; }
.notif-page-icon--danger  { background: rgba(220,53,69,0.15); color: #e57373; }
.notif-page-icon--warning { background: rgba(255,152,0,0.15); color: #ffb74d; }

/* Phase 5-C v2 UX: «Оспорить» кнопка в карточке message_warning */
.notif-page-appeal-btn {
  display: inline-block;
  margin-top: 4px;
  padding: 5px 14px;
  background: rgba(255,152,0,0.15);
  border: 1px solid rgba(255,152,0,0.4);
  color: #ffb74d;
  border-radius: 12px;
  font-size: 0.78rem;
  font-family: inherit;
  cursor: pointer;
}
.notif-page-appeal-btn:hover {
  background: rgba(255,152,0,0.25);
}

.notif-page-content {
  flex: 1;
  min-width: 0;
}
.notif-page-title-row {
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--text-primary);
  margin-bottom: 4px;
  word-wrap: break-word;
}
.notif-page-body {
  font-size: 0.82rem;
  color: var(--text-secondary);
  margin-bottom: 6px;
  word-wrap: break-word;
}
.notif-page-date {
  font-size: 0.75rem;
  color: var(--text-muted);
}

.notif-page-actions {
  display: flex;
  gap: 6px;
  flex-shrink: 0;
}
.notif-page-act {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-muted);
  width: 30px;
  height: 30px;
  border-radius: 8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: var(--transition);
}
.notif-page-act:hover { border-color: rgba(201,166,96,0.4); color: rgb(201,166,96); }
.notif-page-act--danger:hover { border-color: rgba(220,53,69,0.5); color: #e57373; }

@media (max-width: 600px) {
  .notif-page-toolbar { flex-direction: column; align-items: stretch; }
  .notif-page-actions-bar { justify-content: flex-end; }
  .notif-page-card { padding: 12px; }
  .notif-page-icon { width: 28px; height: 28px; }
}

/* Dashboard subs feed (Фаза 3) */
.subs-feed-author {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.72rem;
  color: var(--text-muted);
  margin-top: 4px;
}
.subs-feed-author-avatar {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  overflow: hidden;
  background: #0f0f12;
}
.subs-feed-author-avatar img { width: 100%; height: 100%; object-fit: cover; }
.subs-feed-author-meta { color: var(--text-muted); font-size: 0.68rem; }

/* ============ MESSENGER section extracted to public/css/messaging.css (M0-8, 2026-05-06).
   Includes R3a (100dvh fallback) and R3b (env(safe-area-inset-bottom)) viewport fixes. ============ */

/* Admin complaints sub-tab buttons (Phase 5-C v2) */
.complaints-tab-btn {
  background: none;
  border: 1px solid var(--border);
  color: var(--text-muted);
}
.complaints-tab-btn--active {
  background: rgba(201,166,96,0.15);
  border-color: rgba(201,166,96,0.5);
  color: rgb(201,166,96);
}

/* ================ Site Footer (D-1.8b) ================ */
/* Sticky footer для страниц с .site-footer */
body:has(.site-footer) {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
body:has(.site-footer) > .site-footer {
  margin-top: auto;
}

.site-footer {
  padding: 24px 24px;
  border-top: 1px solid var(--border);
  background: var(--bg-secondary);
}
.site-footer-inner {
  max-width: 1200px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
  color: var(--text-muted);
  font-size: 0.88rem;
}
.site-footer-link {
  color: var(--text-secondary);
  text-decoration: none;
  transition: var(--transition);
}
.site-footer-link:hover {
  color: var(--gold);
}
.site-footer-sep {
  color: var(--text-muted);
  opacity: 0.5;
}
.site-footer-copy {
  color: var(--text-muted);
}
@media (max-width: 480px) {
  .site-footer { padding: 20px 16px; }
  .site-footer-inner { font-size: 0.82rem; gap: 8px; }
}
/* ================ End Site Footer ================ */

/* ================ /my-articles (SPA Phase 1.C) ================
 * Перенесено из inline <style> в views/my-articles.html.
 * .notif-dropdown/.notif-item НЕ перенесены (dead CSS, не используется в JS).
 * .notif-badge уже определён выше — не дублируется.
 */
.my-article-card {
  background: var(--bg-input);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 16px;
  margin-bottom: 10px;
}
.my-article-card.clickable { cursor: pointer; transition: var(--transition); }
.my-article-card.clickable:hover { border-color: rgba(201, 166, 96, 0.5); }
.my-article-card-title {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-primary);
  margin-bottom: 6px;
}
.my-article-card-meta {
  font-size: 0.75rem;
  color: var(--text-muted);
  margin-bottom: 10px;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.my-article-status {
  font-size: 0.7rem;
  padding: 2px 8px;
  border-radius: 8px;
  font-weight: 600;
}
.my-status-pending { background: rgba(255, 193, 7, 0.15); color: #ffc107; border: 1px solid rgba(255, 193, 7, 0.3); }
.my-status-published { background: rgba(40, 167, 69, 0.15); color: #28a745; border: 1px solid rgba(40, 167, 69, 0.3); }
.my-status-rejected { background: rgba(220, 53, 69, 0.15); color: #dc3545; border: 1px solid rgba(220, 53, 69, 0.3); }
.my-status-draft { background: rgba(201, 166, 96, 0.1); color: var(--gold); border: 1px solid rgba(201, 166, 96, 0.2); }

/* Stats modal (открывается из my-articles). .user-stats-overlay.hidden
 * override уже определён выше в общем .hidden блоке. */
.user-stats-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.85);
  z-index: 2000;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 20px;
  overflow-y: auto;
}
.user-stats-modal {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 16px;
  width: 100%;
  max-width: 760px;
  padding: 28px;
  margin: auto;
}
.user-stats-chart-wrap {
  display: flex;
  align-items: flex-end;
  gap: 4px;
  height: 120px;
  margin: 16px 0 8px;
  padding: 0 4px;
  /* «По дням» = ~30 столбиков: на узком экране листаем вбок вместо разъезда. */
  overflow-x: auto;
  scrollbar-width: none;
}
.user-stats-chart-wrap::-webkit-scrollbar { display: none; }
.user-stats-col {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: 1;
  min-width: 22px;
  height: 100%;
  justify-content: flex-end;
  gap: 4px;
  cursor: pointer;
}
.user-stats-bar {
  width: 100%;
  border-radius: 4px 4px 0 0;
  min-height: 4px;
  transition: opacity 0.2s;
}
.user-stats-label {
  font-size: 0.6rem;
  color: var(--text-muted);
  text-align: center;
  white-space: nowrap;
}
.user-stats-count {
  font-size: 0.7rem;
  color: var(--gold);
  font-weight: 600;
}
/* «За всё время» — без графика, крупное число (total/unique глобальные). */
.user-stats-alltime {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  gap: 4px;
}
.user-stats-alltime-num {
  font-size: 2.4rem;
  font-weight: 700;
  color: var(--gold);
  line-height: 1;
}
.user-stats-alltime-sub {
  font-size: 0.85rem;
  color: var(--text-secondary);
}
.user-stats-alltime-uniq {
  font-size: 0.78rem;
  color: var(--text-muted);
}
/* Кнопки периода: один ряд с горизонтальным свайпом (на узком экране вместо
   переноса в 2 ряда). Блочный контейнер на всю ширину → overflow-x скроллит. */
#userStatsPeriodBtns {
  overflow-x: auto;
  scrollbar-width: none;
}
#userStatsPeriodBtns::-webkit-scrollbar { display: none; }
#userStatsPeriodBtns button { flex-shrink: 0; white-space: nowrap; }
/* Счётчики Лайки/Сохранения/Комментарии: один ряд со свайпом на узком экране. */
#userStatsCounters {
  overflow-x: auto;
  scrollbar-width: none;
}
#userStatsCounters::-webkit-scrollbar { display: none; }
#userStatsCounters > div { flex-shrink: 0; }
/* Под-вкладки аудитории (Просмотры/Лайки/Сохранения): свайп на узком экране. */
.user-stats-who {
  display: flex;
  gap: 6px;
  margin: 18px 0 10px;
  overflow-x: auto;
  scrollbar-width: none;
}
.user-stats-who::-webkit-scrollbar { display: none; }
.user-stats-who .feed-tab { flex-shrink: 0; }
/* Список людей аудитории + строка человека. */
.user-stats-aud { display: flex; flex-direction: column; gap: 8px; }
.aud-person {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 12px;
  background: var(--bg-input);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  cursor: pointer;
  transition: var(--transition);
}
.aud-person:hover { border-color: rgba(201, 166, 96, 0.5); }
.aud-person-info { min-width: 0; flex: 1; }
.aud-person-name {
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.aud-person-sub {
  font-size: 0.76rem;
  color: var(--text-muted);
  margin-top: 1px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.aud-person-stats { display: flex; gap: 12px; align-items: center; margin-top: 6px; }
.aud-stat { display: inline-flex; align-items: center; gap: 3px; color: var(--text-muted); font-size: 0.72rem; }
.aud-stat--on { color: var(--gold); }
.aud-person-action { flex-shrink: 0; }
/* Когда открыта модалка статистики (z-index 2000), запрос-модалка (.modal-overlay,
   z-index 1000) при «Отправить запрос» должна быть ПОВЕРХ неё, а не под backdrop'ом.
   Скоупим бамп только на время открытой статистики — остальные контексты не трогаем. */
body:has(.user-stats-overlay:not(.hidden)) .modal-overlay { z-index: 2500; }
/* ================ End /my-articles ================ */

/* ================ /article (SPA Phase 1.D) ================
 * Перенесено из inline <style> в views/article.html (миграция на SPA shell).
 * Ни один из article-*/comment-* классов ранее в styles.css не определялся —
 * перенос дословный, без дедупа.
 */
    /* Кнопка «Назад» использует pill-стиль .profile-back-btn (reuse). На широкой
       колонке статьи добавляем нижний отступ, чтобы дата не липла к кнопке. */
    .article-back-btn { margin-bottom: 24px; }
    .article-wrap {
      max-width: 100%;
      padding: 32px 0 60px;
    }
    .article-hero {
      width: 100%;
      /* G2 (CLS): резервируем высоту под обложку до загрузки картинки.
         Обложки 16:9 (кроппер); aspect-ratio задаёт высоту по ширине ещё
         до onload, max-height клампит на широкой колонке. Без этого контент
         ниже прыгал вверх на ~380px при подгрузке hero. */
      aspect-ratio: 16 / 9;
      max-height: 380px;
      object-fit: cover;
      border-radius: 14px;
      display: block;
      margin-bottom: 28px;
    }
    .article-date {
      font-size: 0.8rem;
      color: var(--text-muted);
      margin-bottom: 14px;
    }
    /* Ряд статистики — визуально как счётчики карточки (.dash-article-counter),
       но like/save кликабельны: --btn даёт курсор+hover, .is-on — золотой active
       (заливка иконки через CSS, без JS-swap). */
    .article-stats {
      display: flex;
      align-items: center;
      gap: 6px;
      flex-wrap: wrap;
      margin-bottom: 24px;
    }
    .article-stat {
      display: inline-flex;
      align-items: center;
      gap: 5px;
      padding: 5px 11px;
      border-radius: 8px;
      color: var(--text-muted);
      font-size: 0.78rem;
      line-height: 1;
      background: rgba(255,255,255,0.02);
      border: 1px solid rgba(255,255,255,0.05);
      text-decoration: none;
      font-family: inherit;
      font-variant-numeric: tabular-nums;
    }
    .article-stat svg { flex-shrink: 0; }
    /* Счётчик со значением > 0 — золотой (как на карточке). Только цвет/фон/рамка,
       БЕЗ заливки иконки (это не toggle, в отличие от .is-on). */
    .article-stat--active {
      color: rgb(201,166,96);
      background: rgba(201,166,96,0.1);
      border-color: rgba(201,166,96,0.3);
    }
    /* Share-чип: золотой по умолчанию + ширина как у соседнего счётчика с одной
       цифрой (min-width), значок по центру. Высота = счётчикам (line-height:1). */
    .article-stat--share {
      min-width: 50px;
      justify-content: center;
      color: rgb(201,166,96);
      background: rgba(201,166,96,0.1);
      border-color: rgba(201,166,96,0.3);
    }
    .article-stat--share:hover {
      color: rgb(227,200,140);
      background: rgba(201,166,96,0.16);
      border-color: rgba(201,166,96,0.4);
    }
    /* Нижние кнопки like/save/share: SVG как block + icon-обёртка как flex —
       убирает baseline-сдвиг инлайн-SVG (значок был выше центра кнопки). */
    .btn-react svg { display: block; }
    .btn-react .react-icon { display: inline-flex; align-items: center; }
    .article-stat--btn {
      cursor: pointer;
      transition: color 0.15s, background 0.15s, border-color 0.15s;
    }
    .article-stat--btn:hover {
      color: rgb(201,166,96);
      background: rgba(201,166,96,0.06);
      border-color: rgba(201,166,96,0.2);
    }
    .article-stat.is-on {
      color: rgb(201,166,96);
      background: rgba(201,166,96,0.1);
      border-color: rgba(201,166,96,0.3);
    }
    .article-stat.is-on svg { fill: rgb(201,166,96); }
    /* Конференции под заголовком: 1 — чип; 2+ — «Темы (N)» + раскрытие списка. */
    .article-confs {
      display: flex;
      align-items: center;
      gap: 8px;
      flex-wrap: wrap;
      margin-bottom: 20px;
    }
    .article-conf-toggle {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      background: rgba(201,166,96,0.1);
      border: 1px solid rgba(201,166,96,0.25);
      color: var(--gold);
      font-size: 0.78rem;
      font-family: inherit;
      padding: 4px 12px;
      border-radius: 20px;
      cursor: pointer;
      transition: background 0.15s;
    }
    .article-conf-toggle:hover { background: rgba(201,166,96,0.18); }
    .article-conf-toggle svg { transition: transform 0.15s; }
    .article-conf-toggle[aria-expanded="true"] svg { transform: rotate(180deg); }
    .article-conf-list {
      display: none;
      width: 100%;
      flex-wrap: wrap;
      gap: 8px;
    }
    .article-conf-list.open { display: flex; }
    /* Автор построчно: «Автор» (белым) / ФИО (золотым) / должность (белым) /
       компания (тёмно-золотым). Аватар + кликабельное имя добавит Этап 3. */
    .article-author {
      display: flex;
      align-items: flex-start;
      gap: 14px;
      margin-bottom: 28px;
    }
    /* Аватар-квадрат со скруглением (как .profile-avatar). Размер = высоте блока
       автора (от «Автор» до низа компании) — задаётся в JS (sizeAuthorAvatar):
       aspect-ratio в flex НЕ выводит ширину из растянутой высоты надёжно. Здесь
       80px — fallback-квадрат до JS-замера/без JS. */
    .article-author-avatar {
      position: relative;
      flex-shrink: 0;
      width: 80px;
      height: 80px;
      border-radius: 12px;
      overflow: hidden;
      border: 1px solid rgba(201,166,96,0.35);
      background: #0f0f12;
    }
    .article-author-avatar img {
      position: absolute;
      inset: 0;
      width: 100%;
      height: 100%;
      object-fit: cover;
      display: block;
    }
    .article-author-info { min-width: 0; }
    .article-author-label {
      font-size: 0.78rem;
      color: var(--text-primary);
      margin-bottom: 5px;
    }
    .article-author-name {
      display: inline-block;
      font-size: 0.98rem;
      font-weight: 600;
      color: rgb(201,166,96);
    }
    .article-author-link { text-decoration: none; }
    .article-author-link:hover { text-decoration: underline; }
    .article-author-position {
      font-size: 0.85rem;
      color: var(--text-primary);
      margin-top: 2px;
    }
    .article-author-org {
      font-size: 0.85rem;
      color: rgba(201,166,96,0.7);
      margin-top: 2px;
    }
    .article-conference {
      background: rgba(201,166,96,0.1);
      border: 1px solid rgba(201,166,96,0.25);
      color: var(--gold);
      font-size: 0.75rem;
      padding: 3px 10px;
      border-radius: 20px;
    }
    .article-body {
      font-size: 0.97rem;
      line-height: 1.85;
      color: var(--text-primary);
      white-space: pre-wrap;
      overflow-wrap: break-word; /* round5 #8: длинный URL/слово не даёт горизонтальный скролл body */
    }
    .article-body a {
      color: var(--gold);
      text-decoration: underline;
    }
    .article-title {
      font-size: 1.6rem;
      font-weight: 700;
      line-height: 1.3;
      margin-bottom: 12px;
      color: var(--text-primary);
    }
    .article-block { margin-bottom: 24px; }
    .article-block-heading {
      font-size: 1.15rem;
      font-weight: 700;
      color: var(--text-primary);
      line-height: 1.4;
      padding-bottom: 8px;
      border-bottom: 1px solid rgba(201,166,96,0.2);
      margin-bottom: 12px;
    }
    .article-block-text {
      font-size: 0.95rem;
      line-height: 1.8;
      color: var(--text-primary);
      white-space: pre-wrap;
      overflow-wrap: break-word; /* round5 #8: перенос длинных слов/ссылок */
    }
    .article-block-text a { color: var(--gold); text-decoration: underline; }
    .article-block-image {
      max-width: 100%;
      margin: 0 auto;
      display: flex;
      justify-content: center;
    }
    .article-block-image img {
      height: auto;
      display: block;
      border-radius: 12px;
    }
    .article-loading {
      text-align: center;
      padding: 80px 0;
      color: var(--text-muted);
    }
    .article-error {
      text-align: center;
      padding: 80px 0;
      color: var(--danger);
    }

    /* === Comments (этап 6.2) === */
    .article-comments-heading {
      font-size: 1.2rem; font-weight: 500;
      margin: 0 0 20px; color: var(--text-primary);
      /* Скролл к #comments не должен садиться под sticky-шапку (desktop 80px,
         mobile ~60px + safe-area). Запас сверху при scrollIntoView/native-anchor. */
      scroll-margin-top: calc(env(safe-area-inset-top, 0px) + 92px);
    }
    /* Тумблер сортировки комментов «Новые / Популярные». */
    .comments-sort { display: inline-flex; gap: 6px; margin: -8px 0 18px; }
    .comments-sort-btn {
      padding: 5px 14px; border-radius: 16px; cursor: pointer;
      border: 1px solid var(--border); background: transparent;
      color: var(--text-muted); font-size: 0.85rem; transition: color 0.2s ease, background 0.2s ease, border-color 0.2s ease;
    }
    .comments-sort-btn.is-active { background: rgb(201, 166, 96); border-color: rgb(201, 166, 96); color: #000; }
    .article-comment-form {
      margin-bottom: 24px; padding: 12px;
      background: var(--bg-card); border-radius: var(--radius);
    }
    .article-comment-form textarea {
      width: 100%; min-height: 70px; resize: vertical;
      background: transparent; border: 1px solid var(--border);
      border-radius: var(--radius); padding: 10px;
      color: var(--text-primary); font-family: inherit; font-size: 0.9rem;
      box-sizing: border-box;
    }
    .article-comment-form textarea:disabled {
      opacity: 0.5; cursor: not-allowed;
    }
    .article-comment-form-footer {
      display: flex; justify-content: space-between; align-items: center;
      margin-top: 8px;
    }
    .article-comment-form-footer span {
      font-size: 0.78rem; color: var(--text-muted);
    }
    .comment-empty {
      text-align: center; color: var(--text-muted); padding: 24px;
    }
    .comment-item {
      padding: 14px 0;
      border-bottom: 1px solid rgba(255,255,255,0.05);
    }
    .comment-item:last-child { border-bottom: none; }
    .comment-item.is-pinned {
      background: rgba(201,166,96,0.04);
      border-radius: var(--radius);
      padding: 14px; margin-bottom: 12px;
      border: 1px solid rgba(201,166,96,0.2);
    }
    .comment-pin-marker {
      display: inline-flex; align-items: center; gap: 6px;
      font-size: 0.78rem; color: rgb(201,166,96);
      margin-bottom: 8px;
    }
    .comment-header {
      display: flex; align-items: center; gap: 10px; margin-bottom: 8px;
    }
    .comment-avatar {
      width: 36px; height: 36px; border-radius: 8px;
      background: var(--bg-card); object-fit: cover; flex-shrink: 0;
    }
    .comment-author-info {
      display: flex; flex-direction: column; flex: 1; min-width: 0;
    }
    .comment-author-name {
      font-weight: 600; font-size: 0.88rem;
      color: var(--text-primary); text-decoration: none;
    }
    .comment-author-name:hover { color: rgb(201,166,96); }
    .comment-meta {
      font-size: 0.74rem; color: var(--text-muted);
    }
    .comment-meta-edited {
      font-style: italic; margin-left: 6px;
    }
    .comment-body {
      font-size: 0.9rem; line-height: 1.5; color: var(--text-primary);
      white-space: pre-wrap; word-wrap: break-word; margin-bottom: 10px;
    }
    .comment-body.is-deleted {
      font-style: italic; color: var(--text-muted);
    }
    .comment-actions {
      display: flex; gap: 14px; align-items: center; flex-wrap: wrap;
      font-size: 0.78rem;
    }
    .comment-action-btn {
      background: transparent; border: none; color: var(--text-muted);
      cursor: pointer; padding: 4px;
      display: inline-flex; align-items: center; gap: 4px;
      font-family: inherit; font-size: 0.78rem;
    }
    .comment-action-btn:hover { color: rgb(201,166,96); }
    .comment-action-btn[data-active="1"] { color: rgb(201,166,96); }
    .comment-replies {
      margin-left: 46px; margin-top: 12px;
      padding-left: 16px;
      border-left: 2px solid rgba(255,255,255,0.05);
    }
    .comment-replies-toggle {
      margin-top: 8px; margin-left: 46px;
      font-size: 0.78rem;
    }
    .comment-edit-form,
    .comment-reply-form {
      margin-top: 10px; padding: 10px;
      background: var(--bg-card); border-radius: var(--radius);
    }
    .comment-edit-form textarea,
    .comment-reply-form textarea {
      width: 100%; min-height: 60px; resize: vertical;
      background: transparent; border: 1px solid var(--border);
      border-radius: var(--radius); padding: 8px;
      color: var(--text-primary); font-family: inherit; font-size: 0.85rem;
      box-sizing: border-box;
    }
    .comment-form-actions {
      display: flex; gap: 8px; justify-content: flex-end; margin-top: 8px;
    }
    .comment-form-actions button {
      padding: 6px 14px; border-radius: var(--radius);
      font-size: 0.8rem; font-family: inherit; cursor: pointer;
      border: 1px solid var(--border); background: transparent;
      color: var(--text-primary);
    }
    .comment-form-actions .btn-primary {
      background: rgb(201,166,96); color: #000;
      border-color: rgb(201,166,96);
    }
    .comment-form-actions .btn-primary:disabled {
      opacity: 0.5; cursor: not-allowed;
    }
/* ================ End /article ================ */

/* ================ /settings (SPA Phase 1.F) ================
 * Перенесено из inline <style> в views/settings.html.
 * .notif-* (мёртвые дубли) и .support-* (принадлежат /support) НЕ перенесены.
 * .avatar-crop-overlay.hidden утилита уже определена выше — не дублируется.
 */
    .settings-section {
      background: var(--bg-card);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      margin-bottom: 16px;
      overflow: hidden;
    }
    .settings-section-header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 18px 20px;
      cursor: pointer;
      user-select: none;
      transition: background 0.15s;
    }
    .settings-section-header:hover { background: rgba(201,166,96,0.04); }
    .settings-section-title {
      display: flex;
      align-items: center;
      gap: 12px;
      font-weight: 600;
      font-size: 0.95rem;
    }
    .settings-section-icon {
      width: 36px;
      height: 36px;
      border-radius: 10px;
      background: rgba(201,166,96,0.1);
      border: 1px solid rgba(201,166,96,0.2);
      display: flex;
      align-items: center;
      justify-content: center;
      color: rgb(201,166,96);
      flex-shrink: 0;
    }
    .settings-chevron {
      color: var(--text-muted);
      transition: transform 0.2s;
    }
    .settings-chevron.open { transform: rotate(180deg); }
    .settings-section-body {
      display: none;
      padding: 20px;
      border-top: 1px solid var(--border);
    }
    .settings-section-body.open { display: block; }
    .topics-grid {
      display: grid;
      grid-template-columns: 1fr;
      gap: 8px;
      margin-top: 6px;
    }
    .topics-grid label {
      display: flex;
      align-items: center;
      gap: 10px;
      padding: 10px 12px;
      background: var(--bg-input);
      border-radius: var(--radius-sm);
      cursor: pointer;
      font-size: 0.9rem;
      color: var(--text-primary);
    }
    .topics-grid input[type="checkbox"] {
      accent-color: var(--gold);
      width: 18px;
      height: 18px;
    }
    .avatar-circle-wrap {
      width: 120px;
      height: 120px;
      position: relative;
      margin: 8px auto 16px;
      cursor: pointer;
    }
    .avatar-circle-inner {
      width: 120px;
      height: 120px;
      border-radius: 12px;
      background: #1a1a1c;
      border: 2px solid rgba(201,166,96,0.3);
      display: flex;
      align-items: center;
      justify-content: center;
      overflow: hidden;
      transition: border-color 0.2s;
    }
    .avatar-circle-wrap:hover .avatar-circle-inner { border-color: rgba(201,166,96,0.7); }
    .avatar-circle-overlay {
      position: absolute;
      top: 0; left: 0;
      width: 120px;
      height: 120px;
      border-radius: 12px;
      background: rgba(0,0,0,0.45);
      display: flex;
      align-items: center;
      justify-content: center;
      opacity: 0;
      transition: opacity 0.2s;
    }
    .avatar-circle-wrap:hover .avatar-circle-overlay { opacity: 1; }
    /* overflow-y + max-height: в ландшафте телефона (высота ~390px) модалка
   кроппера обрезалась, кнопки «Сохранить»/«Отмена» были недостижимы. */
.avatar-crop-overlay { overflow-y: auto; }
.avatar-crop-modal { max-height: calc(100vh - 40px); overflow-y: auto; }
.avatar-crop-overlay {
      position: fixed;
      inset: 0;
      background: rgba(0,0,0,0.88);
      z-index: 3000;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 20px;
    }
    .avatar-crop-modal {
      background: #121214;
      border: 1px solid var(--border);
      border-radius: 16px;
      padding: 24px;
      width: 100%;
      max-width: 400px;
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 16px;
    }
    .avatar-crop-viewport {
      /* Модалка теперь прокручиваемая (ландшафт): без touch-action жест
         перетаскивания фото одновременно скроллил бы её, и кадр «прыгал» —
         слушатели перетаскивания passive и отменить прокрутку не могут. */
      touch-action: none;
      width: 280px;
      height: 280px;
      border-radius: 12px;
      overflow: hidden;
      position: relative;
      background: #000;
      cursor: grab;
      border: 2px solid rgba(201,166,96,0.4);
      flex-shrink: 0;
    }
    .avatar-crop-viewport:active { cursor: grabbing; }
    .avatar-crop-img {
      position: absolute;
      transform-origin: 0 0;
      user-select: none;
      pointer-events: none;
    }
/* ================ End /settings ================ */

/* ================ /support (SPA Phase 1.G) ================
 * Перенесено из inline <style> в views/support.html.
 * .notif-* (мёртвые дубли) НЕ перенесены.
 */
    .support-chat { display:flex;flex-direction:column;gap:10px;max-height:60vh;overflow-y:auto;padding:4px 0;margin-bottom:16px; }
    .support-msg { max-width:80%;padding:12px 16px;border-radius:14px;font-size:0.9rem;line-height:1.6;word-break:break-word;color:var(--text-primary); }
    .support-msg.user { background:rgba(201,166,96,0.12);border:1px solid rgba(201,166,96,0.2);align-self:flex-end;border-bottom-right-radius:4px; }
    .support-msg.admin { background:var(--bg-input);border:1px solid var(--border);align-self:flex-start;border-bottom-left-radius:4px; }
    .support-msg-meta { font-size:0.7rem;color:var(--text-muted);margin-top:4px; }
    .support-ticket-card { background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);padding:16px 18px;margin-bottom:10px;cursor:pointer;transition:border-color 0.2s; }
    .support-ticket-card:hover { border-color:rgba(201,166,96,0.4); }
    .support-ticket-card.has-reply { border-left:3px solid var(--gold); }
    .support-screen { display:none; }
    .support-screen.active { display:block; }
/* ================ End /support ================ */

/* ================ /dashboard (SPA Phase 1.I) ================
 * Перенесено из inline <style> в views/dashboard.html.
 * .article-modal-* (неиспользуемые) и .notif-* (мёртвые дубли) НЕ перенесены.
 * .topic-card--sm уже в styles.css.
 */
    .dash-articles-grid {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 16px;
      margin-bottom: 20px;
    }
    @media (max-width: 1023px) {
      .dash-articles-grid { grid-template-columns: repeat(2, 1fr); }
    }
    @media (max-width: 767px) {
      .dash-articles-grid { grid-template-columns: 1fr; }
    }
    .dash-article-card {
      display: flex;
      flex-direction: column;
      background: #1a1a1c;
      border: 1px solid var(--border);
      border-radius: 12px;
      overflow: hidden;
      cursor: pointer;
      transition: border-color 0.2s, background 0.2s, transform 0.2s;
      text-decoration: none;
      color: inherit;
    }
    .dash-article-card:hover {
      border-color: rgba(201,166,96,0.5);
      background: #202022;
      transform: translateY(-1px);
    }
    .dash-article-thumb {
      width: 100%;
      aspect-ratio: 16/9;
      background: #111;
      overflow: hidden;
      position: relative;
      flex-shrink: 0;
    }
    .dash-article-thumb img {
      width: 100%;
      height: 100%;
      object-fit: cover;
      display: block;
    }
    .dash-article-thumb-empty {
      width: 100%;
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 3rem;
      color: rgba(201,166,96,0.18);
    }
    .dash-article-new-badge {
      position: absolute;
      top: 8px;
      right: 8px;
      background: linear-gradient(to right, rgb(227,200,140), rgb(201,166,96), rgb(165,124,61));
      color: #000;
      font-size: 0.62rem;
      font-weight: 700;
      padding: 2px 7px;
      border-radius: 8px;
      letter-spacing: 0.5px;
      text-transform: uppercase;
    }
    .dash-article-body {
      padding: 12px 14px;
      display: flex;
      flex-direction: column;
      gap: 6px;
      min-width: 0;
      flex: 1;
    }
    .dash-article-title {
      font-size: 0.92rem;
      font-weight: 600;
      color: var(--text-primary);
      line-height: 1.35;
      overflow-wrap: break-word;
      word-wrap: break-word;
    }
    .dash-article-date {
      font-size: 0.72rem;
      color: var(--text-muted);
    }
    .dash-article-author {
      display: flex;
      align-items: center;
      gap: 8px;
      min-width: 0;
    }
    .dash-article-author-avatar {
      width: 28px;
      height: 28px;
      border-radius: 6px;
      overflow: hidden;
      background: #0f0f12;
      border: 1px solid rgba(201,166,96,0.25);
      flex-shrink: 0;
    }
    .dash-article-author-avatar img {
      width: 100%;
      height: 100%;
      object-fit: cover;
      display: block;
    }
    .dash-article-author-name {
      font-size: 0.82rem;
      font-weight: 600;
      color: rgb(201,166,96);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      min-width: 0;
    }
    .dash-article-position {
      font-size: 0.75rem;
      color: var(--text-primary);
      overflow-wrap: break-word;
    }
    .dash-article-org {
      font-size: 0.75rem;
      color: rgba(201, 166, 96, 0.7);
      overflow-wrap: break-word;
    }
    .dash-article-bottom-row {
      display: flex;
      align-items: center;
      justify-content: flex-end;
      gap: 8px;
      margin-top: auto;
    }
    .dash-article-counters {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      flex-wrap: wrap;
    }
    .dash-article-counter {
      display: inline-flex;
      align-items: center;
      gap: 5px;
      padding: 3px 8px;
      border-radius: 6px;
      color: var(--text-muted);
      font-size: 0.72rem;
      font-family: inherit;
      line-height: 1;
      background: rgba(255,255,255,0.02);
      border: 1px solid rgba(255,255,255,0.04);
      opacity: 0.65;
      cursor: default;
      font-variant-numeric: tabular-nums;
    }
    .dash-article-counter--active {
      color: rgb(201,166,96);
      opacity: 1;
      background: rgba(201,166,96,0.08);
      border-color: rgba(201,166,96,0.18);
    }
    /* Кликабельные счётчики (like/save/комментарии) — кнопки. */
    .dash-article-counter--btn {
      cursor: pointer;
      transition: color 0.15s, background 0.15s, border-color 0.15s, opacity 0.15s;
    }
    .dash-article-counter--btn:hover {
      opacity: 1;
      color: rgb(201,166,96);
      background: rgba(201,166,96,0.06);
      border-color: rgba(201,166,96,0.2);
    }
    /* Моя реакция (like/save) — золотой + залитая иконка. */
    .dash-article-counter--mine {
      color: rgb(201,166,96);
      opacity: 1;
    }
    .dash-article-counter--mine svg { fill: rgb(201,166,96); }
    /* Золотой по умолчанию + ширина как у соседнего счётчика с одной цифрой
       (min-width), значок по центру. Высота = счётчикам (line-height:1, icon 13px). */
    .dash-article-share {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      padding: 3px 8px;
      min-width: 42px;
      border-radius: 6px;
      color: rgb(201,166,96);
      background: rgba(201,166,96,0.08);
      border: 1px solid rgba(201,166,96,0.25);
      cursor: pointer;
      flex-shrink: 0;
      transition: color 0.15s, background 0.15s, border-color 0.15s;
    }
    .dash-article-share:hover {
      color: rgb(227,200,140);
      background: rgba(201,166,96,0.16);
      border-color: rgba(201,166,96,0.4);
    }
    .dash-pagination {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 12px;
      margin-top: 20px;
    }
    .dash-pagination-info {
      font-size: 0.85rem;
      color: var(--text-muted);
      min-width: 96px;
      text-align: center;
    }
    .subscriptions-panel {
      background: var(--bg-input);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      margin-bottom: 16px;
      overflow: hidden;
    }
    .subscriptions-panel-header {
      display: flex;
      align-items: center;
      gap: 8px;
      cursor: pointer;
      padding: 12px 16px;
      user-select: none;
      transition: background 0.15s;
    }
    .subscriptions-panel-header:hover {
      background: rgba(201,166,96,0.04);
    }
    .subscriptions-panel-title {
      font-size: 0.85rem;
      color: var(--text-secondary);
      flex: 1;
    }
    .subscriptions-panel-body {
      display: none;
      padding: 14px 16px 14px;
      border-top: 1px solid var(--border);
    }
    .subscriptions-panel.open .subscriptions-panel-body {
      display: block;
    }
    .subscriptions-tags {
      display: flex;
      flex-wrap: wrap;
      gap: 6px;
    }
    .subscription-tag {
      padding: 5px 12px;
      border-radius: 20px;
      border: 1px solid var(--border);
      background: var(--bg-input);
      color: var(--text-secondary);
      font-size: 0.8rem;
      cursor: pointer;
      transition: var(--transition);
      font-family: inherit;
    }
    .subscription-tag.active {
      border-color: var(--gold);
      background: rgba(201,166,96,0.12);
      color: var(--gold);
    }
    .subscription-tag:hover { border-color: rgba(201,166,96,0.5); }
    .subscriptions-edit-panel {
      display: none;
      margin-top: 12px;
      padding-top: 12px;
      border-top: 1px solid var(--border);
    }
    .subscriptions-edit-panel.open { display: block; }
    .subscriptions-edit-grid {
      display: flex;
      flex-wrap: wrap;
      gap: 8px;
      margin-bottom: 12px;
    }
    .subscriptions-edit-item {
      display: flex;
      align-items: center;
      gap: 8px;
      padding: 8px 12px;
      background: var(--bg-primary);
      border: 1px solid var(--border);
      border-radius: var(--radius-sm);
      cursor: pointer;
      font-size: 0.85rem;
      color: var(--text-primary);
      transition: var(--transition);
    }
    .subscriptions-edit-item.checked {
      border-color: var(--gold);
      background: rgba(201,166,96,0.08);
    }
    .subscriptions-edit-item input { accent-color: var(--gold); }
    @media (max-width: 500px) {
      .subscriptions-panel-title { font-size: 0.78rem; }
    }
/* ================ End /dashboard ================ */

/* ============ Toasts (SPA Phase 4 — optimistic UI + brand notifications) ============ */
#app-toasts {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 9999;
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-width: min(380px, calc(100vw - 32px));
  pointer-events: none;
}
.cg-toast {
  pointer-events: auto;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  border-radius: var(--radius);
  background: #1a1a1d;
  border: 1px solid var(--border);
  border-left: 3px solid var(--text-muted);
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.45);
  color: var(--text-primary);
  font-size: 0.9rem;
  line-height: 1.45;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.cg-toast--in { opacity: 1; transform: translateY(0); }
.cg-toast--out { opacity: 0; transform: translateY(8px); }
.cg-toast-icon { flex: 0 0 auto; display: inline-flex; margin-top: 1px; }
.cg-toast-msg { flex: 1 1 auto; word-break: break-word; }
.cg-toast-close {
  flex: 0 0 auto;
  display: inline-flex;
  padding: 2px;
  background: none;
  border: none;
  border-radius: 6px;
  color: var(--text-muted);
  cursor: pointer;
  transition: var(--transition);
}
.cg-toast-close:hover { color: var(--text-primary); background: rgba(255, 255, 255, 0.06); }
.cg-toast--success { border-left-color: rgb(90, 180, 120); }
.cg-toast--success .cg-toast-icon { color: rgb(90, 180, 120); }
.cg-toast--error { border-left-color: rgb(214, 84, 84); }
.cg-toast--error .cg-toast-icon { color: rgb(214, 84, 84); }
.cg-toast--info { border-left-color: var(--gold); }
.cg-toast--info .cg-toast-icon { color: var(--gold); }
@media (max-width: 600px) {
  #app-toasts { left: 16px; right: 16px; bottom: 16px; max-width: none; }
}
@media (prefers-reduced-motion: reduce) {
  .cg-toast,
  .cg-toast--in,
  .cg-toast--out { transform: none; transition: opacity 0.2s ease; }
}

/* ============ SPA Phase 8: UX-бэклог ============ */

/* Общая утилита шапки контент-страницы — единая конвенция отступа вместо
   ad-hoc inline style (1:1 с прежним inline-заголовком /my-articles). */
.page-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}

/* Индикатор «комментарий редактируется» (/article/:id). CSS-only через :has()
   — article-comments.js у потолка размера. Золотой left-accent на .comment-item,
   чей собственный slot содержит edit-форму; дублированный read-only body
   приглушаем, чтобы не путать с textarea. */
.comment-item:has(> .comment-form-slot > .comment-edit-form) {
  box-shadow: inset 2px 0 0 var(--gold);
}
.comment-item:has(> .comment-form-slot > .comment-edit-form) > .comment-body {
  opacity: 0.45;
}

/* Индикатор «в ответ на {автор}» у формы ответа (/article/:id). */
.comment-reply-to {
  font-size: 0.78rem;
  color: var(--text-muted);
  margin-bottom: 6px;
  padding-left: 8px;
  border-left: 2px solid var(--gold);
}
/* Атрибуция ответа: под именем автора — стрелка-уголок + имя адресата (белым,
   кликабельно). /article/:id, Этап5. Отдельное правило (НЕ в comma-список
   .comment-edit-form/.comment-reply-form). */
.comment-reply-attr {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-top: 2px;
  font-size: 0.8rem;
  color: var(--text-muted);
}
.comment-reply-attr svg { flex-shrink: 0; }
.comment-reply-attr-name {
  color: var(--text-primary);
  text-decoration: none;
  font-weight: 500;
}
.comment-reply-attr-name:hover { color: rgb(201,166,96); text-decoration: underline; }
/* Мягкая золотая подсветка коммента при переходе из уведомления (deep-link).
   По образцу мессенджера (.msg-bubble--flash). Отдельное правило (не comma-trap). */
@keyframes commentFlash {
  0%   { box-shadow: 0 0 0 0 rgba(201, 166, 96, 0); }
  20%  { box-shadow: 0 0 0 4px rgba(201, 166, 96, 0.5); }
  100% { box-shadow: 0 0 0 0 rgba(201, 166, 96, 0); }
}
.comment-item--flash {
  animation: commentFlash 1500ms cubic-bezier(0.4, 0, 0.2, 1);
  border-radius: 8px;
}

/* ============ Dashboard: вкладки ленты + редактор тем ============ */
.feed-tabs {
  display: flex;
  gap: 8px;
  margin-bottom: 14px;
  flex-wrap: wrap;
}
.feed-tab {
  padding: 6px 16px;
  border-radius: 20px;
  border: 1px solid var(--border);
  background: none;
  color: var(--text-muted);
  font-size: 0.82rem;
  font-family: inherit;
  cursor: pointer;
  transition: var(--transition);
}
.feed-tab:hover { border-color: rgba(201, 166, 96, 0.5); color: var(--text-secondary); }
.feed-tab.active {
  border-color: var(--gold);
  background: rgba(201, 166, 96, 0.15);
  color: var(--gold);
}
.feed-tab:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.feed-tab:disabled:hover {
  border-color: var(--border);
  color: var(--text-muted);
}
.feed-tab-count {
  margin-left: 6px;
  font-size: 0.72rem;
  opacity: 0.7;
  font-weight: 400;
}
/* /my-articles: 6 вкладок на мобиле — один ряд со свайпом вбок (вместо 3 рядов
   переноса). Скоуп только #myArticlesTabs, дашбордовые .feed-tabs не трогаем.
   mask справа = подсказка «есть ещё»; полосу прокрутки прячем. */
@media (max-width: 767px) {
  #myArticlesTabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 22px), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - 22px), transparent);
  }
  #myArticlesTabs::-webkit-scrollbar { display: none; }
  #myArticlesTabs .feed-tab { flex-shrink: 0; }
  #myArticlesTabs.tabs-at-end {
    -webkit-mask-image: none;
    mask-image: none;
  }
}

.topics-section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 4px;
  flex-wrap: wrap;
}
.topics-section-title { font-size: 1.05rem; font-weight: 700; color: var(--text-primary); }
.topics-subs-link { font-size: 0.82rem; color: var(--gold); text-decoration: none; white-space: nowrap; }
.topics-subs-link:hover { text-decoration: underline; }
.topics-section-hint { font-size: 0.85rem; color: var(--text-muted); margin-bottom: 14px; }
/* scope: #topicsSection — иначе коллизия с settings .topics-grid (другой layout). */
#topicsSection .topics-grid { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }
.topic-chip {
  padding: 7px 14px;
  border-radius: 20px;
  border: 1px solid var(--border);
  background: var(--bg-input);
  color: var(--text-secondary);
  font-size: 0.85rem;
  font-family: inherit;
  cursor: pointer;
  transition: var(--transition);
}
.topic-chip:hover { border-color: rgba(201, 166, 96, 0.5); }
.topic-chip.selected {
  border-color: var(--gold);
  background: rgba(201, 166, 96, 0.15);
  color: var(--gold);
  font-weight: 600;
}
.topics-section-actions { display: flex; align-items: center; gap: 12px; }
.topics-save-hint { font-size: 0.82rem; color: var(--text-muted); }

/* ===== Мобильная нижняя панель навигации + «Ещё»-меню =====
   DOM строит public/js/common/bottom-nav.js (инжектит .mnav + меню в <body>).
   «Матовое стекло» — на ::before (иначе backdrop-filter мылит иконки на iOS).
   Панель скрыта на десктопе (там верхняя шапка) и в открытом диалоге мессенджера. */
.mnav {
  position: fixed;
  left: 0;
  right: 0;
  margin: 0 auto;
  bottom: max(10px, env(safe-area-inset-bottom, 0px) - 18px);
  z-index: 210;
  display: none;
  align-items: center;
  gap: 6px;
  width: calc(100% - 24px);
  max-width: 460px;
  padding: 8px;
  border-radius: 22px;
}
.mnav::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: rgba(18, 18, 20, 0.72);
  -webkit-backdrop-filter: blur(18px);
  backdrop-filter: blur(18px);
  border: 1px solid var(--border);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.45);
}
.mnav-btn {
  position: relative;
  flex: 1 1 0;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 48px;
  padding: 0;
  border: none;
  background: transparent;
  border-radius: var(--radius);
  color: var(--gold-dark);
  cursor: pointer;
  transition: var(--transition);
  -webkit-tap-highlight-color: transparent;
}
.mnav-ico { display: inline-flex; }
/* Без кольца фокуса на кнопках панели: глобальный button:focus-visible (золотое
   кольцо) вспыхивал «хаотично» при программном возврате фокуса на бургер после
   закрытия меню (closeable restoreFocusTo). Панель тач — индикация даётся active-заливкой. */
.mnav-btn:focus,
.mnav-btn:focus-visible { outline: none; }
@media (hover: hover) {
  .mnav-btn:hover { background: rgba(201, 166, 96, 0.10); color: var(--gold); }
}
.mnav-btn--active { background: rgba(201, 166, 96, 0.20); color: var(--gold); }
.mnav-btn .notif-badge { top: 4px; right: 8px; }

.mnav-menu-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: flex-end;
  /* BUG-9: меню всплывает над бургером (крайняя правая кнопка панели), а не по центру. */
  justify-content: flex-end;
  padding: 0 16px calc(max(10px, env(safe-area-inset-bottom, 0px) - 18px) + 60px);
  background: transparent;
  visibility: hidden;
  pointer-events: none;
  transition: visibility .28s ease;
}
.mnav-menu-overlay.is-open { visibility: visible; pointer-events: auto; }
/* Android-нативка (P2-1): базовая формула вычитает 18px (подгон под
   home-indicator iOS) и сажает панель в зону системной навигации — здесь
   инсет ПРИБАВЛЯЕМ. Класс cap-android ставит js/shell/native-shim.js,
   в вебе и на iOS правила мертвы. Меню — тот же низ панели + 60px, как в базе. */
html.cap-android .mnav { bottom: calc(env(safe-area-inset-bottom, 0px) + 8px); }
html.cap-android .mnav-menu-overlay { padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 68px); }
.mnav-menu {
  position: relative;
  width: 100%;
  max-width: 190px;
  padding: 10px;
  border-radius: 20px;
  transform: translateY(120%);
  transform-origin: bottom right; /* BUG-9: раскрытие из-под бургера справа */
  opacity: 0;
  transition: transform .30s cubic-bezier(.22, .61, .36, 1), opacity .22s ease;
}
.mnav-menu::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: rgba(18, 18, 20, 0.82);
  -webkit-backdrop-filter: blur(18px);
  backdrop-filter: blur(18px);
  border: 1px solid var(--border);
}
.mnav-menu-overlay.is-open .mnav-menu { transform: translateY(0); opacity: 1; }
.mnav-menu-title {
  margin: 4px 0 10px;
  font-size: .85rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-align: center;
  color: var(--gold);
}
.mnav-menu-item {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 12px;
  padding: 13px 14px;
  border-radius: var(--radius);
  color: var(--text-primary);
  text-decoration: none;
  font-size: 1rem;
  white-space: nowrap;
  transition: background .15s ease;
}
.mnav-menu-item .mnav-ico {
  flex: 0 0 22px;
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--gold);
}
@media (hover: hover) { .mnav-menu-item:hover { background: rgba(201, 166, 96, 0.08); } }
.mnav-menu-item:active { background: rgba(201, 166, 96, 0.14); }

@media (max-width: 768px) {
  body.mnav-ready .mnav { display: flex; }
  /* Верхняя auth-шапка на мобильном скрыта — её заменяет нижняя панель.
     Admin сохраняет #logoutBtn и свою :has(#logoutBtn) логику (не трогаем). */
  .header:has(.header-nav--app) { display: none; }
  /* Отступы: сверху safe-area (шапки нет), снизу — клиренс под панель. */
  body.has-bottom-nav .container,
  body.has-bottom-nav .container-wide,
  body.has-bottom-nav .container-narrow {
    /* На app-экранах .header скрыт (:has(.header-nav--app)), max()-гейт в .header тут
       мёртв — верхний отступ даёт ТОЛЬКО это правило. Берём max(env, --safe-top),
       иначе на заходе по пушу (env transient-0) контент под часами. */
    padding-top: calc(max(env(safe-area-inset-top, 0px), var(--safe-top, 0px)) + 16px);
    padding-bottom: calc(max(env(safe-area-inset-bottom, 0px), var(--safe-bottom, 0px)) + 84px);
  }
  body.has-bottom-nav .msg-conv-list {
    padding-bottom: calc(max(env(safe-area-inset-bottom, 0px), var(--safe-bottom, 0px)) + 84px);
  }
  /* Тост садился ровно на нижнюю панель: на 4 секунды кнопки навигации
     переставали нажиматься (у тоста z-index 9999 и pointer-events: auto). */
  body.has-bottom-nav #app-toasts {
    bottom: calc(max(env(safe-area-inset-bottom, 0px), var(--safe-bottom, 0px)) + 80px);
  }
  /* /article: сохраняем safe-area (контент не за камеру), но режем лишний
     отступ (+16 → +4). Специфичность 0,3,0 перебивает общее правило выше. */
  body.has-bottom-nav .container-wide:has(.article-back-btn) {
    padding-top: calc(max(env(safe-area-inset-top, 0px), var(--safe-top, 0px)) + 4px);
  }
}
/* В открытом диалоге мессенджера панель скрыта (не перекрывает поле ввода). */
body.msg-chat-mobile-open .mnav { display: none; }

@media (prefers-reduced-motion: reduce) {
  .mnav-menu-overlay, .mnav-menu { transition: none; }
}

/* =====================================================================
   Минималистичные формы входа / регистрации / сброса пароля.
   Чёрный фон, золотые канты полей, белый текст, без рамок.
   Добавлено отдельным блоком в конце файла (override .card без
   правки исходного правила; никаких comma-list дописываний).
   ===================================================================== */

/* Часть 7 — снимаем рамку/фон/тень карточки → «просто чёрный фон». */
.card-borderless {
  background: transparent;
  border: none;
  box-shadow: none;
  padding: 8px 0 0;
}

/* Опциональная центрирующая обёртка (forgot-password). */
.auth-minimal {
  min-height: calc(100vh - 160px);
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* Часть 2 — глазок показа пароля. */
.input-with-toggle {
  position: relative;
}
.input-with-toggle .form-control {
  padding-right: 46px;
}
.pw-toggle-btn {
  position: absolute;
  top: 50%;
  right: 8px;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  border-radius: 6px;
  transition: color 0.2s ease;
}
.pw-toggle-btn:hover {
  color: var(--gold);
}
.pw-toggle-btn:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 1px;
}

/* Часть 6 — gold-outline кнопки в шапке (Войти / Регистрация / Забыли пароль). */
.btn-outline-gold {
  display: inline-flex;
  align-items: center;
  padding: 8px 16px;
  border: 1px solid var(--gold);
  border-radius: 6px;
  color: var(--text-primary);
  font-size: 0.9rem;
  line-height: 1;
  white-space: nowrap;
  background: transparent;
  transition: background 0.2s ease, color 0.2s ease;
}
.header-nav a.btn-outline-gold:hover,
.btn-outline-gold:hover {
  background: rgba(201, 166, 96, 0.12);
  color: var(--gold-light);
}

/* Часть 3 — минималистичный админ-логин: полностью чёрный экран,
   только золотые канты полей, без подписей/лого. */
.admin-minimal {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding: 24px;
  background: var(--bg-primary);
}
.admin-minimal .admin-field {
  width: 100%;
  max-width: 320px;
}
.admin-minimal .form-control {
  text-align: center;
  padding: 14px 18px;
  font-size: 1rem;
  letter-spacing: 0.3px;
  border-color: var(--gold);
}
.admin-minimal .form-control:focus {
  border-color: var(--gold-light);
  box-shadow: 0 0 0 3px rgba(201, 166, 96, 0.18);
}
.admin-minimal #adminPwGroup.hidden {
  display: none;
}
.admin-minimal .alert {
  max-width: 320px;
  width: 100%;
  text-align: center;
}

/* Часть 8 — выпадающее меню автоподсказок (должность / компания). */
.ac-wrap {
  position: relative;
}
.ac-menu {
  position: absolute;
  z-index: 50;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  background: var(--bg-secondary);
  border: 1px solid var(--gold);
  border-radius: var(--radius-sm);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
  overflow: hidden;
  max-height: 280px;
  overflow-y: auto;
}
.ac-menu[hidden] {
  display: none;
}
.ac-item {
  padding: 10px 14px;
  font-size: 0.92rem;
  color: var(--text-primary);
  cursor: pointer;
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.ac-item:hover,
.ac-item--active {
  background: rgba(201, 166, 96, 0.14);
  color: var(--gold-light);
}
.ac-item-count {
  margin-left: auto;
  font-size: 0.75rem;
  color: var(--text-muted);
}
.ac-item--use {
  border-top: 1px solid var(--border);
  color: var(--text-secondary);
  font-size: 0.85rem;
}
.ac-item--use strong {
  color: var(--gold);
  font-weight: 600;
}

/* Часть 10 — мастер регистрации: индикатор шагов, шаги, навигация,
   «?»-подсказка, опциональные подблоки. */
.reg-steps {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-bottom: 24px;
}
.reg-step-dot {
  width: 28px;
  height: 4px;
  border-radius: 2px;
  background: rgba(201, 166, 96, 0.22);
  transition: background 0.25s ease;
}
.reg-step-dot.is-done {
  background: rgba(201, 166, 96, 0.55);
}
.reg-step-dot.is-active {
  background: var(--gold);
}
.reg-step {
  display: none;
}
.reg-step.is-active {
  display: block;
  animation: fadeIn 0.3s ease;
}
.reg-step-title {
  font-size: 1.15rem;
  font-weight: 600;
  margin-bottom: 4px;
  color: var(--text-primary);
}
.reg-step-sub {
  font-size: 0.88rem;
  color: var(--text-secondary);
  margin-bottom: 20px;
}
.reg-nav {
  display: flex;
  gap: 12px;
  margin-top: 8px;
}
.reg-nav .btn {
  flex: 1;
}
.reg-nav .btn-back {
  flex: 0 0 auto;
  min-width: 96px;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-secondary);
}
.reg-nav .btn-back:hover {
  border-color: var(--gold);
  color: var(--gold);
}

/* Label со встроенной «?»-подсказкой. */
.label-with-hint {
  display: flex;
  align-items: center;
  gap: 6px;
}
.field-hint {
  position: relative;
  display: inline-flex;
}
.field-hint-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 1px solid var(--gold);
  color: var(--gold);
  font-size: 0.72rem;
  line-height: 1;
  cursor: help;
  background: none;
  padding: 0;
}
.field-hint-tip {
  position: absolute;
  z-index: 60;
  left: 50%;
  bottom: calc(100% + 8px);
  transform: translateX(-50%);
  width: 240px;
  padding: 10px 12px;
  background: var(--bg-card);
  border: 1px solid var(--gold);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  font-size: 0.8rem;
  font-weight: 400;
  line-height: 1.45;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
}
.field-hint-tip[hidden] {
  display: none;
}

/* Кнопка «Указать ex.» рядом с полем компании. */
.ex-btn {
  margin-top: 8px;
  padding: 6px 12px;
  font-size: 0.82rem;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-secondary);
  cursor: pointer;
  font-family: inherit;
  transition: var(--transition);
}
.ex-btn:hover {
  border-color: var(--gold);
  color: var(--gold);
}

/* Шаг «Фото» — превью аватара + кнопка «Позже». */
.reg-avatar-area {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  margin-bottom: 8px;
}
/* Квадрат со скруглёнными углами — как аватар в /settings
   (.avatar-circle-inner: 120×120, border-radius 12px, кант 2px). */
.reg-avatar-preview {
  width: 120px;
  height: 120px;
  border-radius: 12px;
  border: 2px solid rgba(201, 166, 96, 0.3);
  object-fit: cover;
  background: var(--bg-card);
}
.reg-avatar-placeholder {
  width: 120px;
  height: 120px;
  border-radius: 12px;
  border: 2px solid rgba(201, 166, 96, 0.3);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  cursor: pointer;
  background: var(--bg-card);
  transition: border-color 0.2s;
}
.reg-avatar-placeholder:hover { border-color: rgba(201, 166, 96, 0.7); }
/* [hidden] на .reg-avatar-placeholder перебивается display:flex выше —
   поэтому после выбора фото оставался «второй слот». Явный override. */
.reg-avatar-preview[hidden],
.reg-avatar-placeholder[hidden] { display: none; }

/* =============================================================================
   Конференции 2.0 (C1-3) — /my-conferences (карточки) + /conference/:id
   ============================================================================= */

/* Минималистичная кликабельная карточка конференции */
.mc-card {
  display: flex; gap: 14px; align-items: flex-start;
  background: var(--bg-card, #121214); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 14px 16px; margin-bottom: 12px;
  cursor: pointer; transition: var(--transition);
}
.mc-card:hover { border-color: var(--gold); }
.mc-card-icon { color: var(--gold); flex-shrink: 0; display: flex; padding-top: 2px; }
.mc-card-icon:has(.mc-card-logo) { padding-top: 0; }
.mc-card-logo { width: 40px; height: 40px; border-radius: 9px; object-fit: cover; display: block; }
.confe-logo-preview { width: 56px; height: 56px; border-radius: 10px; background: var(--bg-input); border: 1px solid var(--border); overflow: hidden; flex-shrink: 0; }
.confe-logo-preview img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Программа участником (C6/C10) — глобально (используется и на странице конфы, и в
   предпросмотре конструктора программы в админке). Перенесено из spa-shell. */
.cd-prog-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 16px; }
.cd-prog-list { display: flex; flex-direction: column; gap: 4px; }
.cd-prog-block.cd-prog-cur { background: rgba(201,166,96,0.08); border-radius: 8px; padding: 0 8px;
  box-shadow: 0 0 0 1px rgba(201,166,96,0.5) inset; }
.cd-prog-block.cd-prog-past { opacity: 0.55; }
.cd-prog-now { display: inline-block; font-size: 0.7rem; letter-spacing: 0.05em; color: var(--gold);
  border: 1px solid rgba(201,166,96,0.5); border-radius: 6px; padding: 1px 7px; margin: 8px 0 2px; }
.cd-prog-extra { display: flex; flex-wrap: wrap; gap: 8px; padding: 0 0 8px; }
/* Линия под заголовком раздела — заметное золото (правка Ильи 2026-08-01):
   прежний --border (золото 20%) на чёрном был неразличим. */
.cd-prog-sess { display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin: 18px 0 8px; padding-bottom: 6px; border-bottom: 1px solid rgba(201,166,96,0.55); }
/* Время раздела — в той же левой золотой колонке, что у тем (см. sessHead). */
/* flex:1 + min-width:0 на ОБОИХ уровнях: без этого длинный заголовок раздела не сжимался
   ниже своей min-content и наползал на кнопку «+ Предложить тему» (замерено 62px на 390px,
   92px на 360px). Тот же дефект уже чинили этажом ниже у .cd-prog-theme. */
.cd-prog-sess-main { display: flex; align-items: baseline; gap: 12px; flex: 1; min-width: 0; }
.cd-prog-sess-t { font-size: 1.02rem; font-weight: 600; color: var(--text-primary);
  min-width: 0; overflow-wrap: anywhere; }
/* Перерыв обособлен двумя тонкими золотыми линиями; текст белый, как у тем
   (правка Ильи 2026-08-01) — серым он читался как второстепенный. */
.cd-prog-break { display: flex; gap: 12px; align-items: baseline; color: var(--text-primary);
  font-size: 0.9rem; padding: 10px 0; margin: 8px 0;
  border-top: 1px solid rgba(201,166,96,0.45); border-bottom: 1px solid rgba(201,166,96,0.45); }
.cd-prog-break-t { min-width: 0; }
/* Линия между темами — то же золото, но слабее: иначе список рябит. */
.cd-prog-slot, .cd-prog-dslot { display: flex; align-items: flex-start; justify-content: space-between;
  gap: 12px; padding: 10px 0; border-bottom: 1px solid rgba(201,166,96,0.18); }
.cd-prog-dslot { padding-left: 14px; }
.cd-prog-slot-main { display: flex; gap: 12px; flex: 1; min-width: 0; }
.cd-prog-time { color: var(--gold); font-size: 0.88rem; white-space: nowrap; flex: none; min-width: 92px; }
/* min-width:0 обязателен: без него flex-элемент не сжимается ниже min-content
   своего текста и на телефоне тема наползала на кнопки лайков (замер 2026-08-01:
   нахлёст до 50px). Принудительный перенос НЕ ставим — он рвал слова посередине
   («квалифицирова/нного»); по пробелам текст переносится сам. */
.cd-prog-theme { color: var(--text-primary); min-width: 0; }
.cd-prog-spk { font-size: 0.85rem; margin-top: 2px; }
/* ФИО · должность · компания — три цвета, эталон автора статьи (.dash-article-*). */
.cd-prog-p-name { color: rgb(201,166,96); font-weight: 600; }
.cd-prog-p-pos { color: var(--text-primary); }
.cd-prog-p-org { color: rgba(201,166,96,0.7); }
.cd-prog-p-sep { color: var(--text-muted); margin: 0 5px; }
/* Модератор сессии/дискуссии (правка 2026-06-23) */
.cd-prog-mod { font-size: 0.88rem; margin-top: 4px; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.cd-prog-mod-l { color: var(--text-muted); }
.cd-votes { display: flex; gap: 6px; flex: none; }
.cd-vote { display: inline-flex; align-items: center; gap: 5px; padding: 4px 9px; border-radius: 8px;
  border: 1px solid var(--border); background: none; color: var(--text-secondary); cursor: pointer; }
.cd-vote:hover { border-color: var(--gold); color: var(--gold); }
.cd-vote--on { border-color: var(--gold); color: var(--gold); background: rgba(201,166,96,0.1); }
.cd-vote-n { font-size: 0.82rem; }
.cd-propose-btn { flex: none; }

/* Предпросмотр программы в конструкторе (модалка) */
.pg-preview-modal { max-width: 640px; width: 92vw; max-height: 86vh; overflow: auto; }
.pg-preview-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.cd-prog-wrap { margin-top: 4px; }
/* Фото контакта: в карточке «Моего списка» и в модалке участника (2026-08-01).
   Кликабельная обёртка — кнопка, поэтому гасим её собственный фон и рамку. */
.cd-ml-ava,
.cp-modal-ava {
  flex: none;
  padding: 0;
  border: 1px solid rgba(201, 166, 96, 0.25);
  background: #0f0f12;
  border-radius: 10px;
  overflow: hidden;
  line-height: 0;
  cursor: zoom-in;
}
.cd-ml-ava--empty,
.cp-modal-ava--empty { cursor: default; }
.cd-ml-ava img,
.cp-modal-ava img { display: block; width: 100%; height: 100%; object-fit: cover; }
.cd-ml-ava { width: 44px; height: 44px; }
.cp-modal-ava { width: 72px; height: 72px; border-radius: 12px; }

/* C2-3: фильтр по темам в каталоге «Все» */
.mc-filter-bar { margin-bottom: 12px; }
.mc-topics-panel { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px;
  padding: 12px; border: 1px solid var(--border); border-radius: var(--radius); }
.mc-loadmore { text-align: center; margin: 16px 0 4px; }
.mc-card-body { flex: 1; min-width: 0; }
.mc-card-top { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 4px; }
.mc-card-name { color: var(--text-primary); font-weight: 500; }
.mc-card-meta { color: var(--text-muted); font-size: 0.85rem; }
.mc-card-actions { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }

/* Статус-бейдж (общий для my-conferences + conference-detail) */
.conf-status-badge {
  display: inline-flex; align-items: center; gap: 6px; padding: 2px 10px;
  border-radius: 999px; font-size: 0.78rem; white-space: nowrap;
}
.conf-status-dot { width: 7px; height: 7px; border-radius: 50%; }
.conf-st-draft { background: rgba(150,150,150,0.15); color: var(--text-muted); }
.conf-st-draft .conf-status-dot { background: rgb(150,150,150); }
.conf-st-published { background: rgba(90,140,210,0.15); color: rgb(140,180,235); }
.conf-st-published .conf-status-dot { background: rgb(110,160,225); }
.conf-st-registration_open { background: rgba(201,166,96,0.15); color: var(--gold); }
.conf-st-registration_open .conf-status-dot { background: var(--gold); }
.conf-st-live { background: rgba(90,190,120,0.15); color: rgb(130,210,150); }
.conf-st-live .conf-status-dot { background: rgb(110,200,135); }
.conf-st-finished { background: rgba(120,120,140,0.15); color: rgb(165,165,185); }
.conf-st-finished .conf-status-dot { background: rgb(150,150,170); }
.conf-st-cancelled { background: rgba(210,90,90,0.15); color: rgb(230,140,140); }
.conf-st-cancelled .conf-status-dot { background: rgb(220,110,110); }

/* Страница конференции /conference/:id */
.cd-head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; }
.cd-title { margin: 0; font-size: 1.4rem; }
.confc-tabs { display: flex; flex-wrap: wrap; gap: 4px; border-bottom: 1px solid var(--border); margin-bottom: 20px; }
.confc-tab {
  padding: 10px 16px; background: none; border: none; border-bottom: 2px solid transparent;
  color: var(--text-secondary); cursor: pointer; font-size: 0.9rem; font-family: inherit;
}
.confc-tab.active { color: var(--gold); border-bottom-color: var(--gold); }
.cd-info-head { display: flex; gap: 16px; align-items: flex-start; margin-bottom: 16px; }
.cd-logo { color: var(--gold); flex-shrink: 0; display: flex; }
.cd-meta { flex: 1; min-width: 0; }
.cd-meta-row { font-size: 0.9rem; margin-bottom: 6px; color: var(--text-secondary); }
.cd-meta-label { color: var(--text-muted); }
.cd-desc { color: var(--text-secondary); line-height: 1.7; margin: 16px 0; white-space: pre-wrap; overflow-wrap: break-word; }
.cd-actions { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; margin-top: 16px; }
.cd-registered { color: rgb(130,210,150); font-size: 0.9rem; }
/* C2-3: org рядом с лого, инвайт-блоки, рендер лендинга */
.cd-info-head { align-items: center; }
.cd-logo-img { width: 56px; height: 56px; border-radius: 10px; object-fit: cover; }
.cd-head-org { font-size: 1.05rem; color: var(--text-primary); font-weight: 500; }
.cd-statusinfo { margin-bottom: 14px; }
.cd-invite { margin: 14px 0; }
.cd-invite .cd-actions { margin-top: 0; }
.cd-landing { margin-top: 18px; }
/* Типографика лендинга = типографика статьи (решение Ильи 2026-08-01). Раньше
   текст и подзаголовок шли --text-secondary: на чёрном фоне лендинг читался
   выцветшей копией статьи. Значения дословно с .article-block-* (строки ~2991),
   включая ритм блоков 24px и золотую линию под заголовком. */
.cl-h2 {
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--text-primary);
  line-height: 1.4;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(201, 166, 96, 0.2);
  margin: 24px 0 12px;
}
/* Подзаголовок — младший брат заголовка: та же семья, мельче, без золотой линии. */
.cl-h3 {
  font-size: 1.02rem;
  font-weight: 600;
  color: var(--text-primary);
  line-height: 1.45;
  margin: 24px 0 8px;
}
.cl-text {
  font-size: 0.95rem;
  line-height: 1.8;
  color: var(--text-primary);
  white-space: pre-wrap;
  overflow-wrap: break-word; /* длинный URL не даёт горизонтальный скролл */
  margin: 0 0 24px;
}
.cl-text a {
  color: var(--gold);
  text-decoration: underline;
}
.cl-img {
  max-width: 100%;
  border-radius: 12px;
  display: block;
  margin: 0 auto 24px;
}
/* Карусель: сама .acar самодостаточна (своя высота и фон), обёртка нужна
   только ради вертикального ритма — того же, что у .cl-img. */
.cl-carousel { margin: 0 0 24px; }
.cl-video { margin: 0 0 24px; }
/* Первый блок не отодвигаем — у .cd-landing свой отступ сверху. */
.cd-landing > :first-child { margin-top: 0; }
.cl-buttons { display: flex; flex-wrap: wrap; gap: 10px; margin: 16px 0; }

/* #3 (2026-06-24): пикер менеджера/ответственного — поиск вместо общего списка (общий компонент) */
.confe-mgr-pick, .mgr-pick-container { position: relative; }
.mgr-chip { display: inline-flex; align-items: center; gap: 8px; max-width: 100%;
  background: var(--surface-2, #1b1b1f); border: 1px solid var(--border, #26262b);
  border-radius: 999px; padding: 6px 6px 6px 14px; }
.mgr-chip span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mgr-chip-x { flex: none; width: 24px; height: 24px; border-radius: 50%; border: 0; cursor: pointer;
  background: var(--surface-1, #121214); color: var(--text-secondary, #aaa); font-size: 0.8rem; line-height: 1; }
.mgr-chip-x:hover { color: #e06464; }
.mgr-results { position: absolute; left: 0; right: 0; z-index: 30; margin-top: 4px;
  background: var(--surface-1, #121214); border: 1px solid var(--border, #26262b);
  border-radius: 10px; max-height: 240px; overflow-y: auto; box-shadow: 0 8px 24px rgba(0,0,0,.4); }
.mgr-res-item { display: block; width: 100%; text-align: left; border: 0; cursor: pointer;
  background: transparent; color: var(--text, #eee); padding: 9px 12px; font-size: 0.9rem; }
.mgr-res-item:hover { background: var(--surface-2, #1b1b1f); }
.mgr-res-empty { padding: 9px 12px; color: var(--text-muted, #888); font-size: 0.86rem; }

/* ============ Видео-блок статей (2026-07-07) ============ */
/* Адаптивная 16:9 обёртка встроенного плеера (VK/YouTube/Rutube). */
.article-video-frame {
  position: relative;
  width: 100%;
  padding-top: 56.25%;
  border-radius: 12px;
  overflow: hidden;
  background: #0a0a0c;
}
.article-video-frame iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}
/* Ссылка-вложение в тексте статьи. */
.article-block-text a,
.block-text-input a {
  color: var(--gold, rgb(201, 166, 96));
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* ===== Карусель картинок: редактор (article-blocks.js, 2026-07-08) ===== */
.block-image-frames {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.bif-drop {
  width: 100%;
  border: 1.5px dashed rgba(201, 166, 96, 0.35);
  border-radius: 8px;
  padding: 22px 14px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  cursor: pointer;
}
.bif-dragover .bif-drop,
.bif-dragover .block-image-frames {
  outline: 2px dashed rgba(201, 166, 96, 0.7);
  outline-offset: 3px;
  border-radius: 8px;
}
.bif-thumb {
  position: relative;
  width: 96px;
  height: 96px;
  border-radius: 8px;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.04);
}
.bif-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.bif-btns {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  justify-content: center;
  gap: 4px;
  padding: 3px;
  background: linear-gradient(transparent, rgba(0, 0, 0, 0.65));
}
.bif-btns button {
  border: 0;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  width: 24px;
  height: 22px;
  border-radius: 5px;
  cursor: pointer;
  font-size: 0.8rem;
  line-height: 1;
}
.bif-btns button:disabled {
  opacity: 0.35;
  cursor: default;
}
.bif-add {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  border: 1.5px dashed rgba(201, 166, 96, 0.35);
  background: none;
  color: var(--text-secondary, #999);
  cursor: pointer;
  font-size: 1.3rem;
  line-height: 1;
  gap: 2px;
}
.bif-add span {
  font-size: 0.68rem;
}
.bif-spinner {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 22px;
  height: 22px;
  border: 2.5px solid rgba(201, 166, 96, 0.25);
  border-top-color: rgba(201, 166, 96, 0.9);
  border-radius: 50%;
  animation: bifspin 0.8s linear infinite;
}
@keyframes bifspin {
  to { transform: rotate(360deg); }
}
.bif-progress {
  width: 100%;
  font-size: 0.78rem;
  color: var(--text-secondary, #999);
}
.bif-count {
  font-weight: 400;
  color: var(--text-secondary, #999);
}

/* ===== Карусель картинок: статья (article.js) ===== */
.acar {
  position: relative;
  height: min(480px, 62vw);
  background: rgba(255, 255, 255, 0.03);
  border-radius: 10px;
}
.acar-track {
  display: flex;
  height: 100%;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  border-radius: 10px;
}
.acar-track::-webkit-scrollbar {
  display: none;
}
.acar-slide {
  flex: 0 0 100%;
  height: 100%;
  scroll-snap-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
}
.acar-slide img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}
.acar-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 0;
  background: rgba(0, 0, 0, 0.45);
  color: #fff;
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2;
}
.acar-prev { left: 10px; }
.acar-next { right: 10px; }
.acar-nav:hover { background: rgba(0, 0, 0, 0.65); }
.acar-count {
  position: absolute;
  top: 10px;
  right: 12px;
  background: rgba(0, 0, 0, 0.5);
  color: #fff;
  font-size: 0.75rem;
  padding: 2px 8px;
  border-radius: 10px;
  z-index: 2;
}
.acar-dots {
  position: absolute;
  bottom: 8px;
  left: 0;
  right: 0;
  display: flex;
  justify-content: center;
  gap: 5px;
  z-index: 2;
  pointer-events: none;
}
.acar-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.4);
}
.acar-dot.active {
  background: rgba(255, 255, 255, 0.95);
}
@media (max-width: 600px) {
  .acar-nav { display: none; } /* мобайл: свайп; точки+счётчик показывают листаемость */
}

/* ===== Нативка iOS (12.2i): подъём полей ввода над клавиатурой =====
   kb-open ставит native-shim по keyboardWillShow (только приложение, iOS).
   Отступ снизу на высоту клавиатуры даёт документу место для подскролла к
   сфокусированному полю у низа страницы (комментарии, формы) — иначе
   документу некуда скроллиться и клавиатура накрывает поле. Довод поля в
   видимую зону делает шим (scrollIntoView по keyboardWillShow). На /messages
   документ не прокручивается (внутренний скролл + замок в шиме) — правило
   безвредно. Веб и Android не затронуты: kb-open там не ставится. */
html.cap-ios.kb-open body {
  padding-bottom: var(--keyboard-height, 0px);
}

/* ===== BlurHash-плейсхолдеры (Фаза 2 плавности) =====
   Контейнер с data-blurhash красится размытой превьюшкой (blurhash-client),
   картинка внутри плавно проявляется по load. На <img> с собственным
   data-blurhash (вложения чата) фейд не вешается — фон на самом элементе. */
img.cg-blur-img {
  opacity: 0;
  transition: opacity 0.22s ease;
}
img.cg-blur-img.cg-blur-loaded {
  opacity: 1;
}

/* ===== Индикатор соединения (Фаза 8 плавности, только приложение) =====
   Минималистичная плашка сверху: «Соединение…» + спиннер / «Нет подключения
   к интернету». Выезжает из-за верхней кромки, уважает сейф-зону выреза. */
.cg-conn-banner {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1500;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: calc(env(safe-area-inset-top, 0px) + 8px) 16px 8px;
  background: #121214;
  border-bottom: 1px solid rgba(201, 166, 96, 0.35);
  color: var(--text-secondary);
  font-size: 0.82rem;
  transform: translateY(-100%);
  transition: transform 0.25s ease;
  pointer-events: none;
}
.cg-conn-banner--show {
  transform: translateY(0);
}
.cg-conn-banner--offline .cg-conn-spinner {
  display: none;
}
.cg-conn-spinner {
  width: 12px;
  height: 12px;
  flex: none;
  border-radius: 50%;
  border: 2px solid rgba(201, 166, 96, 0.25);
  border-top-color: rgb(201, 166, 96);
  animation: cgConnSpin 0.8s linear infinite;
}
@keyframes cgConnSpin {
  to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  .cg-conn-banner { transition: none; }
  .cg-conn-spinner { animation-duration: 1.6s; }
}

/* ===== Pull-to-refresh лент (Фаза 9 плавности, только приложение) ===== */
.cg-ptr {
  position: fixed;
  top: calc(env(safe-area-inset-top, 0px) + 8px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 1400;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: #121214;
  border: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
}
.cg-ptr-spinner {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 2px solid rgba(201, 166, 96, 0.25);
  border-top-color: rgb(201, 166, 96);
}
.cg-ptr--armed .cg-ptr-spinner {
  border-color: rgb(201, 166, 96);
  border-top-color: rgba(201, 166, 96, 0.25);
}
.cg-ptr--busy {
  transition: transform 0.15s ease, opacity 0.15s ease;
}
.cg-ptr--busy .cg-ptr-spinner {
  animation: cgConnSpin 0.8s linear infinite;
}

/* ===== Полноэкранный просмотр картинок с зумом (common/image-viewer.js) ===== */
.cgiv-overlay {
  position: fixed;
  inset: 0;
  z-index: 1300;
  background: rgba(0, 0, 0, 0.96);
  overflow: hidden;
  animation: cgivFadeIn 0.16s ease-out;
  touch-action: none;
}
@keyframes cgivFadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.cgiv-track {
  display: flex;
  height: 100%;
  width: 100%;
  will-change: transform;
}
.cgiv-slide {
  flex: 0 0 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.cgiv-img {
  max-width: 100%;
  max-height: 100%;
  user-select: none;
  -webkit-user-select: none;
  will-change: transform;
}
.cgiv-btn {
  position: absolute;
  top: calc(14px + env(safe-area-inset-top, 0px));
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(18, 18, 20, 0.72);
  border: 1px solid rgba(255, 255, 255, 0.12);
  color: #fff;
  cursor: pointer;
  z-index: 3;
}
.cgiv-close { right: 14px; }
.cgiv-download { left: 14px; }
.cgiv-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 46px;
  height: 46px;
  display: none;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(18, 18, 20, 0.72);
  border: 1px solid rgba(255, 255, 255, 0.12);
  color: #fff;
  cursor: pointer;
  z-index: 3;
}
.cgiv-arrow--prev { left: 14px; }
.cgiv-arrow--next { right: 14px; }
@media (hover: hover) and (pointer: fine) {
  .cgiv-arrow { display: flex; }
}
.cgiv-name {
  position: absolute;
  left: 16px;
  right: 16px;
  bottom: calc(40px + env(safe-area-inset-bottom, 0px));
  text-align: center;
  color: rgba(255, 255, 255, 0.85);
  font-size: 0.85rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  pointer-events: none;
  z-index: 2;
}
.cgiv-counter {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  text-align: center;
  color: rgba(255, 255, 255, 0.75);
  font-size: 0.85rem;
  pointer-events: none;
  z-index: 2;
}
/* Тап-навигация картинок статей и лендинга конфы — курсор на десктопе. */
.article-block-image img,
.acar-slide img,
.article-hero,
.cl-img { cursor: zoom-in; }

/* ===== Плашка «установить приложение» (app-banner.js) =====
   Своя, одна на iOS и Android: системный Smart App Banner рисуется стилями Apple и
   на Android аналога не имеет. Стоит первым элементом body В ПОТОКЕ — липкая шапка
   остаётся липкой, а высота документа меняется до восстановления скролла. */
.appbnr {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  background: var(--surface-1, #121214);
  border-bottom: 1px solid rgba(201, 166, 96, 0.28);
}
.appbnr-ico {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  flex: 0 0 auto;
  border-radius: 10px;
  color: rgb(20, 18, 14);
  background: var(--gold-gradient);
}
.appbnr-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.appbnr-txt b {
  font-size: 0.88rem;
  font-weight: 600;
  /* Заголовок обязан жить в одну строку: с переносом плашка занимала 90 px — почти
     десятую часть экрана телефона. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.appbnr-sub {
  font-size: 0.72rem;
  color: var(--text-secondary, #aaa);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.appbnr-go {
  margin-left: auto;
  flex: 0 0 auto;
  padding: 6px 12px;
  border-radius: 8px;
  font-size: 0.82rem;
  white-space: nowrap;
  font-weight: 600;
  color: rgb(20, 18, 14);
  background: var(--gold-gradient);
  text-decoration: none;
}
.appbnr-x {
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--text-muted, #888);
  cursor: pointer;
}
.appbnr-x:hover { color: var(--gold-light, rgb(227, 200, 140)); }
/* Плашка нужна только на телефонах — на широком экране установить нечего. */
@media (min-width: 768px) {
  .appbnr { display: none; }
}
