/* ================================================================
   Speech Annotator — app.css
   Palette: neutral grays, accent #2563eb (blue-600)
   ================================================================ */

@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500&display=swap');

:root {
  /* ---- Brand blue: интерактив (CTA/ссылки/фокус/актив), НЕ большие заливки ---- */
  --accent:          #2563eb;
  --accent-hover:    #1d4ed8;
  --accent-strong:   #1e40af;   /* текст-ссылки на светлом, где нужен контраст */
  --accent-soft:     #eef2ff;   /* тонированная поверхность (индиго-подложка) */
  --accent-light:    var(--accent-soft);  /* legacy-алиас: не удаляем, чтобы не ломать вызовы */
  --accent-2:        #6366f1;   /* индиго — партнёр по градиенту / вторичный */

  /* ---- Тёплый вторичный (энергия / активность) ---- */
  --warm:            #f59e0b;
  --warm-strong:     #c2410c;
  --warm-soft:       #fff7ed;

  /* ---- Статусы ---- */
  --success:         #16a34a;   --success-soft: #dcfce7;
  --warning:         #d97706;   --warning-soft: #fff7ed;
  --danger:          #dc2626;   --danger-soft:  #fef2f2;

  /* ---- Нейтрали — чуть теплее и мягче ---- */
  --sidebar-width:   240px;
  --sidebar-bg:      #ffffff;
  --body-bg:         #f5f5f7;   /* было #f3f4f6 (холодный) */
  --card-bg:         #ffffff;
  --surface-2:       #f8fafc;   /* приглушённая подложка панелей/фильтров */
  --surface-sunken:  #fafafa;   /* «утопленные» полоски: шапки карточек, hover */
  --surface-sunken-2:#fcfcfd;   /* тело раскрытой карточки датасета */
  --hover-bg:        #eef0f3;   /* мягкий hover для nav / строк */
  --chip-bg:         #f3f4f6;   /* нейтральный чип/пилюля */
  --chip-text:       #6b7280;
  --text-primary:    #111827;
  --text-secondary:  #6b7280;
  --text-muted:      #9ca3af;
  --border:          #e8e8ec;   /* мягче, менее «линованно» */
  --border-input:    #d1d5db;
  --sidebar-border:  var(--border);

  /* ---- Тени — мягче ---- */
  --shadow-sm:       0 1px 2px rgba(17,24,39,.05), 0 1px 3px rgba(17,24,39,.06);
  --shadow:          0 4px 12px rgba(17,24,39,.07);

  /* ---- Геометрия — крупнее ---- */
  --radius:          12px;      /* было 8 */
  --radius-sm:       8px;       /* было 4 */
  --radius-pill:     999px;

  --font-mono:       'IBM Plex Mono', 'Consolas', 'Courier New', monospace;

  /* ---- Градиенты как токены ---- */
  --grad-primary:    linear-gradient(135deg, #2563eb, #6366f1);
  --grad-warm:       linear-gradient(90deg, #f97316, #f59e0b);
  --grad-success:    linear-gradient(90deg, #16a34a, #22c55e);

  /* Segment region colors */
  --seg-spk1:  rgba(37,  99, 235, .22);
  --seg-spk2:  rgba(249, 115,  22, .22);
  --seg-spk3:  rgba(22,  163,  74, .22);
  --seg-event: rgba(107, 114, 128, .18);
}

/* ================================================================
   Тёмная тема — ЗАДЕЛ (opt-in через data-theme="dark").
   Намеренно НЕ на prefers-color-scheme: активируется только когда
   появится переключатель, иначе dark включился бы у всех сразу и
   недотестированным (осциллограмма/спектрограмма имеют свой тёмный
   холст #0b1021, требуют отдельной выверки). Переопределяем только
   нейтрали и тонированные подложки — акценты/градиенты те же.
   ================================================================ */
:root[data-theme="dark"] {
  --accent-soft:     rgba(99, 102, 241, .18);
  --warm-soft:       rgba(245, 158, 11, .15);
  --success-soft:    rgba(22, 163, 74, .18);
  --warning-soft:    rgba(217, 119, 6, .15);
  --danger-soft:     rgba(220, 38, 38, .16);

  --sidebar-bg:      #14171d;
  --body-bg:         #0f1115;
  --card-bg:         #181b22;
  --surface-2:       #1f232c;
  --surface-sunken:  #1c2029;
  --surface-sunken-2:#171a21;
  --hover-bg:        #232833;
  --chip-bg:         #262b35;
  --chip-text:       #9ca3af;
  --text-primary:    #e5e7eb;
  --text-secondary:  #9ca3af;
  --text-muted:      #6b7280;
  --border:          #2a2f3a;
  --border-input:    #3a4150;

  --shadow-sm:       0 1px 2px rgba(0,0,0,.4), 0 1px 3px rgba(0,0,0,.5);
  --shadow:          0 4px 12px rgba(0,0,0,.5);
}

/* ---- Тёмная тема: точечные оверрайды кастомных компонентов, которые Bootstrap
   (data-bs-theme) не трогает — цветные бейджи/чипы статусов и календарь.
   Светлая подложка + тёмный текст → тёмная тонировка + светлый текст. ---- */
:root[data-theme="dark"] .status-approved,
:root[data-theme="dark"] .stage-green   { background: rgba(22,163,74,.20);  color: #4ade80; }
:root[data-theme="dark"] .status-rejected,
:root[data-theme="dark"] .stage-red     { background: rgba(220,38,38,.20);  color: #f87171; }
:root[data-theme="dark"] .status-in-progress,
:root[data-theme="dark"] .stage-blue    { background: rgba(37,99,235,.22);  color: #93c5fd; }
:root[data-theme="dark"] .status-pending,
:root[data-theme="dark"] .stage-yellow  { background: rgba(234,179,8,.18);  color: #fde047; }
:root[data-theme="dark"] .status-partial,
:root[data-theme="dark"] .stage-amber   { background: rgba(245,158,11,.18); color: #fbbf24; }
:root[data-theme="dark"] .chunk-type-vad   { background: rgba(99,102,241,.22); color: #a5b4fc; }
:root[data-theme="dark"] .chunk-type-full  { background: rgba(236,72,153,.20); color: #f9a8d4; }
:root[data-theme="dark"] .speaker-badge.has-meta { background: rgba(99,102,241,.22); color: #a5b4fc; border-color: rgba(99,102,241,.4); }
:root[data-theme="dark"] .speaker-badge.needs-role { background: rgba(220,38,38,.20); color: #f87171; border-color: rgba(220,38,38,.45); }
/* Speaker badges keep their light-theme background tint (already translucent)
   and only lift the foreground to a readable tone — one per SPEAKERS entry. */
:root[data-theme="dark"] .seg-num.spk1  { color: #93c5fd; }
:root[data-theme="dark"] .seg-num.spk2  { color: #fdba74; }
:root[data-theme="dark"] .seg-num.spk3  { color: #86efac; }
:root[data-theme="dark"] .seg-num.spk4  { color: #fca5a5; }
:root[data-theme="dark"] .seg-num.spk5  { color: #d8b4fe; }
:root[data-theme="dark"] .seg-num.spk6  { color: #67e8f9; }
:root[data-theme="dark"] .seg-num.spk7  { color: #fcd34d; }
:root[data-theme="dark"] .seg-num.spk8  { color: #f9a8d4; }
:root[data-theme="dark"] .seg-num.spk9  { color: #bef264; }
:root[data-theme="dark"] .seg-num.spk10 { color: #a5b4fc; }
/* Календарь загрузок: тонированные ячейки вместо светлых плашек. */
:root[data-theme="dark"] .ds-cal-green { background: rgba(22,163,74,.14);  border-color: rgba(22,163,74,.5); }
:root[data-theme="dark"] .ds-cal-amber { background: rgba(245,158,11,.14); border-color: rgba(245,158,11,.5); }
:root[data-theme="dark"] .ds-cal-red   { background: rgba(220,38,38,.14);  border-color: rgba(220,38,38,.5); }
/* Тёмный NDA-бейдж на тёмном фоне — инвертируем на светлый. */
:root[data-theme="dark"] .ds-nda { background: #e5e7eb; color: #111827; }
/* Заметки и диалог: подложки уже полупрозрачные (--warm-soft/--accent-soft),
   но текст на них — тёмно-оранжевый/тёмно-синий, на тёмном нечитаемый. */
:root[data-theme="dark"] .ds-flag-note,
:root[data-theme="dark"] .ds-seg-note   { color: #fbbf24; }
:root[data-theme="dark"] .ds-flag-dialog { color: #a5b4fc; }
:root[data-theme="dark"] .ds-flag-report { color: #86efac; }
:root[data-theme="dark"] .ds-flag-useful { color: #f9a8d4; }
:root[data-theme="dark"] .ds-pre-yes { background: rgba(37,99,235,.22); color: #93c5fd; }
:root[data-theme="dark"] .ds-fu-empty    { color: #f87171; }
/* Полоски-разделители на rgba(0,0,0,…) в тёмной теме невидимы — осветляем. */
:root[data-theme="dark"] .ds-hist-row:nth-child(odd) { background: rgba(255,255,255,.04); }
:root[data-theme="dark"] .seg-collapse-toggle:hover,
:root[data-theme="dark"] .ds-chip-count { background: rgba(255,255,255,.08); }

/* ---- Reset / Base ---- */
*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  font-family: system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-size: .9375rem;
  line-height: 1.5;
  background: var(--body-bg);
  color: var(--text-primary);
  min-height: 100vh;
}

/* ================================================================
   Layout: sidebar + main
   ================================================================ */

.app-layout {
  display: flex;
  min-height: 100vh;
}

/* ---- Sidebar ---- */
.sidebar {
  width: var(--sidebar-width);
  min-width: var(--sidebar-width);
  background: var(--sidebar-bg);
  border-right: 1px solid var(--sidebar-border);
  display: flex;
  flex-direction: column;
  position: fixed;
  top: 0; left: 0; bottom: 0;
  z-index: 100;
  overflow-y: auto;
  overflow-x: hidden;
  transition: width .2s ease, min-width .2s ease;
}

.sidebar.collapsed {
  width: 56px;
  min-width: 56px;
}

.sidebar-header {
  padding: 20px 16px 16px;
  border-bottom: 1px solid var(--sidebar-border);
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
}

.sidebar-logo {
  width: 32px; height: 32px;
  background: var(--accent);
  border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: 16px;
  flex-shrink: 0;
}

.sidebar-title {
  font-weight: 600;
  font-size: .9rem;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
}

.sidebar.collapsed .sidebar-title { display: none; }

/* Nav groups */
.sidebar-nav {
  flex: 1;
  padding: 12px 8px;
}

.nav-group-label {
  font-size: .7rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 12px 8px 4px;
  white-space: nowrap;
  overflow: hidden;
}

.sidebar.collapsed .nav-group-label { opacity: 0; }

.nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  text-decoration: none;
  font-size: .875rem;
  transition: background .15s, color .15s;
  white-space: nowrap;
  overflow: hidden;
  cursor: pointer;
}

.nav-item:hover { background: var(--hover-bg); color: var(--text-primary); }
.nav-item.active { background: var(--accent-soft); color: var(--accent); font-weight: 500; }

.nav-item i { font-size: 1rem; flex-shrink: 0; width: 18px; text-align: center; }
.nav-item span { overflow: hidden; white-space: nowrap; }
.sidebar.collapsed .nav-item span { display: none; }
.sidebar.collapsed .nav-group-label { display: none; }

/* Плашка «задание вернули на доработку». Она не .nav-item, поэтому правило выше
   её подпись не прятало — в свёрнутом сайдбаре (56 px) длинная фраза вылезала
   за его пределы. В свёрнутом виде остаётся один значок; что он значит,
   говорит title. */
.returned-alert {
  display: flex; align-items: center; gap: 8px;
  margin: 0 8px 10px; padding: 9px 11px;
  border-radius: var(--radius-sm);
  background: var(--danger-soft); border: 1px solid #fecaca; color: #b91c1c;
  font-size: .8rem; font-weight: 600; line-height: 1.3; text-decoration: none;
  overflow: hidden;
}
.returned-alert i { flex-shrink: 0; }
/* В развёрнутом сайдбаре фраза переносится на две строки — обрезать её нельзя,
   иначе плашка теряет смысл. */
.returned-alert .sidebar-label { min-width: 0; }
.sidebar.collapsed .returned-alert {
  justify-content: center;
  gap: 0;
  padding: 9px 0;
}
.sidebar.collapsed .returned-alert .sidebar-label { display: none; }

/* Заметка ревьюера к возврату: ревьюер пишет её списком по строкам, и
   переносы должны дойти до разметчика — иначе пункты слипаются в одну фразу. */
#reviewer-notes-text, .reviewer-note-text { white-space: pre-line; }

/* Полоса отстранённого — на страницах, куда его всё-таки пускают (справка,
   профиль). Красная и не прячется: человек должен помнить, почему у него
   ничего не работает, а не думать, что система сломалась. Сам экран
   отстранения (/suspended) оформлен у себя в шаблоне. */
.suspended-banner {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 18px;
  background: var(--danger-soft);
  border-bottom: 2px solid var(--danger);
  color: #b91c1c;
  font-size: .85rem; line-height: 1.35;
}
.suspended-banner i { flex-shrink: 0; font-size: 1rem; }
.suspended-banner a { color: #b91c1c; font-weight: 600; white-space: nowrap; }
/* В тёмной теме тёмно-красный текст на полупрозрачной подложке нечитаем. */
:root[data-theme="dark"] .suspended-banner,
:root[data-theme="dark"] .suspended-banner a { color: #fca5a5; }

/* ================================================================
   Экран отстранения, аттестация, аттестат
   ================================================================ */

/* Плашка аттестации в сайдбаре — как .returned-alert, но на три состояния.
   Одна строка, потому что в свёрнутом сайдбаре (56px) остаётся один значок. */
.cert-alert {
  display: flex; align-items: center; gap: 8px;
  margin: 0 8px 10px; padding: 9px 11px;
  border-radius: var(--radius-sm);
  font-size: .8rem; font-weight: 600; line-height: 1.3;
  text-decoration: none; overflow: hidden;
}
.cert-alert i { flex-shrink: 0; }
.cert-alert .sidebar-label { min-width: 0; }
.cert-alert.ok   { background: var(--success-soft); border: 1px solid #bbf7d0; color: #15803d; }
.cert-alert.wait { background: var(--warning-soft); border: 1px solid #fed7aa; color: #b45309; }
.cert-alert.bad  { background: var(--danger-soft);  border: 1px solid #fecaca; color: #b91c1c; }
.sidebar.collapsed .cert-alert { justify-content: center; gap: 0; padding: 9px 0; }
.sidebar.collapsed .cert-alert .sidebar-label { display: none; }
:root[data-theme="dark"] .cert-alert.ok   { color: #86efac; }
:root[data-theme="dark"] .cert-alert.wait { color: #fcd34d; }
:root[data-theme="dark"] .cert-alert.bad  { color: #fca5a5; }

/* Переключатель языка (RU/KK) — только на двуязычных страницах. Крупный и по
   центру: на экране отстранения и в тесте это первое, что человеку может
   понадобиться, а мелкий чип в углу такого не обещает. */
.i18n-lang-row { display: flex; justify-content: center; margin-bottom: 18px; }
.i18n-lang { display: inline-flex; gap: 4px; background: var(--chip-bg);
  border: 1px solid var(--border); border-radius: var(--radius-pill); padding: 4px; }
.i18n-lang-btn {
  border: 0; background: transparent; color: var(--text-secondary);
  font-size: 1rem; font-weight: 600; padding: 9px 26px; min-width: 130px;
  border-radius: var(--radius-pill); cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.i18n-lang-btn:hover { color: var(--text-primary); }
.i18n-lang-btn.active { background: var(--card-bg); color: var(--text-primary);
  box-shadow: var(--shadow-sm); }
@media (max-width: 480px) {
  .i18n-lang-btn { min-width: 0; padding: 8px 18px; font-size: .92rem; }
}

/* Карточка экрана отстранения. Селектор с двумя классами намеренно: .auth-card
   объявлен ниже по файлу и со своим max-width:420px перебил бы одиночный
   .susp-card — экран отстранения ужимался в колонку формы входа. */
.auth-card.susp-card { max-width: 700px; }
.susp-badge {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--danger-soft); color: var(--danger);
  border-radius: var(--radius-pill);
  padding: 6px 14px; font-size: .8rem; font-weight: 600;
  letter-spacing: .04em; text-transform: uppercase;
}
.susp-reason {
  background: var(--surface-2); border: 1px solid var(--border);
  border-left: 4px solid var(--danger); border-radius: var(--radius-sm);
  padding: 14px 16px; white-space: pre-wrap; word-break: break-word;
}
.susp-steps { padding-left: 1.1rem; margin-bottom: 0; }
.susp-steps li + li { margin-top: .5rem; }
.susp-rules-link {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; padding: 11px 16px; border-radius: var(--radius);
  border: 1px solid var(--border-input); background: var(--surface-2);
  color: var(--text-primary); font-weight: 600; font-size: .9rem;
  text-decoration: none;
}
.susp-rules-link:hover { background: var(--hover-bg); color: var(--text-primary); }

/* Главная кнопка «Пройти аттестацию» — единственная дорога назад в работу,
   поэтому она заметнее всего остального на странице. */
.cert-cta {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  width: 100%; padding: 16px 20px; border: 0; border-radius: var(--radius);
  background: var(--grad-primary); color: #fff;
  font-weight: 700; font-size: 1rem; letter-spacing: .03em;
  text-decoration: none; cursor: pointer; box-shadow: var(--shadow);
}
.cert-cta:hover { color: #fff; filter: brightness(.96); }
.cert-cta i { font-size: 1.15rem; }

/* Плашки состояния заявки */
.cert-plaque {
  border: 1px solid var(--border); border-left-width: 4px;
  border-radius: var(--radius-sm); padding: 12px 14px; margin-bottom: 12px;
  background: var(--surface-2); font-size: .875rem;
}
.cert-plaque-head { display: flex; align-items: center; gap: 8px;
  font-weight: 700; margin-bottom: 4px; }
.cert-plaque-text { color: var(--text-secondary); line-height: 1.5; }
.cert-plaque-note { margin-top: 6px; font-weight: 600; }
.cert-plaque-link { display: inline-block; margin-top: 8px; font-weight: 600; }
.cert-plaque-wait { border-left-color: var(--warning); }
.cert-plaque-wait .cert-plaque-head { color: var(--warning); }
.cert-plaque-bad  { border-left-color: var(--danger); }
.cert-plaque-bad .cert-plaque-head { color: var(--danger); }
.cert-plaque-ok   { border-left-color: var(--success); }
.cert-plaque-ok .cert-plaque-head { color: var(--success); }

/* Значок сертификата в доске рейтинга — рядом с именем, не ломая колонку. */
.gami-lb-cert { margin-left: 6px; font-size: .95em; cursor: default; }

/* Строка сертификата в гейм-баре — единственная награда проекта, которую можно
   распечатать, поэтому она стоит отдельной строкой, а не чипом в общем ряду. */
.gami-cert {
  display: flex; align-items: center; gap: 12px;
  margin-top: 10px; padding: 10px 12px;
  border: 1px dashed var(--border-input); border-radius: var(--radius-sm);
  background: var(--surface-2); color: var(--text-primary); text-decoration: none;
}
.gami-cert:hover { background: var(--hover-bg); color: var(--text-primary); }
.gami-cert.is-got { border-style: solid; border-color: #c8a44a;
  background: linear-gradient(90deg, rgba(200,164,74,.12), transparent); }
.gami-cert-emoji { font-size: 1.5rem; line-height: 1; }
.gami-cert-main { display: flex; flex-direction: column; flex: 1; min-width: 0;
  font-size: .85rem; }
.gami-cert-sub { color: var(--text-secondary); font-size: .78rem; }

/* Страница теста */
.cert-page { max-width: 820px; margin: 0 auto; }
.cert-progress { display: flex; align-items: center; gap: 12px; margin-bottom: 18px; }
.cert-progress .progress { flex: 1; height: 8px; }
.cert-qnum { font-size: .82rem; color: var(--text-secondary); white-space: nowrap; }
.cert-question { font-size: 1.05rem; font-weight: 600; line-height: 1.5;
  margin-bottom: 16px; }
.cert-option {
  display: flex; gap: 10px; align-items: flex-start;
  border: 1px solid var(--border-input); border-radius: var(--radius-sm);
  padding: 12px 14px; margin-bottom: 8px; cursor: pointer; line-height: 1.45;
  background: var(--card-bg);
}
.cert-option:hover { background: var(--hover-bg); }
.cert-option.selected { border-color: var(--accent); background: var(--accent-soft);
  box-shadow: 0 0 0 1px var(--accent) inset; }
.cert-option input { margin-top: .22rem; }
.cert-dots { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 16px; }
.cert-dot {
  width: 28px; height: 28px; border-radius: var(--radius-sm);
  border: 1px solid var(--border-input); background: var(--card-bg);
  font-size: .75rem; color: var(--text-secondary); cursor: pointer;
}
.cert-dot.answered { background: var(--accent-soft); border-color: var(--accent);
  color: var(--accent-strong); font-weight: 700; }
.cert-dot.current { outline: 2px solid var(--accent); outline-offset: 1px; }

/* Результат теста */
.cert-score { font-size: 3rem; font-weight: 800; line-height: 1; }
.cert-score-ok { color: var(--success); }
.cert-score-bad { color: var(--danger); }

/* Аттестат на экране (печатная версия — PDF, тут только просмотр) */
.crt-sheet {
  max-width: 900px; margin: 0 auto; background: var(--card-bg);
  border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 32px 36px;
}
.crt-rule { height: 3px; background: var(--grad-warm); border-radius: 2px;
  margin: 18px 0 22px; }
.crt-title { font-size: 1.9rem; font-weight: 800; letter-spacing: .28em;
  text-align: center; }
.crt-level { text-align: center; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; font-size: .82rem; color: #a8842c; }
.crt-holder { font-size: 1.5rem; font-weight: 700; text-align: center; }
.crt-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 14px; margin-top: 22px; }
.crt-cell { background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 10px 12px; }
.crt-cell-label { font-size: .72rem; text-transform: uppercase;
  letter-spacing: .05em; color: var(--text-muted); }
.crt-cell-value { font-weight: 700; margin-top: 2px; }

/* Sidebar footer */
.sidebar-footer {
  border-top: 1px solid var(--sidebar-border);
  padding: 12px 12px;
  flex-shrink: 0;
}

.user-card {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 4px;
}

.user-avatar {
  width: 32px; height: 32px;
  background: var(--accent);
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-weight: 600; font-size: .8rem;
  flex-shrink: 0;
}

.user-info { overflow: hidden; }
.user-name { font-weight: 500; font-size: .85rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-stats { font-size: .75rem; color: var(--text-muted); }
.sidebar.collapsed .user-info { display: none; }

/* Avatar is a button that opens the account popover */
.user-avatar { cursor: pointer; transition: box-shadow .15s; }
.user-avatar:hover    { box-shadow: 0 0 0 2px var(--accent-light); }
.user-avatar.active   { box-shadow: 0 0 0 2px var(--accent); }

/* Account popover (Профиль / Выйти) — fixed-positioned from JS */
.user-menu {
  position: fixed;
  min-width: 196px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 8px 24px rgba(0,0,0,.18);
  padding: 8px;
  z-index: 1200;
}

/* ---- Main ---- */
.main-wrapper {
  flex: 1;
  margin-left: var(--sidebar-width);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  transition: margin-left .2s ease;
}

.sidebar.collapsed ~ .main-wrapper { margin-left: 56px; }

.page-header {
  padding: 24px 28px 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.page-title {
  font-size: 1.25rem;
  font-weight: 600;
  margin: 0;
}

.page-content {
  padding: 20px 28px 32px;
  flex: 1;
}

/* Shared sub-tab pill bar (e.g. «Транскрипция» → Текущее/Мои задания/Черновик) */
.app-subtabs { flex-wrap: wrap; }
.app-subtabs .nav-link {
  padding: .4rem .85rem;
  font-size: .85rem;
  color: var(--text-secondary, #4b5563);
  border: 1px solid transparent;
}
.app-subtabs .nav-link { border-radius: var(--radius-pill); transition: background .15s, color .15s; }
.app-subtabs .nav-link:hover { background: var(--hover-bg); }
/* Active sub-tab — тонированная pill (тёмный текст того же hue), а не сплошной синий. */
.app-subtabs .nav-link.active { background: var(--accent-soft); color: var(--accent-strong); font-weight: 600; }

/* One row: sub-tab pills + the active-task toolbar (chunk identity, timer,
   primary actions, overflow menu). Wraps to a second line when cramped. */
.subtab-bar {
  display: flex;
  align-items: center;
  gap: 8px 16px;
  flex-wrap: wrap;
}
.subtab-bar .app-subtabs { margin-bottom: 0; }

/* Всё правее пилюль — одной группой с ОДНИМ margin-left:auto: два «прижаться
   вправо» поделили бы свободное место пополам и разъехались. */
.subtab-right {
  display: flex;
  align-items: center;
  gap: 8px;
  /* Не переносим: переносится САМ тулбар внутри себя, а кнопка горячих клавиш
     всегда остаётся справа от него. Иначе на 1200px она уезжала на третью
     строку в одиночестве. */
  flex-wrap: nowrap;
  justify-content: flex-end;
  margin-left: auto;
  flex: 1 1 auto;
  min-width: 0;
}
.subtab-right > .btn { flex-shrink: 0; }

.task-toolbar {
  display: flex;
  align-items: center;
  gap: 6px 18px;
  flex-wrap: wrap;
  justify-content: flex-end;
  flex: 1 1 auto;
  min-width: 0;
}
.task-toolbar.d-none { display: none; }

/* Две смысловые половины тулбара: «что за запись» и «что с ней делать».
   Действия не должны перемешиваться с бейджами — главная кнопка обязана
   оказываться в одном и том же месте, сколько бы ни было бейджей. */
.task-toolbar-info,
.task-toolbar-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  min-width: 0;
}
.task-toolbar-actions { flex: 1 1 auto; justify-content: flex-end; }
.task-toolbar-info { flex-shrink: 0; }

/* Единственная строка шапки в задании (над волной): слева — что за запись,
   справа (.task-toolbar, margin-left:auto) — время, сохранение/сдача, чипы. */
.chunk-meta-row {
  display: flex; align-items: center; gap: 6px 8px;
  flex-wrap: wrap;
  margin-bottom: 6px;
}
.chunk-meta-row:empty { display: none; }
.chunk-meta-row > .task-toolbar { margin-left: auto; flex: 0 1 auto; gap: 6px 10px; }
/* В задании строка вкладок не нужна вовсе: переходы «Мои задания» /
   «Черновик» — после сдачи, а всё про запись — в строке над волной. */
#workspace-layout:has(#state-task:not(.d-none)) .subtab-bar { display: none; }

/* The session timer is `margin-left:auto` for the old header layout; here it
   sits inline, so cancel that. */
.task-toolbar .session-timer { margin-left: 0; }
/* Long IDs must not push the action buttons off-row. */
.task-toolbar-info .chunk-id {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 22ch;
}
/* Сдать/Сохранить/Ещё — единый блок, который не рвётся при переносе строки. */
.task-actions { flex-shrink: 0; }
.task-actions .btn { white-space: nowrap; }

.autosave-indicator {
  font-size: .75rem;
  color: var(--text-secondary);
  white-space: nowrap;
}

/* Время работы над заданием — «фишка» со значком: иначе рядом с «Сохранено
   14:02» два числа подряд читаются как одна надпись. */
.session-timer-chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 8px;
  border: 1px solid var(--border); border-radius: 999px;
  color: var(--text-secondary); font-size: .78rem;
  white-space: nowrap; flex-shrink: 0;
}
.session-timer-chip .session-timer { font-size: .8rem; }


/* ================================================================
   Cards
   ================================================================ */
.card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}

.card-body { padding: 20px; }
.card-header {
  padding: 14px 20px;
  border-bottom: 1px solid var(--border);
  font-weight: 500;
  display: flex; align-items: center; justify-content: space-between;
}

/* ================================================================
   Buttons
   ================================================================ */
.btn { border-radius: var(--radius-sm); font-size: .875rem; transition: background .15s, border-color .15s, color .15s, box-shadow .15s, transform .15s; }

.btn-primary { background: var(--accent); border-color: var(--accent); }
.btn-primary:hover, .btn-primary:focus { background: var(--accent-hover); border-color: var(--accent-hover); }

.btn-outline-primary { color: var(--accent); border-color: var(--accent); }
.btn-outline-primary:hover { background: var(--accent); color: #fff; }

/* Soft-кнопка: тонированная подложка + акцентный текст, hover = заливка.
   Для вторичных действий, разгружает интерфейс от сплошного синего. */
.btn-soft {
  background: var(--accent-soft); border-color: transparent; color: var(--accent-strong);
}
.btn-soft:hover, .btn-soft:focus { background: var(--accent); border-color: var(--accent); color: #fff; }

/* Главный CTA (hero / единственное ключевое действие на экране) — градиент + подъём. */
.btn-cta {
  background: var(--grad-primary); border-color: transparent; color: #fff;
  box-shadow: 0 2px 8px rgba(37,99,235,.28);
}
.btn-cta:hover, .btn-cta:focus {
  color: #fff; box-shadow: 0 4px 14px rgba(37,99,235,.38); transform: translateY(-1px);
}
.btn-cta:active { transform: translateY(0); box-shadow: 0 1px 4px rgba(37,99,235,.3); }

.btn-sm { padding: .3rem .65rem; font-size: .8125rem; }
.btn-lg { padding: .625rem 1.5rem; font-size: 1rem; }

/* ================================================================
   Forms
   ================================================================ */
.form-control, .form-select {
  border-color: var(--border-input);
  border-radius: var(--radius-sm);
  font-size: .875rem;
}
.form-control:focus, .form-select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.form-label { font-size: .875rem; font-weight: 500; margin-bottom: .35rem; }

/* Единый видимый фокус для интерактивных элементов (кроме полей — у них свой glow). */
.btn:focus-visible,
.nav-link:focus-visible,
.ds-chip:focus-visible,
a.gami-profile-btn:focus-visible,
[role="button"]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ================================================================
   Tables
   ================================================================ */
.table { font-size: .875rem; }
.table th { font-weight: 500; color: var(--text-secondary); font-size: .8125rem; text-transform: uppercase; letter-spacing: .04em; }
.table > :not(caption) > * > * { padding: .625rem 1rem; }

/* ================================================================
   Badges / Pills
   ================================================================ */
.badge { font-size: .7rem; font-weight: 500; padding: .25em .6em; border-radius: 20px; }

.status-badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 8px; border-radius: 20px;
  font-size: .72rem; font-weight: 500;
}
.status-approved    { background: #dcfce7; color: #15803d; }
.status-pending     { background: #fef9c3; color: #a16207; }
.status-rejected    { background: #fee2e2; color: #b91c1c; }
.status-in-progress { background: #dbeafe; color: #1d4ed8; }
.status-no-trans    { background: var(--chip-bg); color: var(--chip-text); }
.status-partial     { background: #fde68a; color: #92400e; }

/* ---- Lifecycle stage badges (single vocabulary; tones from backend) ---- */
.stage-badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 9px; border-radius: 20px;
  font-size: .72rem; font-weight: 500; white-space: nowrap;
}
.stage-gray   { background: var(--chip-bg); color: var(--chip-text); }
.stage-amber  { background: #fde68a; color: #92400e; }
.stage-blue   { background: #dbeafe; color: #1d4ed8; }
.stage-yellow { background: #fef9c3; color: #a16207; }
.stage-green  { background: #dcfce7; color: #15803d; }
.stage-red    { background: #fee2e2; color: #b91c1c; }

/* ================================================================
   Dataset console (admin → Датасет)
   ================================================================ */
.ds-funnel { display: flex; flex-wrap: wrap; gap: 8px; }
.ds-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-radius: 20px;
  border: 1px solid var(--border); background: var(--card-bg);
  color: var(--text-secondary); font-size: .8rem; cursor: pointer;
  transition: .15s; user-select: none;
}
.ds-chip:hover { border-color: var(--accent); color: var(--text-primary); }
.ds-chip.active { background: var(--accent); border-color: var(--accent); color: #fff; }
.ds-chip-count {
  font-weight: 600; font-size: .72rem;
  background: rgba(0,0,0,.06); border-radius: 10px; padding: 0 6px;
}
.ds-chip.active .ds-chip-count { background: rgba(255,255,255,.25); }
/* Record card. The head is TWO lines on purpose: identity (name + stage + the
   flags a record is picked out by) above, measurements + provenance below.
   Everything used to sit in one wrapping row, where a long bank_id pushed the
   stage badge onto the next line and the card read as a word soup. */
.ds-card {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--card-bg); overflow: hidden;
  box-shadow: 0 1px 2px rgba(16,24,40,.04);
  transition: box-shadow .15s, border-color .15s;
}
.ds-card:hover { box-shadow: 0 6px 16px -8px rgba(16,24,40,.22); border-color: var(--border-input); }
.ds-card-head { display: flex; align-items: center; gap: 10px; padding: 10px 14px; cursor: pointer; }
.ds-card-head:hover { background: var(--surface-sunken); }
.ds-caret { color: var(--text-muted); font-size: .8rem; flex-shrink: 0; transition: transform .15s; }
.ds-card-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.ds-card-line { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.ds-card-facts { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 14px; }
.ds-card-title { font-weight: 600; font-size: .88rem; max-width: 340px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* uuid — последним в НИЖНЕЙ строке и прижат вправо: справа у карточки должна
   быть ровно одна колонка (действия), а не три правых края на разных уровнях. */
.ds-card-uuid { margin-left: auto; padding-left: 8px; }
@media (max-width: 992px) { .ds-card-uuid { display: none; } }
.ds-meta { display: inline-flex; align-items: center; gap: 4px; font-size: .72rem; color: var(--text-secondary); white-space: nowrap; }
.ds-meta i { opacity: .7; }
.ds-sc { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px; font-size: .66rem; font-weight: 600; }
/* Разбивка по стадиям — хвост счётчика единиц, а не отдельная группа кружков в
   ряду: сама по себе она читалась как цифра непонятно о чём. */
.ds-sc-group { display: inline-flex; align-items: center; gap: 3px; margin-left: 5px; }
.ds-nda { font-size: .6rem; font-weight: 700; letter-spacing: .04em; background: #111827; color: #fff; border-radius: 4px; padding: 1px 4px; }
.ds-card-actions { display: inline-flex; gap: 6px; flex-shrink: 0; align-self: center; }
.ds-card-actions .btn { padding: 3px 8px; line-height: 1.2; font-size: .8rem; }
.ds-uuid { font-family: var(--font-mono); font-size: .7rem; color: var(--text-muted); }
.ds-card-body { border-top: 1px solid var(--border); padding: 10px 12px; background: var(--surface-sunken-2); }

/* Панель над списком записей: вид (таблица / карточки) и группировка. */
.ds-list-tools { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.ds-list-tools-label { font-size: .78rem; color: var(--text-secondary); margin-left: 6px; }

/* Заголовок группы (по длительности) в виде карточек. */
.ds-group-head {
  display: flex; align-items: center; gap: 8px; font-size: .82rem;
  padding: 6px 2px 2px; color: var(--text-secondary);
}
.ds-group-head b { color: var(--text-primary); }

/* Таблица записей. Каждая запись — свой <tbody> (строка + строка-деталь), так
   что раскрытие живёт рядом со строкой, как тело у карточки. */
.ds-table-wrap {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--card-bg); box-shadow: 0 1px 2px rgba(16,24,40,.04);
}
.ds-table { font-size: .8rem; --bs-table-bg: transparent; }
.ds-table thead th {
  font-size: .7rem; font-weight: 600; text-transform: uppercase; letter-spacing: .03em;
  color: var(--text-muted); white-space: nowrap; background: var(--surface-sunken);
  border-bottom: 1px solid var(--border); padding: 8px 10px;
}
.ds-table td { padding: 6px 10px; border-color: var(--border); }
.ds-trow { cursor: pointer; }
.ds-trow:hover > td { background: var(--surface-sunken); }
.ds-tcol-caret { width: 24px; padding-right: 0 !important; }
.ds-tcol-name { max-width: 300px; }
.ds-tname { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ds-tsub { display: flex; align-items: center; gap: 6px; font-size: .68rem; color: var(--text-muted); white-space: nowrap; }
.ds-tsmall { font-size: .74rem; color: var(--text-secondary); }
.ds-tnum { font-variant-numeric: tabular-nums; white-space: nowrap; }
.ds-tflags { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; max-width: 260px; }
.ds-tflags .ds-flag-useful { max-width: 220px; overflow: hidden; text-overflow: ellipsis; }
.ds-table .ds-card-actions .btn { padding: 2px 6px; }
.ds-rec-fold > td { border-bottom: 1px solid var(--border); }
.ds-rec-fold .ds-card-body { border-top: 0; }
.ds-tgroup td {
  background: var(--surface-sunken-2); font-size: .8rem; color: var(--text-secondary);
  padding: 7px 10px; border-bottom: 1px solid var(--border);
}
.ds-tgroup td b { color: var(--text-primary); margin: 0 6px 0 4px; }

/* Что выделяет запись глазами в списке: обучаемая заметка и диалог с моделью
   (services/dataset._notes_by_source). */
.ds-flag {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: .66rem; font-weight: 600; white-space: nowrap;
  border-radius: 10px; padding: 1px 8px; border: 1px solid transparent;
}
.ds-flag-note   { background: var(--warm-soft);   color: var(--warm-strong);  border-color: rgba(245,158,11,.35); }
.ds-flag-dialog { background: var(--accent-soft); color: var(--accent-strong); border-color: rgba(99,102,241,.35); }
/* Отчёт по записи — второй ход разговора (поле report, format_version 9): свой
   флажок, потому что «комментарий есть» про отчёт больше ничего не говорит. */
.ds-flag-report { background: var(--success-soft); color: var(--success); border-color: rgba(22,163,74,.35); }
/* Пометка «полезно» (services/useful): запись особенно нужна обучению —
   например, на ней модель уходит в петлю. Не группировка, поэтому флажок. */
.ds-flag-useful { background: rgba(219,39,119,.10); color: #be185d; border-color: rgba(219,39,119,.35); }

.ds-chunk { border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--card-bg); margin-bottom: 8px; overflow: hidden; }
.ds-chunk:last-child { margin-bottom: 0; }
.ds-chunk-head { display: flex; align-items: center; gap: 8px; padding: 8px 10px; background: var(--surface-sunken); }
.ds-chunk-badges { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; flex-wrap: wrap; gap: 6px 8px; }
/* uuid — последним и вправо: он идентификатор для копирования, а не то, по чему
   строку читают (полный — в title). */
.ds-chunk-badges .ds-uuid { margin-left: auto; padding-left: 8px; }
.ds-chunk-head-actions { display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0; }
.ds-chunk-body { border-top: 1px solid var(--border); padding: 10px; }
.ds-chunk-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; padding-top: 10px; border-top: 1px dashed var(--border); }
.ds-transcript { font-family: var(--font-mono); font-size: .8rem; line-height: 1.6; color: var(--text-primary); white-space: pre-wrap; word-break: break-word; }
.ds-body-label { margin-bottom: 5px; }

/* Строка расшифровки = адрес для перемотки (ds-player.js). Полоска слева несёт
   цвет сегмента — тот же, что у его оверлея на волне, поэтому строку и полосу
   читают как одно. Отступ под полоску есть ВСЕГДА (в том числе у неактивной
   строки), иначе подсветка играющего сегмента дёргала бы текст вбок. */
.ds-tline {
  position: relative; padding-left: 10px; border-radius: 3px; cursor: pointer;
  transition: background .12s ease;
}
.ds-tline::before {
  content: ''; position: absolute; left: 0; top: 2px; bottom: 2px; width: 3px;
  border-radius: 2px; background: var(--tline-bar, transparent); opacity: .5;
}
.ds-tline:hover { background: var(--surface-sunken); }
.ds-tline:hover::before { opacity: 1; }
.ds-tline.is-active { background: var(--accent-soft); }
.ds-tline.is-active::before { opacity: 1; }

/* ---- Встроенный плеер: волна + сегменты (pages/ds-player.js) ----
   Живёт первым блоком в теле чанка, разворачивается по кнопке «слушать». */
.ds-player {
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface-sunken); overflow: hidden; margin-bottom: 10px;
}
/* Вся волна — поверхность перемотки (dsWireScrub): клик = переход в точку,
   протяжка = скраб. pan-y — чтобы на тач-экране страница всё ещё листалась. */
.ds-player-wave { position: relative; background: var(--card-bg); cursor: pointer;
                  touch-action: pan-y; user-select: none; }
.ds-player-wave.is-scrubbing, .ds-player-wave.is-scrubbing * { cursor: grabbing; }
.ds-player-host { position: relative; z-index: 1; }
/* Сегменты ловят мышь только ради подсказки и hover; нажатие всплывает к
   волне и перематывает в точку клика, а не на начало сегмента. */
.ds-player-segs { position: absolute; inset: 0; z-index: 2; pointer-events: none; }
.ds-pseg {
  position: absolute; top: 0; bottom: 0; pointer-events: auto;
  overflow: hidden; border-left: 2px solid var(--pseg-bar, transparent);
}
/* Маркер воспроизведения — поверх оверлеев, с ручкой сверху. Красный: синего
   не видно сквозь полупрозрачные сегменты (цвет канваса — не токен, как и у
   самой волны). */
.ds-player-head {
  position: absolute; top: 0; bottom: 0; width: 2px; margin-left: -1px;
  z-index: 3; background: #ef4444; pointer-events: none;
}
.ds-player-knob {
  position: absolute; top: -1px; left: 50%; width: 12px; height: 12px;
  transform: translateX(-50%); border-radius: 50%;
  background: #ef4444; border: 2px solid var(--card-bg);
  box-shadow: var(--shadow-sm); cursor: grab; pointer-events: auto;
}
.ds-player-wave.is-scrubbing .ds-player-knob { transform: translateX(-50%) scale(1.2); }
.ds-pseg > span {
  position: absolute; left: 3px; top: 2px; max-width: calc(100% - 5px);
  font-size: .6rem; font-weight: 600; line-height: 1.1; white-space: nowrap;
  color: var(--pseg-bar, var(--text-secondary));
  text-shadow: 0 0 3px var(--card-bg), 0 0 3px var(--card-bg);
}
.ds-pseg:hover { filter: brightness(.92) saturate(1.2); }
.ds-pseg.is-active { box-shadow: inset 0 0 0 2px var(--pseg-bar, var(--accent)); }
/* «Не добавлять» — штриховка, как у вырезанного куска в аудиоредакторе: этот
   участок физически уедет из экспортного WAV, и заливкой одного тона это не
   сказать (см. memory/overlap-guard-exclude). */
.ds-pseg-cut {
  background-image: repeating-linear-gradient(45deg,
    rgba(220,38,38,.28) 0 5px, rgba(220,38,38,0) 5px 10px);
}
.ds-player-load {
  position: absolute; inset: 0; z-index: 3; display: flex;
  align-items: center; justify-content: center;
  font-size: .78rem; color: var(--text-muted); background: var(--card-bg);
}
.ds-player-bar {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  padding: 6px 8px; border-top: 1px solid var(--border);
}
.ds-player-time { font-family: var(--font-mono); font-size: .76rem; color: var(--text-secondary); }
.ds-player-now  { font-size: .72rem; font-weight: 600; color: var(--text-primary); }
.ds-player-legend { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 4px 10px; margin-left: auto; }
.ds-pleg { display: inline-flex; align-items: center; gap: 4px; font-size: .68rem; color: var(--text-secondary); }
.ds-pleg i { width: 9px; height: 9px; border-radius: 2px; display: inline-block; }
.ds-player-rates .btn { font-size: .68rem; padding: 1px 6px; }
.ds-empty-line { font-size: .8rem; color: var(--text-muted); }
.ds-count-pill { font-size: .7rem; color: var(--text-secondary); background: var(--chip-bg); border-radius: 10px; padding: 1px 8px; }

/* ---- Обучаемые поля разметки: заметки и диалог с моделью ----
   Комментарий отрезка живёт хвостом строки таргета, поэтому и здесь он хвост
   строки — но не моноширинный, иначе читается как часть реплики. */
.ds-seg-note {
  display: inline-flex; align-items: center; gap: 4px;
  font-family: system-ui, -apple-system, 'Segoe UI', sans-serif; font-size: .7rem;
  border-radius: 8px; padding: 0 6px; vertical-align: baseline;
  background: var(--warm-soft); color: var(--warm-strong); border: 1px solid rgba(245,158,11,.35);
}
.ds-notes { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; }
.ds-note {
  border: 1px solid var(--border); border-left: 3px solid var(--border-input);
  border-radius: var(--radius-sm); padding: 8px 10px; background: var(--card-bg);
}
.ds-note-record { border-left-color: var(--warm); }
.ds-note-dialog { border-left-color: var(--accent-2); }
.ds-note-report { border-left-color: var(--success); }
/* «Чем просили» — длинная простыня запроса, поэтому по умолчанию свёрнута и с
   собственной прокруткой: она справочная, а читают ответ. */
.ds-report-req summary { font-size: .7rem; color: var(--text-muted); cursor: pointer; margin-bottom: 4px; }
.ds-report-req .ds-note-text { font-size: .72rem; color: var(--text-secondary); max-height: 220px; overflow: auto; }
.ds-note-tech   { background: var(--surface-sunken); }
.ds-note-head {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  font-size: .74rem; font-weight: 600; color: var(--text-primary); margin-bottom: 5px;
}
.ds-note-head i { opacity: .8; }
.ds-note-hint { font-weight: 400; font-size: .68rem; color: var(--text-muted); }
.ds-note-text { font-size: .8rem; color: var(--text-primary); white-space: pre-wrap; word-break: break-word; }
/* Отрендеренный Markdown (core/markdown): у него своя блочная структура, поэтому
   pre-wrap здесь снимается — иначе к отступам тегов добавились бы ещё и
   переводы строк исходника. */
.ds-note-text.ds-md, .ds-fu-text.ds-md { white-space: normal; }
.ds-note-tech .ds-note-text { font-size: .76rem; color: var(--text-secondary); display: flex; flex-direction: column; gap: 3px; }
.ds-note-tech .ds-note-text i { opacity: .7; margin-right: 5px; }

.ds-fu-list { display: flex; flex-direction: column; gap: 8px; }
.ds-fu-turn { display: flex; align-items: flex-start; gap: 8px; }
.ds-fu-n {
  flex-shrink: 0; width: 20px; height: 20px; margin-top: 2px; border-radius: 50%;
  background: var(--chip-bg); color: var(--chip-text);
  font-size: .68rem; font-weight: 700;
  display: inline-flex; align-items: center; justify-content: center;
}
.ds-fu-pair { flex: 1 1 auto; min-width: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
@media (max-width: 900px) { .ds-fu-pair { grid-template-columns: 1fr; } }
.ds-fu-side { border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 6px 8px; background: var(--surface-sunken); min-width: 0; }
.ds-fu-bot { background: var(--accent-soft); border-color: rgba(99,102,241,.3); }
.ds-fu-who {
  display: flex; align-items: center; gap: 4px; margin-bottom: 3px;
  font-size: .64rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--text-muted);
}
.ds-fu-text { font-size: .8rem; color: var(--text-primary); white-space: pre-wrap; word-break: break-word; }
.ds-fu-empty { color: var(--danger); font-style: italic; }

/* ================================================================
   Состав говорящих чипами (core/speaker-meta) — шапка записи и шапка чанка
   в консоли «Датасет». Номер несёт цвет спикера (SpeakerColors), тот же, что в
   редакторе и на осциллограмме, поэтому «Спикер 2» узнаётся, не читая текст.
   ================================================================ */
.spk-chips { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 4px; }
.spk-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 7px 1px 3px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--card-bg);
  font-size: .68rem; color: var(--text-secondary); white-space: nowrap;
}
.spk-chip-n {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 16px; height: 16px; border-radius: 50%;
  font-size: .64rem; font-weight: 700;
}
.spk-chip-txt { font-weight: 500; }

/* ================================================================
   Отрендеренный Markdown разметчика (core/markdown). Плотнее обычной типографики
   страницы: это заметка внутри карточки, а не статья, — поэтому заголовки почти
   не крупнее текста, а вертикальные отступы вдвое меньше.
   ================================================================ */
.ds-md { font-size: .8rem; line-height: 1.55; color: var(--text-primary); }
.ds-md > *:first-child { margin-top: 0; }
.ds-md > *:last-child  { margin-bottom: 0; }
.ds-md p { margin: 0 0 .5rem; }
.ds-md h3, .ds-md h4, .ds-md h5, .ds-md h6 {
  margin: .7rem 0 .35rem; font-weight: 600; line-height: 1.3; color: var(--text-primary);
}
.ds-md h3 { font-size: .92rem; }
.ds-md h4 { font-size: .85rem; }
.ds-md h5, .ds-md h6 { font-size: .8rem; color: var(--text-secondary); }
.ds-md ul, .ds-md ol { margin: 0 0 .5rem; padding-left: 1.25rem; }
.ds-md li { margin: .1rem 0; }
.ds-md code {
  font-family: var(--font-mono); font-size: .92em;
  background: var(--chip-bg); border-radius: 3px; padding: 0 4px;
}
.ds-md pre {
  margin: 0 0 .5rem; padding: 8px 10px; overflow-x: auto;
  background: var(--surface-sunken); border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.ds-md pre code { background: none; padding: 0; }
.ds-md blockquote {
  margin: 0 0 .5rem; padding: 2px 0 2px 10px;
  border-left: 3px solid var(--border-input); color: var(--text-secondary);
}
.ds-md hr { margin: .6rem 0; border: 0; border-top: 1px solid var(--border); }
/* Таблица претензий — самая широкая часть отчёта: скроллится внутри себя, чтобы
   не растягивать карточку записи. */
.md-table-wrap { overflow-x: auto; margin: 0 0 .5rem; }
.md-table { border-collapse: collapse; font-size: .76rem; }
.md-table th, .md-table td {
  border: 1px solid var(--border); padding: 3px 8px; text-align: left; vertical-align: top;
}
.md-table th { background: var(--surface-sunken); font-weight: 600; white-space: nowrap; }

/* Per-record provenance (services/history). The block sits at the top of the
   body (authors + collapsible timeline); the review-stage actors (submitted /
   review-edited / approved) live as compact chips in the chunk header. */
.ds-head-prov { display: inline-flex; align-items: center; gap: 3px; font-size: .68rem; color: var(--text-secondary); background: var(--chip-bg); border-radius: 10px; padding: 1px 7px; white-space: nowrap; }
.ds-head-prov i { opacity: .75; }
.ds-history { border-bottom: 1px dashed var(--border); padding-bottom: 8px; }
.ds-hist-summary { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font-size: .74rem; color: var(--text-secondary); }
.ds-hist-summary i { opacity: .7; }
.ds-hist-details { margin-top: 6px; }
.ds-hist-details > summary { cursor: pointer; font-size: .72rem; color: var(--text-muted); user-select: none; }
.ds-hist-details > summary:hover { color: var(--accent); }
.ds-hist-list { margin-top: 6px; display: flex; flex-direction: column; gap: 2px; }
.ds-hist-row { display: grid; grid-template-columns: 120px 1fr auto; gap: 8px; font-size: .72rem; padding: 2px 6px; border-radius: 4px; }
.ds-hist-row:nth-child(odd) { background: rgba(0,0,0,.03); }
.ds-hist-when { color: var(--text-muted); white-space: nowrap; }
.ds-hist-act { color: var(--text-secondary); }
.ds-hist-who { color: var(--text-primary); font-weight: 500; text-align: right; }

/* ASR pre-transcriptor + queue indicator */
.ds-asr {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 8px 14px; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--card-bg); font-size: .8rem;
}
.ds-asr-dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; flex-shrink: 0; }
.ds-asr-on  { background: #16a34a; box-shadow: 0 0 0 3px rgba(22,163,74,.15); }
.ds-asr-off { background: #9ca3af; }
.ds-q { display: inline-flex; align-items: center; gap: 5px; color: var(--text-secondary); }
.ds-asr-state { display: inline-flex; align-items: center; gap: 5px; }
.ds-asr-busy { color: var(--accent); font-weight: 600; }
.ds-asr-busy .spinner-border { width: .8rem; height: .8rem; border-width: .14em; }
.ds-asr-progress { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--border); }
.ds-asr-jobs { margin-top: 6px; display: flex; flex-direction: column; gap: 3px; }

/* "Предтранскрибировано: да/нет" pill on the source card */
.ds-pre {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: .66rem; font-weight: 600; white-space: nowrap;
  border-radius: 10px; padding: 1px 7px;
}
.ds-pre-yes { background: #dbeafe; color: #1d4ed8; }
.ds-pre-no  { background: var(--chip-bg); color: var(--chip-text); }

/* ================================================================
   Dataset calendar (admin → Датасет → browse by upload date)
   ================================================================ */
.ds-cal-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ds-cal-title { font-weight: 600; font-size: .95rem; min-width: 150px; text-align: center; }
.ds-cal-legend { display: flex; gap: 12px; flex-wrap: wrap; font-size: .74rem; color: var(--text-secondary); }
.ds-cal-legend span { display: inline-flex; align-items: center; gap: 5px; }
.ds-cal-key { width: 12px; height: 12px; border-radius: 3px; display: inline-block; border: 1px solid rgba(0,0,0,.08); }

.ds-cal-totals { display: flex; flex-wrap: wrap; gap: 14px; font-size: .8rem; color: var(--text-secondary); }
.ds-cal-stat { display: inline-flex; align-items: center; gap: 5px; }
.ds-cal-stat b { color: var(--text-primary); }

.ds-cal { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
.ds-cal-wd { text-align: center; font-size: .72rem; font-weight: 600; color: var(--text-muted); padding: 2px 0; }
.ds-cal-pad { visibility: hidden; }
.ds-cal-day {
  position: relative; min-height: 78px; border: 1px solid var(--border);
  border-radius: var(--radius-sm); background: var(--card-bg); padding: 5px 6px;
  display: flex; flex-direction: column; transition: .12s;
}
.ds-cal-day[role="button"] { cursor: pointer; }
.ds-cal-day[role="button"]:hover { box-shadow: 0 0 0 2px var(--accent); transform: translateY(-1px); }
.ds-cal-num { font-size: .78rem; font-weight: 600; color: var(--text-secondary); }
.ds-cal-total { font-size: 1.25rem; font-weight: 700; line-height: 1; margin-top: 2px; }
.ds-cal-counts { margin-top: auto; display: flex; gap: 8px; font-size: .68rem; color: var(--text-secondary); }
.ds-cal-counts span { display: inline-flex; align-items: center; gap: 2px; }
.ds-cal-counts i { font-size: .7rem; }

.ds-cal-empty { background: var(--card-bg); }
.ds-cal-empty .ds-cal-num { color: var(--text-muted); }
.ds-cal-green { background: #ecfdf3; border-color: #86efac; }
.ds-cal-amber { background: #fffbeb; border-color: #fde68a; }
.ds-cal-red   { background: #fef2f2; border-color: #fca5a5; }
.ds-cal-gray  { background: var(--chip-bg); border-color: var(--border); }
.ds-cal-today-cell { outline: 2px solid var(--accent); outline-offset: -1px; }

.ds-day-label { font-size: .9rem; }

/* Inline ASR prelabel progress bar (transcription editor) */
.prelabel-prog { display:inline-block; width:90px; height:6px; vertical-align:middle;
  background:var(--border); border-radius:3px; overflow:hidden; }
.prelabel-prog-fill { display:block; height:100%; background:var(--grad-primary); transition:width .3s ease; }

/* ================================================================
   Auth pages
   ================================================================ */
.auth-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--body-bg);
  padding: 24px;
}

.auth-card {
  width: 100%;
  max-width: 420px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow);
  padding: 36px 32px;
}

.auth-logo {
  display: flex; align-items: center; justify-content: center;
  gap: 10px;
  margin-bottom: 28px;
}

.auth-logo-icon {
  width: 40px; height: 40px;
  background: var(--accent);
  border-radius: 10px;
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: 20px;
}

.auth-logo-text {
  font-weight: 700; font-size: 1.1rem; color: var(--text-primary);
}

/* ================================================================
   Главная — / (о проекте, курс, правила). Standalone, как auth-страницы.
   Язык: <html data-page-lang="ru|kk">, блоки [data-lang] другого языка скрыты.
   ================================================================ */
html[data-page-lang="ru"] [data-lang="kk"],
html[data-page-lang="kk"] [data-lang="ru"] { display: none !important; }

.home-body { background: var(--body-bg); color: var(--text-primary); }
.home-wrap { max-width: 1040px; margin: 0 auto; padding: 0 16px; }

.home-top {
  position: sticky; top: 0; z-index: 10;
  background: var(--card-bg);
  border-bottom: 1px solid var(--border);
}
.home-top-inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; min-height: 60px;
}
.home-brand { display: flex; align-items: center; gap: 10px; text-decoration: none; }
.home-brand .auth-logo-icon { width: 34px; height: 34px; font-size: 17px; border-radius: 9px; }
.home-top-nav { display: flex; align-items: center; gap: 8px; }

.home-lang {
  display: inline-flex; padding: 2px;
  border: 1px solid var(--border); border-radius: var(--radius-pill);
  background: var(--surface-2);
}
.home-lang button {
  border: 0; background: transparent; color: var(--text-secondary);
  font-size: .78rem; font-weight: 600; padding: 3px 10px;
  border-radius: var(--radius-pill);
}
.home-lang button.active { background: var(--accent); color: #fff; }

.home-hero { padding: 48px 0 28px; max-width: 760px; }
.home-hero h1 { font-size: clamp(1.6rem, 4vw, 2.3rem); font-weight: 700; line-height: 1.2; margin-bottom: 14px; }
.home-lead { font-size: 1.05rem; line-height: 1.65; color: var(--text-secondary); }
.home-hero-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 20px; }

.home-cards {
  display: grid; gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.home-card {
  background: var(--card-bg); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow-sm); padding: 20px;
}
.home-card h3 { font-size: 1rem; font-weight: 600; margin-bottom: 6px; }
.home-card p { font-size: .9rem; line-height: 1.6; color: var(--text-secondary); margin: 0; }
.home-card-icon {
  width: 36px; height: 36px; margin-bottom: 12px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 10px; background: var(--accent-soft); color: var(--accent); font-size: 18px;
}

.home-steps, .home-section { padding-top: 40px; }
.home-steps h2, .home-section h2 { font-size: 1.35rem; font-weight: 700; margin-bottom: 12px; }
.home-steps ol { padding-left: 1.2rem; line-height: 1.8; margin-bottom: 12px; }
.home-nda {
  display: flex; gap: 8px; align-items: flex-start;
  font-size: .86rem; color: var(--text-secondary);
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 10px 12px; margin: 0;
}
.home-muted { color: var(--text-secondary); font-size: .92rem; }
.home-section { scroll-margin-top: 64px; }

.home-video {
  border-radius: var(--radius); overflow: hidden;
  background: #000; box-shadow: var(--shadow);
  aspect-ratio: 16 / 9;
}
.home-video video { width: 100%; height: 100%; display: block; }
.home-video-alt { margin-top: 10px; }

/* Курс разметчика во вкладке «Правила» на /support */
.course-head {
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: 10px; margin-bottom: 8px;
}
.course-lang .btn { font-weight: 600; padding: 6px 18px; }

.home-foot {
  margin-top: 48px; padding: 20px 0 28px;
  border-top: 1px solid var(--border); font-size: .88rem;
}

/* Ссылка на главную с экрана входа. */
.auth-about-link { font-size: .85rem; }

/* ================================================================
   Waveform / Annotator workspace
   ================================================================ */
.workspace { display: flex; flex-direction: column; gap: 16px; }

.chunk-header {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.chunk-id {
  font-family: var(--font-mono);
  font-size: .78rem;
  color: var(--text-secondary);
}

.chunk-type-badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 8px; border-radius: 4px; font-size: .72rem; font-weight: 500;
}
.chunk-type-vad      { background: #e0e7ff; color: #3730a3; }
.chunk-type-full     { background: #fce7f3; color: #9d174d; }

.session-timer {
  font-family: var(--font-mono);
  font-size: .875rem; font-weight: 500;
  color: var(--text-secondary);
  margin-left: auto;
}
.session-timer.warn  { color: #d97706; }
.session-timer.danger { color: #dc2626; }

/* Waveform container — merged with the chunk header into one panel that lives
   in the fixed workspace-top region, so the header + player stay pinned above
   the scrolling segment list. */
.waveform-wrap {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 12px;
  box-shadow: 0 4px 10px -6px rgba(0,0,0,.25);
}

/* Speaker badges in the task toolbar (transcription): one per used speaker,
   click opens a role/gender/age picker. `.has-meta` = something is already
   filled in.
   Геометрия строки ФИКСИРОВАННАЯ: пустой и заполненный бейдж одной высоты, а
   подпись обрезается по ширине. Раньше заполненный бейдж вырастал и утаскивал
   весь тулбар на вторую строку — бейджи прыгали на другой уровень ровно в тот
   момент, когда их заполняли (короткие подписи — annotator.SPK_SHORT). */
.speaker-badges {
  display: inline-flex; align-items: center; gap: 4px;
  flex-wrap: wrap; row-gap: 4px;
  align-self: center;
}
/* В строке плеера /transcription бейджи стоят в левой колонке сетки (транспорт —
   по центру, эквалайзер — справа); на узком экране — первыми в строке. */
.wave-controls > .speaker-badges { justify-self: start; min-width: 0; }
@media (max-width: 1399.98px) {
  .wave-controls > .speaker-badges { order: 0; }
}
.speaker-badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 0 8px; min-height: 26px; border-radius: 999px;
  font-size: .72rem; font-weight: 600; line-height: 1.5;
  background: var(--hover-bg, #f3f4f6);
  color: var(--text-secondary, #4b5563);
  border: 1px solid var(--border, #e5e7eb);
  cursor: pointer;
  white-space: nowrap;
  transition: background .15s, border-color .15s, color .15s;
}
.speaker-badge:hover { border-color: var(--accent, #2563eb); color: var(--accent, #2563eb); }
/* Человечек — цветом спикера (--spk ставит страница: транскрипция, ревью,
   «Создание датасета»); у бейджа «не заполнено» — цветом тревоги. */
.speaker-badge .bi-person-fill { color: var(--spk, currentColor); }
.speaker-badge.needs-role .bi-person-fill { color: inherit; }
.speaker-badge .spk-num {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 14px;
}
.speaker-badge.has-meta {
  background: #e0e7ff; color: #3730a3; border-color: #c7d2fe;
}
/* «Роль не выбрана» — единственное, что мешает сдать задание с этой панели, а
   искать его глазами негде: подсвечиваем бейдж так же тревожно, как is-invalid
   у обязательных select'ов сегмента. Ставится только на своих записях. */
.speaker-badge.needs-role {
  background: #fee2e2; color: #991b1b; border-color: #fca5a5;
}
.speaker-badge .spk-summary:empty { display: none; }
.speaker-badge .spk-summary {
  font-weight: 500; opacity: .85;
  padding-left: 5px; margin-left: 1px; border-left: 1px solid currentColor;
  max-width: 20ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Role/gender/age picker hanging off a speaker badge. Варианты стоят В СТОЛБИК
   и по левому краю: подписи здесь полные и разной длины («Клиент (обслуживают
   его)» против «Женский»), и в несколько колонок они ложились рваными рядами —
   два варианта в одной строке, один в следующей. Столбик читается как меню. */
.spk-meta-menu {
  min-width: 236px; padding: 10px !important;
  max-height: min(70vh, 480px); overflow-y: auto;
}
.spk-meta-title {
  font-size: .78rem; font-weight: 600;
  color: var(--text-primary, #111827);
  padding: 0 2px 6px;
  border-bottom: 1px solid var(--border, #e5e7eb);
  margin-bottom: 2px;
}
.spk-meta-group-label {
  font-size: .7rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: .03em; color: var(--text-muted, #6b7280);
  padding: 8px 2px 4px;
}
.spk-meta-opts { display: flex; flex-direction: column; gap: 3px; }
.spk-meta-opts .btn {
  text-align: left; padding: .2rem .55rem; font-size: .74rem;
  white-space: nowrap;
}
.spk-meta-opt.active {
  background: var(--accent, #2563eb); color: #fff; border-color: var(--accent, #2563eb);
}
/* Имя спикера — единственное поле состава без словаря, поэтому поле ввода в том
   же выпадающем меню, что и кнопки роли/пола. */
.spk-meta-name { font-size: .74rem; padding: .2rem .5rem; }

/* Review detail (/review/<uuid>) top bar: nav + chunk identity + speaker badges
   on the left, decisions on the right. Mirrors .task-toolbar on /transcription. */
.review-topbar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 10px 28px;
  border-bottom: 1px solid var(--border);
}
.review-topbar-actions {
  display: flex; align-items: center; gap: 8px;
  margin-left: auto; flex-wrap: wrap;
}
.review-topbar .chunk-id {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 22ch;
}
.review-more-label {
  font-size: .7rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: .03em; color: var(--text-muted, #6b7280);
  padding: 0 4px 3px;
}
@media (max-width: 767px) { .review-topbar { padding: 10px 16px; } }

/* Бридкам «папка / карточка» записи (core/card-move.js) — в шапке ревью и
   редактора. У админа и ревьювера это кнопка: открывает окно переноса. */
.card-crumb {
  display: inline-flex; align-items: center; gap: 5px; min-width: 0;
  max-width: 46ch; padding: 2px 9px;
  font-size: .76rem; line-height: 1.5; color: var(--text-secondary);
  background: var(--chip-bg); border: 1px solid transparent;
  border-radius: var(--radius-pill); white-space: nowrap;
}
.card-crumb > span { overflow: hidden; text-overflow: ellipsis; }
.card-crumb .bi { font-size: .78rem; opacity: .75; }
.card-crumb .card-crumb-card { color: var(--text-primary); font-weight: 600; }
.card-crumb .card-crumb-sep { opacity: .55; }
.card-crumb .card-crumb-edit { margin-left: 2px; opacity: 0; transition: opacity .15s; }
button.card-crumb.is-clickable { cursor: pointer; }
button.card-crumb.is-clickable:hover { border-color: var(--border-input); background: var(--hover-bg); }
button.card-crumb.is-clickable:hover .card-crumb-edit { opacity: .8; }

/* Окно переноса: цели деревом папок, как в обзоре консоли. */
.cm-list { max-height: 60vh; overflow-y: auto; border: 1px solid var(--border); border-radius: 10px;
           padding: 4px 0; }
.cm-folder-head {
  display: flex; align-items: center; gap: 6px; padding: 5px 12px;
  font-size: .86rem; font-weight: 600; color: var(--text-primary);
  cursor: pointer; user-select: none;
}
.cm-folder-head:hover { background: var(--hover-bg); }
.cm-folder-head .bi { color: var(--text-muted); }
.cm-folder-head .cm-caret { font-size: .7rem; transition: transform .15s; transform: rotate(90deg); }
.cm-folder.collapsed > .cm-folder-head .cm-caret { transform: none; }
.cm-folder-head .cm-meta { color: var(--text-muted); font-size: .74rem; font-weight: 500; }
.cm-kids { margin-left: 18px; border-left: 2px solid var(--border); }
.cm-folder.collapsed > .cm-kids { display: none; }
.cm-item {
  display: flex; align-items: center; gap: 8px; padding: 5px 12px;
  font-size: .86rem; cursor: pointer;
}
.cm-item:hover { background: var(--hover-bg); }
.cm-item .bi { color: var(--text-muted); }
.cm-item .cm-name { flex: 1 1 auto; min-width: 0; font-weight: 500; overflow-wrap: anywhere; }
.cm-item .cm-meta { color: var(--text-muted); font-size: .76rem; white-space: nowrap; }
.cm-item .cm-now {
  font-size: .7rem; padding: 0 7px; border-radius: var(--radius-pill);
  background: var(--chip-bg); color: var(--chip-text); white-space: nowrap;
}
.cm-item.is-selected { background: var(--accent-soft); box-shadow: inset 3px 0 0 var(--accent); }
.cm-item.is-selected .cm-name { font-weight: 600; }
.cm-item.is-current { cursor: default; }
.cm-item.is-current:hover { background: transparent; }
.cm-item.is-disabled { cursor: not-allowed; opacity: .5; }
.cm-item.is-disabled:hover { background: transparent; }

/* «Кого ревьювить» — фильтр по автору над очередью ревью. */
.review-author-filter {
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
  padding: 12px 14px; border-radius: 8px;
  background: var(--surface-2, #f8fafc); border: 1px solid var(--border, #e5e7eb);
}
.review-author-filter-label {
  font-size: .8rem; font-weight: 600; color: var(--text-muted, #6b7280);
}
.review-author-btn { white-space: nowrap; }

/* ================================================================
   Очередь ревью — карточка записи (.rq-*)

   Карточка кликабельна целиком, поэтому её собственная иерархия должна
   читаться без «зацепок»: одна крупная величина (длительность), под ней
   автор и свежесть, ниже — профиль сегментов полосой, факты чипами и
   превью текста. Всё на токенах, чтобы тёмная тема досталась даром.
   ================================================================ */
.rq-card {
  cursor: pointer;
  transition: box-shadow .15s, border-color .15s, transform .15s;
}
.rq-card:hover {
  box-shadow: var(--shadow);
  border-color: var(--border-input);
  transform: translateY(-1px);
}
.rq-body { padding: 14px 16px 12px; display: flex; flex-direction: column; gap: 10px; }

/* --- шапка: величина + ярлыки + uuid --- */
.rq-head { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.rq-dur {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: .95rem; font-weight: 600; color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
.rq-dur i { color: var(--accent); font-size: .85rem; }
.rq-tag {
  font-size: .68rem; font-weight: 600; letter-spacing: .02em;
  padding: 2px 7px; border-radius: var(--radius-pill);
  background: var(--chip-bg); color: var(--chip-text);
}
.rq-uuid {
  margin-left: auto; font-size: .68rem; color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* --- автор и свежесть --- */
.rq-people { display: flex; align-items: center; gap: 6px; min-width: 0; }
.rq-avatar {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: .6rem; font-weight: 700; letter-spacing: .02em;
  background: var(--accent-soft); color: var(--accent-strong);
}
.rq-author {
  font-size: .8rem; font-weight: 500; color: var(--text-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rq-author-more {
  font-size: .65rem; font-weight: 600; padding: 1px 5px; border-radius: var(--radius-pill);
  background: var(--chip-bg); color: var(--chip-text); flex: 0 0 auto;
}
.rq-when {
  margin-left: auto; flex: 0 0 auto;
  display: inline-flex; align-items: center; gap: 4px;
  font-size: .72rem; color: var(--text-secondary); white-space: nowrap;
}
.rq-when i { opacity: .7; }

/* --- полоса состава: чем и насколько размечена запись --- */
.rq-bar {
  display: flex; height: 7px; border-radius: var(--radius-pill);
  background: var(--chip-bg);   /* дорожка = «не размечено» */
  overflow: hidden;
}
.rq-bar-seg { display: block; height: 100%; min-width: 2px; }
.rq-bar-seg + .rq-bar-seg { border-left: 1px solid var(--card-bg); }

/* Цвета видов сегментов — те же роли, что в редакторе: речь синяя (материал),
   неразборчивое янтарное (требует внимания), шум/тишина нейтральные, вырезанное
   красное и штрихованное (в датасет не попадёт). */
.rq-k-speech  { --rq-c: var(--accent); }
.rq-k-unclear { --rq-c: var(--warm); }
.rq-k-noise   { --rq-c: #94a3b8; }
.rq-k-silence { --rq-c: #cbd5e1; }
.rq-k-exclude { --rq-c: var(--danger); }
.rq-k-rest    { --rq-c: var(--text-muted); }
.rq-bar-seg.rq-k-speech, .rq-bar-seg.rq-k-unclear,
.rq-bar-seg.rq-k-noise,  .rq-bar-seg.rq-k-silence { background: var(--rq-c); }
.rq-bar-seg.rq-k-exclude {
  background: repeating-linear-gradient(45deg,
    var(--danger) 0 3px, transparent 3px 6px), var(--danger-soft);
}

.rq-legend, .rq-facts {
  display: flex; align-items: center; flex-wrap: wrap; gap: 4px 10px;
}
.rq-stat {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: .72rem; color: var(--text-secondary); white-space: nowrap;
}
.rq-stat i { font-size: .72rem; color: var(--rq-c, currentColor); opacity: .9; }
.rq-stat b { color: var(--text-primary); font-weight: 600; font-variant-numeric: tabular-nums; }
.rq-stat-dur { color: var(--text-muted); font-variant-numeric: tabular-nums; }

/* --- факты: спикеры / слова / языки / заметки / качество звука --- */
.rq-facts { gap: 4px 6px; }
.rq-fact {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: .7rem; padding: 2px 7px; border-radius: var(--radius-pill);
  background: var(--chip-bg); color: var(--chip-text); white-space: nowrap;
}
.rq-fact i { opacity: .8; }
.rq-fact b { color: var(--text-primary); }
.rq-fact-note   { background: var(--warm-soft);   color: var(--warm-strong); }
.rq-fact-dialog { background: var(--accent-soft); color: var(--accent-strong); }
/* «отчёты: нет» — генерация ещё не прошла: виден, но не спорит с остальным */
.rq-fact-none   { opacity: .65; }
.rq-fact-none b { color: inherit; font-weight: 500; }
.rq-lang-chip {
  font-size: .68rem; font-weight: 600; letter-spacing: .03em;
  padding: 2px 7px; border-radius: var(--radius-pill);
  border: 1px solid var(--border); color: var(--text-secondary); white-space: nowrap;
}
.rq-lang-chip b { color: var(--text-primary); font-weight: 600; }
/* Бейджи качества звука (App.qualityBadges) в общем ряду фактов. */
.rq-facts .badge { font-size: .68rem; font-weight: 500; }

/* --- превью текста: ровно две строки, чтобы карточки стояли в сетке --- */
.rq-preview {
  margin: auto 0 0; padding-top: 2px;
  font-size: .8125rem; line-height: 1.45; color: var(--text-secondary);
  overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.rq-preview-empty { color: var(--text-muted); }
.rq-empty-line { font-size: .75rem; color: var(--text-muted); }

/* --- подвал: дата загрузки слева (очередь идёт по ней), действия справа --- */
.rq-foot {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  padding: 10px 16px; border-top: 1px solid var(--border);
  background: var(--surface-sunken);
  border-radius: 0 0 var(--radius) var(--radius);
}
.rq-uploaded {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: .72rem; color: var(--text-muted); white-space: nowrap;
}
/* Кнопки — одной группой: в узкой колонке они переносятся ВМЕСТЕ и остаются
   прижатыми вправо, а не расползаются по разным краям подвала. */
.rq-actions { display: flex; gap: 6px; margin-left: auto; }
.rq-foot .btn { white-space: nowrap; }

/* --- очередь таблицей (09.10): строка = запись, те же блоки по колонкам --- */
.rq-trow { cursor: pointer; }
.rq-trow:hover > td { background: var(--surface-sunken); }
.rq-table td { vertical-align: top; }
.rq-table .rq-head { gap: 4px; margin-bottom: 2px; min-width: 170px; }
.rq-table .rq-uuid { font-size: .68rem; margin-left: 0; }
.rq-tsub { display: flex; align-items: center; gap: 8px; white-space: nowrap; }
.rq-table .rq-people { flex-wrap: wrap; min-width: 150px; max-width: 210px; }
.rq-table .rq-people .rq-when { flex-basis: 100%; margin-left: 30px; }
.rq-tcol-comp { min-width: 200px; max-width: 280px; }
.rq-tcol-comp .rq-bar { margin: 4px 0 5px; }
.rq-tcol-comp .rq-legend { gap: 2px 8px; }
.rq-tcol-facts { min-width: 210px; max-width: 300px; }
.rq-tcol-text { min-width: 180px; max-width: 340px; }
.rq-tpreview {
  font-size: .78rem; line-height: 1.4; color: var(--text-secondary);
  overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.rq-table .rq-actions { justify-content: flex-end; flex-wrap: nowrap; }
.rq-table .rq-actions .btn { white-space: nowrap; padding: 2px 8px; }
.rq-tgroup td {
  background: var(--surface-sunken-2); font-size: .8rem; color: var(--text-secondary);
  padding: 7px 10px; border-bottom: 1px solid var(--border);
}
.rq-tgroup td b { color: var(--text-primary); margin: 0 6px 0 4px; }

/* Тёмная тема: нейтрали видов сегментов слишком светлые на тёмной дорожке —
   сдвигаем в сторону фона, оставляя различимыми. Тонированные чипы (заметка /
   диалог / аватарка) несут ТЁМНЫЙ текст на светлой подложке — на тёмной их
   подложка полупрозрачная, а текст остаётся нечитаемым, поэтому осветляем его
   ровно так же, как у ds-flag-* выше. */
:root[data-theme="dark"] .rq-k-noise   { --rq-c: #64748b; }
:root[data-theme="dark"] .rq-k-silence { --rq-c: #475569; }
:root[data-theme="dark"] .rq-fact-note   { color: #fbbf24; }
:root[data-theme="dark"] .rq-fact-dialog { color: #a5b4fc; }
:root[data-theme="dark"] .rq-avatar      { color: #a5b4fc; }

#waveform { width: 100%; position: relative; }

/* WaveSurfer renders its horizontal scrollbar at the bottom of its own scroll
   container, which sat *inside* the waveform — right under the bottom marker
   band, so scrubbing the marker kept grabbing the scrollbar by accident. Push it
   clear of the waveform with bottom padding on the shadow part. Scoped to the
   zoned workspace (.wave-zoned is set by wave-shared) so other pages keep their
   existing layout. */
#waveform.wave-zoned > div::part(scroll) { padding-bottom: 12px; }

/* Gesture bands (wave-shared zonedInteraction): top = draw a selection,
   bottom = place the playback marker, middle = move a segment / pan the view.
   Guides are inert — they only make the bands legible; the cursor per band and
   the gestures themselves live in wave-shared.js. */
.wave-zone {
  pointer-events: none;
  z-index: 1;
  font-size: 9px;
  letter-spacing: .02em;
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
}
.wave-zone::after {
  content: attr(data-label);
  position: absolute;
  right: 6px;
  opacity: .75;
  font-weight: 600;
}
/* Временная линейка в полосе маркера (wave-shared.renderRuler): риски от
   нижнего края, подписи сверху. Инертна — жест «поставить курсор» живёт в той
   же полосе и должен доходить до неё нетронутым. */
#wave-ruler i {
  position: absolute; bottom: 0; width: 1px;
  background: var(--text-secondary); opacity: .55;
}
#wave-ruler b {
  position: absolute; top: 1px;
  font-size: 10px; font-weight: 600; line-height: 1;
  letter-spacing: .02em; white-space: nowrap;
  color: var(--text-secondary);
}

#wave-minimap { width: 100%; margin-top: 8px; border-top: 1px solid var(--border); padding-top: 8px; }

/* Зона нахлёста сегментов поверх вейвформы — как Adobe Audition штрихует область
   кроссфейда. Диагональная штриховка читается на любой заливке региона и сразу
   отличима от неё: заливка сплошная, нахлёст — полосатый. Мышь не ловит, под
   ней живут регионы со своими жестами. */
.wave-overlap {
  position: absolute;
  z-index: 3;
  pointer-events: none;
  background-image: repeating-linear-gradient(
    45deg,
    rgba(217, 119, 6, .30) 0, rgba(217, 119, 6, .30) 4px,
    rgba(217, 119, 6, 0)   4px, rgba(217, 119, 6, 0)   9px);
  border-left:  1px solid rgba(217, 119, 6, .55);
  border-right: 1px solid rgba(217, 119, 6, .55);
}

/* Критический нахлёст — с сегментом «Не добавлять»: его участок физически
   вырезается из аудио при экспорте, и сосед потеряет часть звука. Штриховка
   гуще и краснее, плюс знак «стоп» по центру полосы (::after), чтобы причина
   читалась без наведения мыши. */
.wave-overlap-crit {
  background-image: repeating-linear-gradient(
    45deg,
    rgba(220, 38, 38, .45) 0, rgba(220, 38, 38, .45) 5px,
    rgba(220, 38, 38, .10) 5px, rgba(220, 38, 38, .10) 10px);
  border-left:  2px solid rgba(220, 38, 38, .9);
  border-right: 2px solid rgba(220, 38, 38, .9);
}
/* Сам знак — настоящей иконкой из шрифта, а не ::after с кодпоинтом: подпись
   класса переживёт смену версии bootstrap-icons, кодпоинт — нет. Ставит его
   renderOverlapBands(). Полоса бывает уже иконки — она честно вылезает за
   границы, потому что спрятать её значило бы спрятать причину блокировки. */
.wave-overlap-mark {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 15px;
  line-height: 1;
  color: #fff;
  text-shadow: 0 0 3px rgba(0, 0, 0, .9), 0 0 6px rgba(220, 38, 38, .95);
}

/* Значок нахлёста в шапке карточки сегмента + рамка у критической карточки. */
.seg-overlap-flag { font-size: .72rem; }
.segment-card.seg-overlap-crit {
  outline: 1px solid var(--bs-danger, #dc2626);
  outline-offset: -1px;
}

/* ================================================================
   Замечания ревьюера к месту записи (core/review-issues.js)
   ================================================================ */
/* Участок на волне: пунктирные края во всю высоту + ярлык с номером в верхней
   полосе, где нет регионов сегментов. Сама рамка мышь не ловит — под ней
   регионы со своими жестами; кликается только ярлык. */
.wave-issue {
  position: absolute;
  z-index: 4;
  pointer-events: none;
  border-left:  2px dashed rgba(220, 38, 38, .85);
  border-right: 2px dashed rgba(220, 38, 38, .85);
  background: rgba(220, 38, 38, .06);
}
.wave-issue-tab {
  position: absolute; top: 0; left: -2px;
  min-width: 18px; padding: 0 5px;
  background: #dc2626; color: #fff;
  font-size: .66rem; font-weight: 700; text-align: center;
  border-radius: 0 0 4px 0;
  pointer-events: auto; cursor: pointer;
  white-space: nowrap;
}
.wave-issue.is-active { background: rgba(220, 38, 38, .16); }
.wave-issue.is-active .wave-issue-tab { box-shadow: 0 0 0 2px rgba(220, 38, 38, .35); }
.wave-issue.is-resolved { border-color: rgba(22, 163, 74, .7); background: rgba(22, 163, 74, .05); }
.wave-issue.is-resolved .wave-issue-tab { background: #16a34a; }

/* Флажок в шапке карточки и рамка карточки с неисправленным замечанием. */
.seg-issue-flag { font-size: .72rem; color: var(--danger); }
.seg-issue-flag.is-resolved { color: var(--success); }
.segment-card.seg-has-issue { box-shadow: inset 3px 0 0 var(--danger); }
.seg-issue-add { color: var(--text-muted); font-size: .8rem; line-height: 1; }
.seg-issue-add:hover { color: var(--danger); }

/* Строка замечания — одна разметка в карточке и в списке панели. */
.seg-issues { padding: 4px 10px 2px; display: flex; flex-direction: column; gap: 4px; }
.ri-item {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 6px 8px;
  border-radius: var(--radius-sm);
  background: var(--danger-soft);
  border: 1px solid rgba(220, 38, 38, .25);
  font-size: .8rem;
}
.ri-item.is-active { border-color: var(--danger); box-shadow: 0 0 0 2px rgba(220, 38, 38, .18); }
.ri-item.is-resolved { background: var(--success-soft); border-color: rgba(22, 163, 74, .3); }
.ri-item.is-resolved .ri-text { text-decoration: line-through; opacity: .7; }
.ri-num {
  flex-shrink: 0; min-width: 22px; height: 22px; padding: 0 5px;
  border: 0; border-radius: 11px;
  background: var(--danger); color: #fff;
  font-size: .7rem; font-weight: 700; cursor: pointer;
}
.ri-item.is-resolved .ri-num { background: var(--success); }
.ri-body { flex: 1; min-width: 0; cursor: pointer; }
.ri-target { font-size: .72rem; color: var(--text-secondary); margin-bottom: 1px; }
.ri-text { white-space: pre-line; color: var(--text-primary); line-height: 1.4; }
.ri-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.ri-btn { font-size: .9rem; line-height: 1; }
.ri-resolve { display: flex; align-items: center; gap: 4px; margin: 0; cursor: pointer;
              font-size: .75rem; color: var(--text-secondary); white-space: nowrap; }
.ri-resolve .form-check-input { margin: 0; }
.ri-badge-ok { color: var(--success); font-weight: 600; font-size: .7rem; margin-left: 4px; }
.ri-empty { font-size: .8rem; padding: 4px 2px; }
.ri-list { display: flex; flex-direction: column; gap: 6px; }

/* Окно ввода замечания у места, где его ставят. */
.ri-editor {
  position: fixed; z-index: 1080;
  width: min(380px, calc(100vw - 16px));
  padding: 10px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
}
.ri-editor-title { font-size: .78rem; font-weight: 600; color: var(--danger); margin-bottom: 6px; }
.ri-editor-foot { display: flex; align-items: center; gap: 6px; margin-top: 8px; }
.ri-editor-foot .text-muted { font-size: .7rem; margin-right: auto; }

/* Регион речи без спикера/языка — красная рамка поверх штриховки (заливку
   ставит annotator.regionColor, класс — wave-shared renderManualRegion). */
.mreg-flagged { box-shadow: inset 0 0 0 2px rgba(220, 38, 38, .9); }

/* Segment number badge drawn over each manual region overlay (mreg-*). Pinned to
   the region's top, centered; readable over any region colour; never blocks the
   region's pointer interactions. Overflows narrow regions instead of clipping. */
.mreg-num {
  position: absolute;
  top: 1px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 3;
  pointer-events: none;
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  padding: 1px 4px;
  border-radius: 4px;
  color: #fff;
  background: rgba(0, 0, 0, .55);
  white-space: nowrap;
}
.mreg-num .bi { font-size: 10px; vertical-align: middle; }

/* Duration label drawn over each manual region overlay, pinned to the bottom.
   Same readable pill as .mreg-num; overflows narrow regions instead of clipping. */
.mreg-dur {
  position: absolute;
  bottom: 1px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 3;
  pointer-events: none;
  font-size: 9px;
  font-weight: 600;
  line-height: 1;
  padding: 1px 4px;
  border-radius: 4px;
  color: #fff;
  background: rgba(0, 0, 0, .45);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* Строка под волной (общие куски — _wave_transport.html, _wave_eq.html).
   Сетка 1fr/auto/1fr, а не flex: транспорт стоит ровно по центру панели
   независимо от того, насколько широк блок эквалайзера справа. */
.wave-controls {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
}
.wave-transport {
  grid-column: 2;
  display: flex; align-items: center; justify-content: center; gap: 8px;
}
.wave-eq {
  grid-column: 3;
  display: flex; align-items: center; justify-content: flex-end;
  gap: 6px; flex-wrap: wrap;
}
/* Пока места хватает, play стоит на оси панели — под плашкой времени. Как
   только блоку эквалайзера перестаёт хватать его колонки (а это ~1400px с
   учётом сайдбара), симметрия обходится дороже, чем стоит: строка становится
   обычной — транспорт слева, эквалайзер справа. */
@media (max-width: 1399.98px) {
  .wave-controls { display: flex; flex-wrap: wrap; gap: 6px 12px; }
  .wave-transport { order: 1; grid-column: auto; }
  .wave-eq       { order: 2; grid-column: auto; margin-left: auto; }
}

/* Все кнопки строки — одного размера: одна высота, один шрифт, play тоже (он
   выделен цветом, а не величиной). */
.wave-controls .btn {
  height: 28px; padding: 0 .55rem;
  font-size: .78rem; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
}
.btn-play-main { min-width: 44px; font-size: 1.05rem; }
.btn-play-main:active { transform: scale(.96); }

/* ================================================================
   Журнал действий редактора (core/edit-journal.js)
   ================================================================ */
/* Play — опора для надписи «журнал (N) ↓» под ним и панели. Надпись стоит
   абсолютно, чтобы не сдвигать play с оси строки; место под неё строка
   добирает нижним отступом, пока надпись видна. */
.wave-play-wrap { position: relative; display: flex; justify-content: center; }
.wave-controls:has(.wave-journal-toggle:not(.d-none)) { margin-bottom: 14px; }
.wave-journal-toggle {
  position: absolute; top: calc(100% + 1px); left: 50%; transform: translateX(-50%);
  padding: 0 4px; border: 0; background: none;
  font-size: .68rem; line-height: 1.2; white-space: nowrap;
  color: var(--text-muted); cursor: pointer;
}
.wave-journal-toggle:hover,
.wave-journal-toggle[aria-expanded="true"] { color: var(--accent); }
.wave-journal-toggle .bi { font-size: .6rem; transition: transform .18s ease; }
.wave-journal-toggle[aria-expanded="true"] .bi { transform: rotate(180deg); }

.journal-panel {
  position: absolute; top: calc(100% + 20px); left: 50%;
  z-index: 60;
  width: min(460px, calc(100vw - 32px));
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
  opacity: 0; visibility: hidden;
  transform: translate(-50%, -6px);
  transition: opacity .16s ease, transform .16s ease, visibility 0s linear .16s;
}
.journal-panel.is-open {
  opacity: 1; visibility: visible;
  transform: translate(-50%, 0);
  transition: opacity .16s ease, transform .16s ease, visibility 0s;
}
@media (max-width: 1399.98px) {
  .journal-panel { left: 0; transform: translate(0, -6px); }
  .journal-panel.is-open { transform: translate(0, 0); }
}
.ej-head {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px 4px 12px;
}
.ej-title { font-size: .82rem; font-weight: 600; color: var(--text-primary); }
.ej-head-actions { margin-left: auto; display: flex; gap: 4px; align-items: center; }
.ej-head-actions .btn { height: 26px; padding: 0 .5rem; font-size: .8rem; }
.ej-close { color: var(--text-muted); }
.ej-hint { padding: 0 12px 6px; font-size: .7rem; color: var(--text-muted); }
.ej-list {
  max-height: min(55vh, 440px); overflow-y: auto;
  border-top: 1px solid var(--border);
  padding: 4px;
}
.ej-row {
  display: grid; grid-template-columns: 18px 1fr auto auto; align-items: center; gap: 8px;
  width: 100%; padding: 6px 8px;
  border: 0; border-radius: 6px; background: none; text-align: left;
  font-size: .79rem; color: var(--text-primary); cursor: pointer;
}
.ej-row:hover { background: var(--surface-sunken); }
.ej-row.is-current { background: var(--accent-soft); }
.ej-row.is-current .ej-label { font-weight: 600; }
.ej-row.is-undone { color: var(--text-muted); }
.ej-row.is-undone .ej-label { text-decoration: line-through; text-decoration-color: var(--border-input); }
.ej-icon { color: var(--text-secondary); font-size: .85rem; text-align: center; }
.ej-row.is-current .ej-icon { color: var(--accent); }
.ej-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ej-time { font-size: .7rem; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.ej-tag {
  font-size: .64rem; padding: 1px 6px; border-radius: 9px;
  background: var(--surface-sunken); color: var(--text-muted);
}
.ej-tag-now { background: var(--accent); color: #fff; }

/* Скорость и громкость — зеркальные группы по бокам от play: значок слева,
   [−] [значение] [+]. Ширина значения постоянная — play не гуляет по оси,
   когда «1×» сменяется на «1.25×». */
.wave-level { display: flex; align-items: center; gap: 5px; }
.wave-level-title { font-size: .9rem; line-height: 1; color: var(--text-muted); }
.wave-controls .wave-level-val  { min-width: 50px; font-weight: 600; }
.wave-controls .wave-level-step { min-width: 28px; padding: 0; font-weight: 600; }

/* Время — плашка поверх верхней полосы волны. Высота = WAVE_SAFE_ZONE (34px,
   annotator.js): плашка занимает полосу «выделение» целиком, но мышь не ловит,
   поэтому выделение тянется прямо сквозь неё. */
#waveform > .time-display {
  position: absolute;
  top: 0; left: 50%; transform: translateX(-50%);
  z-index: 5;
  pointer-events: none;
  height: 34px;
  display: inline-flex; align-items: center;
  padding: 0 14px;
  /* Без заливки: полоса «выделение» под ней — рабочая, и плашка не должна
     выглядеть накладкой поверх волны. */
  background: none;
  font-family: var(--font-mono);
  font-size: 1rem; font-weight: 600; letter-spacing: .01em;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ================================================================
   Segment cards
   ================================================================ */
.segments-panel { display: flex; flex-direction: column; gap: 2px; }

.segment-card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  transition: box-shadow .15s, border-color .15s, transform .12s;
}

/* Речь спикера — полоса его цвета слева и лёгкий градиент от неё, как у
   реплики в «Создании датасета» (.synth-turn.speech.voiced). --spk и класс
   ставит annotator.paintSegCardSpeaker; шапка тогда прозрачная — цвет несёт
   карточка. Правила стоят ДО .active/.seg-playing/.seg-invalid: их подсветка
   важнее принадлежности. */
.segment-card.seg-speech {
  border-left: 4px solid var(--spk);
  background: linear-gradient(90deg, color-mix(in srgb, var(--spk) 6%, var(--card-bg)), var(--card-bg) 40%);
}
.segment-card.seg-speech > .segment-card-header { background: transparent; }

/* Selected segment — strong, unmistakable highlight (single source of truth). */
.segment-card.active {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(37,99,235,.30), 0 10px 24px -10px rgba(37,99,235,.6);
}
.segment-card.active .segment-card-header {
  background: var(--accent-light);
  box-shadow: inset 4px 0 0 var(--accent);
}
.segment-card.active .seg-num { box-shadow: 0 0 0 2px rgba(37,99,235,.4); }
.segment-card.seg-speech.active { border-left-color: var(--spk); }

/* Play cursor — the segment under the playhead during whole-track playback.
   Green so it reads as "now playing", distinct from the blue selection. */
.segment-card.seg-playing {
  border-color: #16a34a;
  box-shadow: 0 0 0 2px rgba(22,163,74,.30);
}
.segment-card.seg-playing .segment-card-header {
  background: rgba(22,163,74,.09);
  box-shadow: inset 4px 0 0 #16a34a;
  animation: seg-playing-pulse 1.3s ease-in-out infinite;
}
@keyframes seg-playing-pulse {
  0%, 100% { box-shadow: inset 4px 0 0 #16a34a; }
  50%      { box-shadow: inset 4px 0 0 rgba(22,163,74,.45); }
}

/* Незаполненное обязательное поле. Спикер/язык — сразу, пока размечают
   (annotator.paintSegRequired), текст — после попытки сдать. Шапка
   красится вместе с полем: свёрнутая карточка иначе ничем не выдаёт, что
   проблема в ней, и приходится разворачивать все подряд. !important — потому
   что фон шапки ставится инлайном по цвету спикера (updateSegHeaderColor). */
.segment-card.seg-invalid {
  border-color: #dc2626;
  box-shadow: 0 0 0 3px rgba(220,38,38,.32);
}
/* Шапка красится ЦЕЛИКОМ: у свёрнутой карточки она — единственное, что видно,
   и слабый оттенок поверх цвета спикера просто теряется. !important на фоне и
   левой полосе — их ставит инлайном updateSegHeaderColor по цвету спикера, а
   «здесь не заполнено» важнее принадлежности. */
.segment-card.seg-invalid .segment-card-header {
  background: rgba(220,38,38,.22) !important;
  border-left-color: #dc2626 !important;
  box-shadow: inset 4px 0 0 #dc2626;
}
.segment-card.seg-invalid .seg-time { color: #b91c1c; font-weight: 600; }
:root[data-theme="dark"] .segment-card.seg-invalid .segment-card-header {
  background: rgba(220,38,38,.32) !important;
}
:root[data-theme="dark"] .segment-card.seg-invalid .seg-time { color: #fca5a5; }
.seg-invalid-flag { font-size: .72rem; color: #dc2626; }

.segment-card-header {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 12px;
  background: var(--surface-sunken);
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  user-select: none;
}

.seg-num-wrap { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
.seg-num {
  width: 22px; height: 22px; border-radius: 4px;
  display: flex; align-items: center; justify-content: center;
  font-size: .7rem; font-weight: 600; flex-shrink: 0;
  background: var(--border); color: var(--text-secondary);
}
.seg-del-btn { color: #9ca3af; line-height: 1; }
.seg-del-btn:hover { color: #dc2626; }
/* Large, prominent in-body "Воспроизвести" button */
.seg-play-big { font-weight: 600; }
.seg-play-big.seg-play-active {
  color: #16a34a !important;
  border-color: #16a34a !important;
  background: rgba(22, 163, 74, .08);
}
/* Segment play button: green + pulsing icon while that segment is playing */
[data-play-seg].seg-play-active { color: #16a34a !important; }
[data-play-seg].seg-play-active i { animation: seg-play-pulse 1.1s ease-in-out infinite; }
@keyframes seg-play-pulse { 0%,100% { opacity: 1; } 50% { opacity: .55; } }
/* One badge colour per speaker in SPEAKERS (app/constants.py, 1–10). The hues
   mirror core/speaker-colors.js — keep the two lists in step. */
.seg-num.spk1  { background: rgba(37,  99,235,.15); color: #1d4ed8; }
.seg-num.spk2  { background: rgba(249,115, 22,.15); color: #c2410c; }
.seg-num.spk3  { background: rgba(22, 163, 74,.15); color: #15803d; }
.seg-num.spk4  { background: rgba(220, 38, 38,.15); color: #b91c1c; }
.seg-num.spk5  { background: rgba(147, 51,234,.15); color: #7e22ce; }
.seg-num.spk6  { background: rgba(8,  145,178,.15); color: #0e7490; }
.seg-num.spk7  { background: rgba(161, 98,  7,.15); color: #854d0e; }
.seg-num.spk8  { background: rgba(219, 39,119,.15); color: #be185d; }
.seg-num.spk9  { background: rgba(101,163, 13,.15); color: #4d7c0f; }
.seg-num.spk10 { background: rgba(67,  56,202,.15); color: #3730a3; }
.seg-num.nonspeech { background: rgba(107,114,128,.15); color: #6b7280; }

.seg-time {
  font-family: var(--font-mono);
  font-size: .75rem;
  color: var(--text-muted);
  min-width: 168px;
  white-space: nowrap;
  flex-shrink: 0;
}
/* Начало/конец в шапке — поля, неотличимые от текста: та же моно-строка, без
   рамки и фона. Что их можно править, выдают только курсор-каретка, пунктир
   при наведении и подсветка в фокусе. */
.seg-time-inp {
  font: inherit; color: inherit; background: transparent;
  border: 0; border-bottom: 1px dashed transparent; border-radius: 0;
  padding: 0; margin: 0; width: 10ch; line-height: inherit;
  cursor: text; outline: none;
}
.seg-time-inp:hover { border-bottom-color: currentColor; }
.seg-time-inp:focus {
  color: var(--text-primary); background: var(--card-bg);
  border-bottom-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft);
}

.segment-card-body { padding: 8px 10px; }

/* Шапка карточки = строка мини-волны (core/seg-card.js headHtml): номер,
   время, ▶, мини-волна на всё свободное место, значки и стрелка справа. */
.seg-miniwave-row { display: flex; align-items: center; gap: 6px; }
.segment-card-header.seg-miniwave-row { padding: 5px 10px; }
.seg-head-flags { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
.seg-miniwave { flex: 1 1 0; min-width: 0; display: block; border-radius: 4px;
                background: transparent; cursor: pointer; }
.seg-play-mini {
  flex: 0 0 auto; width: 32px; height: 32px; padding: 0; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center; font-size: 1.05rem;
}
.seg-play-mini .bi { margin: 0 !important; }

/* Collapse chevron is the only collapse affordance (header click = select). */
.seg-collapse-toggle { cursor: pointer; padding: 2px 4px; border-radius: 4px; }
.seg-collapse-toggle:hover { background: rgba(0,0,0,.06); color: var(--text-secondary) !important; }

.seg-fields-noise  { display: grid; grid-template-columns: 200px; gap: 8px; }

.seg-text-wrap { margin-top: 6px; }
.seg-text { font-size: .875rem; }

/* Карточка сегмента (разметка и ревью, core/seg-card.js): две колонки — слева
   тип и свойства реплики стопкой, справа текст на всю их высоту (растёт и
   дальше, если длиннее) или вид шума. */
.seg-cols { display: flex; gap: 12px; align-items: stretch; }
.seg-col-meta, .seg-cols .seg-fields-speech { display: flex; flex-direction: column; gap: 6px; }
.seg-col-meta { flex: 0 0 240px; min-width: 0; }
.seg-col-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.seg-cols .seg-text-wrap { margin-top: 0; flex: 1 1 auto; display: flex; flex-direction: column; }
.seg-cols .seg-text { flex: 1 1 auto; font-size: .95rem; line-height: 1.5; }
@media (max-width: 767px) {
  .seg-cols { flex-direction: column; }
  .seg-col-meta { flex-basis: auto; }
}

.seg-actions { margin-top: 8px; display: flex; justify-content: flex-end; gap: 6px; }

/* ================================================================
   Empty state
   ================================================================ */
.empty-state {
  display: flex; flex-direction: column; align-items: center;
  justify-content: center;
  padding: 60px 24px; text-align: center;
}
.empty-state-icon { font-size: 3rem; color: var(--text-muted); margin-bottom: 16px; }
.empty-state-title { font-size: 1.1rem; font-weight: 600; margin-bottom: 8px; }
.empty-state-desc { color: var(--text-secondary); margin-bottom: 24px; font-size: .9rem; }

/* ---- Пустое состояние /transcription: «где я» слева, «что делать» справа ---- */
/* Блок содержательный, а не «пусто» — заголовка и центральной иконки здесь
   больше нет, поэтому и вертикального воздуха под них не нужно */
#state-empty.empty-state { padding: 8px 24px 40px; }
/* Плашка-уведомление: показывается только когда есть что сказать
   (задание перехватили / пул пуст) — см. setEmptyNotice() */
.empty-notice {
  width: 100%; max-width: 1480px; margin-bottom: 16px;
  padding: 10px 14px; border-radius: 10px; text-align: left;
  font-size: .875rem; color: var(--text-secondary);
  background: var(--card-bg); border: 1px solid var(--border);
}
.empty-notice.is-warning {
  color: #b45309; background: #fff7ed; border-color: #fed7aa;
}
[data-theme="dark"] .empty-notice.is-warning {
  color: #fbbf24; background: rgba(217, 119, 6, .14); border-color: rgba(217, 119, 6, .45);
}
.idle-grid {
  display: grid; gap: 20px; align-items: start; text-align: left;
  /* Рейтинг | мои данные | кнопки. Гейм-бар — самый плотный, ему больше места. */
  grid-template-columns: minmax(0, 1fr) minmax(360px, 1.3fr) minmax(250px, .85fr);
  grid-template-areas: "board me act";
  width: 100%; max-width: 1480px;
}
.idle-board   { grid-area: board; }
.idle-me      { grid-area: me; }
.idle-actions { grid-area: act; }
.idle-col { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
/* Кнопки — на всю ширину своей колонки, порядок = приоритет. Отступ
   между ними меньше общего gap. */
.idle-actions { gap: 10px; }
.idle-actions .btn { width: 100%; justify-content: center; }
/* ---- Отстранение от новой разметки (5+ висящих возвратов) ---- */
/* Плашка-объяснение над кнопками: почему они больше не работают */
.idle-suspended-note {
  padding: 10px 14px; border-radius: 10px; text-align: left;
  font-size: .85rem; font-weight: 600; line-height: 1.4;
  color: var(--danger); background: var(--danger-soft);
  border: 1px solid var(--danger);
}
/* Кнопки получения работы остаются на месте (видно, что именно закрыто), но
   красные и неактивные. Специфичность .idle-actions .btn.is-locked перебивает
   .btn-primary / .btn-outline-*, поэтому исходные классы не трогаем. */
.idle-actions .btn.is-locked,
.idle-actions .btn.is-locked:hover,
.idle-actions .btn.is-locked:focus {
  color: var(--danger); background: var(--danger-soft);
  border-color: var(--danger);
  opacity: 1; cursor: not-allowed; box-shadow: none; transform: none;
}
.idle-lb-head {
  display: flex; align-items: center; justify-content: space-between;
  font-size: .875rem; font-weight: 600;
}
.idle-lb-note { font-size: .72rem; font-weight: 500; color: var(--text-muted); }
/* Длинный список не должен растягивать страницу — прокручиваем внутри карточки */
.idle-lb .card-body { max-height: min(70vh, 620px); overflow-y: auto; }

/* Сводка датасета на экране задания (админ/ревьювер, annotator.js
   renderDatasetSummary): три плитки + таблица по корпусам по кнопке. */
/* Сводка датасета — кнопка в строке вкладок + выпадающая панель. В задании
   строку занимает тулбар записи, сводка там не нужна. */
.idle-ds-chip { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.idle-ds-chip b { font-variant-numeric: tabular-nums; }
#task-toolbar:not(.d-none) ~ #idle-dataset { display: none !important; }
.idle-ds-pop {
  width: 560px; max-width: calc(100vw - 24px); padding: 0;
  border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden;
}
.idle-ds-pop-head {
  padding: 10px 14px; border-bottom: 1px solid var(--border); background: var(--surface-sunken);
}
#idle-dataset-body { padding: 12px 14px; max-height: min(70vh, 560px); overflow-y: auto; }
.idle-ds-head-right { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }
.idle-ds-refresh {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 0; font-size: .74rem; font-weight: 600; text-decoration: none;
  color: var(--accent); white-space: nowrap;
}
.idle-ds-refresh:hover { text-decoration: underline; }
.idle-ds-refresh:disabled { color: var(--text-muted); opacity: 1; }
.idle-ds-refresh.is-spinning .bi { animation: idle-ds-spin .9s linear infinite; }
@keyframes idle-ds-spin { to { transform: rotate(360deg); } }
@media (max-width: 520px) { .idle-ds-head-right .idle-lb-note { display: none; } }
.idle-ds-tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.idle-ds-tile {
  border: 1px solid var(--border); border-radius: var(--radius-sm, 8px);
  padding: 8px 10px; background: var(--surface-sunken); min-width: 0;
}
.idle-ds-tile-title { font-size: .72rem; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.idle-ds-tile-big { font-size: 1.15rem; font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1.3; }
.idle-ds-tile-big small { font-size: .72rem; font-weight: 500; color: var(--text-muted); }
.idle-ds-tile-sub { font-size: .72rem; color: var(--text-secondary); }
.idle-ds-tile.train .idle-ds-tile-big { color: var(--success); }
.idle-ds-tile.gold  .idle-ds-tile-big { color: var(--warm-strong); }
.idle-ds-tile.useful .idle-ds-tile-big { color: #be185d; }
:root[data-theme="dark"] .idle-ds-tile.useful .idle-ds-tile-big { color: #f9a8d4; }
.idle-ds-table-wrap { max-height: 340px; overflow-y: auto; margin-top: 4px; }
.idle-ds-table { font-size: .78rem; font-variant-numeric: tabular-nums; }
.idle-ds-table th { font-weight: 600; color: var(--text-muted); position: sticky; top: 0; background: var(--card-bg); }
.idle-ds-kind td { font-size: .7rem; font-weight: 600; text-transform: uppercase; letter-spacing: .03em;
                   color: var(--text-muted); background: var(--surface-sunken); }
.idle-ds-name { max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 520px) { .idle-ds-tiles { grid-template-columns: minmax(0, 1fr); } }

/* Средний экран: мои данные и кнопки рядом, рейтинг — под ними на всю ширину. */
@media (max-width: 1199px) {
  .idle-grid {
    grid-template-columns: minmax(0, 1.3fr) minmax(240px, .9fr);
    grid-template-areas: "me act" "board board";
  }
}
/* Узкий: одна колонка, кнопки важнее всего — наверх. */
@media (max-width: 767px) {
  .idle-grid {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "act" "me" "board";
  }
}
@media (max-width: 767px) {
  #state-empty.empty-state { padding: 24px 12px; }
}

/* ================================================================
   Toast / Alert
   ================================================================ */
.toast-container {
  position: fixed; top: 16px; right: 16px; z-index: 9999;
  display: flex; flex-direction: column; gap: 8px;
  pointer-events: none;
}

.app-toast {
  background: var(--card-bg); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 12px 16px;
  display: flex; align-items: center; gap: 10px;
  min-width: 260px; max-width: 380px;
  pointer-events: all;
  animation: slideIn .2s ease;
}

@keyframes slideIn {
  from { transform: translateX(40px); opacity: 0; }
  to   { transform: translateX(0);    opacity: 1; }
}

.app-toast.toast-success { border-left: 3px solid var(--success); }
.app-toast.toast-error   { border-left: 3px solid var(--danger); }
.app-toast.toast-warning { border-left: 3px solid var(--warning); }
.app-toast.toast-info    { border-left: 3px solid var(--accent); }

/* ================================================================
   Stats / Charts
   ================================================================ */
.stat-card {
  background: var(--card-bg); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 20px; text-align: center;
}
.stat-value { font-size: 2rem; font-weight: 700; color: var(--text-primary); line-height: 1; }
.stat-label { font-size: .8rem; color: var(--text-secondary); margin-top: 4px; }

/* ================================================================
   Hotkeys modal
   ================================================================ */
.hotkey-table td:first-child {
  font-family: var(--font-mono); font-size: .78rem;
  white-space: nowrap; color: var(--accent);
}

/* ================================================================
   Admin tables
   ================================================================ */
.table-actions { display: flex; gap: 6px; flex-wrap: wrap; }

/* Source status bar */
.status-bar {
  display: flex; gap: 1px; height: 6px; border-radius: 3px; overflow: hidden;
}
.status-bar-segment { flex-shrink: 0; transition: width .3s; }

/* ================================================================
   Responsive — mobile
   ================================================================ */
@media (max-width: 767px) {
  .sidebar {
    transform: translateX(-100%);
    transition: transform .25s ease;
  }
  .sidebar.mobile-open { transform: translateX(0); }

  .main-wrapper { margin-left: 0 !important; }

  .page-header { padding: 16px 16px 0; }
  .page-content { padding: 16px; }


  .auth-card { padding: 24px 20px; }
}

/* ================================================================
   Misc helpers
   ================================================================ */
.mono { font-family: var(--font-mono); }
.text-muted-sm { font-size: .78rem; color: var(--text-muted); }
.gap-8 { gap: 8px; }

/* Scrollbars */
::-webkit-scrollbar { width: 5px; height: 5px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #d1d5db; border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: #9ca3af; }

/* ================================================================
   Sidebar collapse/expand toggle button (desktop)
   ================================================================ */
.sidebar-collapse-btn {
  width: 28px;
  height: 28px;
  padding: 0;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--card-bg);
  border: 1px solid var(--border);
  box-shadow: 0 1px 4px rgba(0,0,0,.10);
  color: var(--text-secondary);
  cursor: pointer;
  font-size: .7rem;
  line-height: 1;
  transition: background .15s, box-shadow .15s, color .15s, border-color .15s;
}

.sidebar-collapse-btn:hover {
  background: var(--body-bg);
  box-shadow: 0 2px 6px rgba(0,0,0,.14);
  color: var(--text-primary);
  border-color: #c5cbd3;
}

.sidebar-collapse-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Mobile overlay when sidebar is open */
.sidebar-overlay {
  display: none;
  position: fixed; inset: 0;
  background: rgba(0,0,0,.4);
  z-index: 99;
}
@media (max-width: 767px) {
  .sidebar-overlay.visible { display: block; }
}

/* ================================================================
   Connection-lost blocking overlay (periodic /health check)
   ================================================================ */
.conn-lost-overlay {
  position: fixed; inset: 0; z-index: 100000;
  display: flex; align-items: center; justify-content: center;
  background: rgba(15, 23, 42, .88);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
}
.conn-lost-box { text-align: center; color: #fff; max-width: 420px; padding: 28px 32px; }
.conn-lost-icon { font-size: 2.75rem; color: #f87171; margin-bottom: 12px; line-height: 1; }
.conn-lost-title { font-weight: 700; margin-bottom: 8px; }
.conn-lost-text { font-size: .95rem; opacity: .92; }
.conn-lost-text b { font-variant-numeric: tabular-nums; }

/* ================================================================
   Audio-loading blocking overlay (App.withAudioLoading)
   Blocks the UI while audio is fetched for playback. The `--silent`
   modifier keeps it transparent (but still pointer-capturing) for the
   first 2s, so quick loads never flash a modal.
   ================================================================ */
.audio-loading-overlay {
  position: fixed; inset: 0; z-index: 99000;
  display: flex; align-items: center; justify-content: center;
  background: rgba(15, 23, 42, .6);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  transition: background .15s ease;
}
.audio-loading-overlay.audio-loading-overlay--silent {
  background: transparent;
  -webkit-backdrop-filter: none; backdrop-filter: none;
}
.audio-loading-overlay.audio-loading-overlay--silent .audio-loading-box {
  display: none;
}
.audio-loading-box {
  display: flex; flex-direction: column; align-items: center; gap: .65rem;
  padding: 1.75rem 2rem; background: #1e293b; border-radius: 14px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, .45);
  width: min(420px, calc(100vw - 32px));
}
.audio-loading-box .spinner-border { margin-bottom: .35rem; }
.audio-loading-title { color: #fff; font-size: 1rem; font-weight: 600; }
.audio-loading-name {
  color: #e2e8f0; font-size: .875rem; font-weight: 500; text-align: center;
  max-width: 100%; word-break: break-word; line-height: 1.3;
}
.audio-loading-name:empty { display: none; }
.audio-loading-meta {
  color: #94a3b8; font-size: .75rem; text-align: center;
  font-variant-numeric: tabular-nums;
}
.audio-loading-meta:empty { display: none; }
.audio-loading-progress {
  width: 100%; height: 8px; margin-top: .35rem;
  background: rgba(148, 163, 184, .25); border-radius: 6px; overflow: hidden;
}
.audio-loading-progress .progress-bar {
  background: #3b82f6; transition: width .15s ease;
}

/* ================================================================
   Gamification — гейм-бар, достижения, конфетти
   ================================================================ */
/* Гейм-бар — вертикальные секции: шапка (уровень) → дневной рубеж → факты →
   мелкая мета. Раньше всё жило в одной переносящейся строке .gami-titlerow. */
.gamebar {
  display: flex; flex-direction: column; gap: 14px;
  padding: 18px 22px;
  border-radius: 14px;
  text-align: left;
  background:
    radial-gradient(120% 140% at 0% 0%, rgba(37,99,235,.12), transparent 55%),
    radial-gradient(120% 140% at 100% 100%, rgba(249,115,22,.10), transparent 55%),
    var(--card-bg);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
}
.gamebar-compact { padding: 14px 16px; gap: 12px; }
.gami-head { display: flex; align-items: center; gap: 18px; }
.gamebar-compact .gami-head { gap: 14px; }
.gami-head-main { flex: 1; min-width: 0; }

/* Круг уровня с кольцом прогресса (conic-gradient по --pct) */
.gami-level { flex-shrink: 0; }
.gami-ring {
  --sz: 92px;
  width: var(--sz); height: var(--sz); border-radius: 50%;
  display: grid; place-items: center;
  background:
    conic-gradient(var(--accent) calc(var(--pct) * 1%), var(--border) 0);
  transition: background .6s ease;
}
.gamebar-compact .gami-ring { --sz: 76px; }
.gami-badge {
  width: calc(var(--sz) - 12px); height: calc(var(--sz) - 12px);
  border-radius: 50%; background: var(--card-bg);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1px; box-shadow: inset 0 0 0 1px var(--border);
}
.gami-emoji { font-size: 1.7rem; line-height: 1; }
.gamebar-compact .gami-emoji { font-size: 1.4rem; }
.gami-lvlnum {
  font-size: .64rem; font-weight: 700; letter-spacing: .02em;
  color: var(--accent); text-transform: uppercase;
}

.gami-titlerow { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
.gami-rank { font-size: 1.15rem; font-weight: 700; color: var(--text-primary); }
/* Кнопка профиля всегда прижата к правому краю шапки */
.gami-titlerow .gami-profile-btn { margin-left: auto; }

/* Факты — сетка плиток «значение / подпись» */
.gami-facts {
  display: grid; gap: 8px;
  grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
}
.gami-fact {
  display: flex; flex-direction: column; gap: 2px;
  padding: 8px 10px; border-radius: 9px;
  background: var(--body-bg); box-shadow: inset 0 0 0 1px var(--border);
}
.gami-fact-v {
  font-size: .95rem; font-weight: 700; color: var(--text-primary);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.gami-fact-k {
  font-size: .68rem; font-weight: 600; color: var(--text-secondary);
  text-transform: uppercase; letter-spacing: .02em; line-height: 1.25;
}
.gami-fact.is-speech .gami-fact-v { color: var(--accent); }
.gami-fact.is-review .gami-fact-v { color: #d97706; }
.gami-fact.is-returned .gami-fact-v { color: var(--danger, #dc2626); }

/* Мета-строка: сегменты по видам, спикеры, языки — мелким, одной строкой */
.gami-meta {
  display: flex; flex-wrap: wrap; gap: 6px 14px;
  font-size: .74rem; font-weight: 600; color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}
.gami-meta-item { display: inline-flex; gap: 8px; white-space: nowrap; }
.gami-chip {
  font-size: .72rem; font-weight: 600; padding: 2px 9px; border-radius: 999px;
  background: var(--accent-light); color: var(--accent); white-space: nowrap;
}
.gami-chip-streak { background: #fff7ed; color: #c2410c; }
.gami-chip-tempo { background: #eef2ff; color: #4338ca; }

/* «Какие записи получать» — язык сегментами + галочка (core/audio-prefs.js) */
.gami-prefs {
  display: flex; flex-direction: column; gap: 8px;
  padding-top: 12px; border-top: 1px solid var(--border);
}
.gami-prefs.is-busy { opacity: .6; pointer-events: none; }
/* Тот же блок отдельной карточкой над кнопками в /transcription. */
.gami-prefs.idle-prefs {
  padding: 12px 14px; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--card-bg); box-shadow: var(--shadow-sm); margin-bottom: 6px;
}
.gami-prefs.idle-prefs:empty { display: none; }

/* ---- «Правила разметки» / «Примеры разметки» в /transcription ----
   Специально кричащие: залитые градиентом, с пульсирующим ореолом. В колонке
   действий — блоком над кнопками получения работы, в строке вкладок — чипами
   (видны и посреди задания). */
.learn-box {
  display: flex; flex-direction: column; gap: 8px;
  padding: 12px; border-radius: 12px;
  background: var(--warm-soft);
  border: 2px dashed var(--warm);
}
.learn-box-title {
  font-size: .85rem; font-weight: 700; line-height: 1.35;
  color: var(--warm-strong); text-align: center;
}
.learn-btn, .learn-chip {
  color: #fff !important; font-weight: 700; border: 0;
  animation: learn-pulse 1.8s ease-in-out infinite;
}
.learn-btn-rules    { background: linear-gradient(135deg, var(--warm), var(--warm-strong)); --learn-glow: 245, 158, 11; }
.learn-btn-examples { background: linear-gradient(135deg, var(--accent), var(--accent-2)); --learn-glow: 99, 102, 241; }
.learn-btn:hover, .learn-chip:hover { filter: brightness(1.08); transform: translateY(-1px); }
.learn-chip { flex-shrink: 0; white-space: nowrap; }
@keyframes learn-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(var(--learn-glow), .55); }
  50%      { box-shadow: 0 0 0 7px rgba(var(--learn-glow), 0); }
}
@media (prefers-reduced-motion: reduce) {
  .learn-btn, .learn-chip { animation: none; }
}
/* ---- Встраивание во фрейм (?embed=1, base.html) — только содержимое ---- */
.embed-mode .sidebar,
.embed-mode .sidebar-overlay,
.embed-mode .sidebar-collapse-btn,
.embed-mode .main-wrapper > .d-md-none { display: none !important; }
.embed-mode .main-wrapper { margin-left: 0 !important; }

/* ---- Пример разметки в редакторе (/transcription?example=…, annotator.js) ----
   Всё, что сдаёт, сохраняет, перекладывает или зовёт модель, — убрано: пример
   только смотрят. Во фрейме /support ещё и навигация раздела не нужна. */
.example-mode .task-toolbar-actions,
.example-mode #card-crumb,
.example-mode #useful-badge,
.example-mode #prelabel-box,
.example-mode #page-prelabel-btn,
.example-mode #auto-diar-btn,
.example-mode #idle-dataset,
.example-mode .learn-btn-examples { display: none !important; }
.embed-mode .subtab-bar,
.embed-mode .learn-chip { display: none !important; }
.example-mode #chunk-id-display {
  font-family: inherit; font-size: .9rem; font-weight: 600; max-width: 60ch;
  color: var(--text-primary);
}
.example-badge {
  display: inline-flex; align-items: center;
  font-size: .75rem; font-weight: 700; white-space: nowrap;
  padding: 2px 10px; border-radius: 999px;
  color: #fff; background: linear-gradient(135deg, var(--accent), var(--accent-2));
}

/* Узкая шапка: чипы ужимаются до значка, остаётся подсказка-title. */
@media (max-width: 1399px) {
  .learn-chip { font-size: 0; padding: .25rem .5rem; }
  .learn-chip .bi { font-size: .9rem; margin: 0 !important; }
}
.gami-prefs-head {
  font-size: .68rem; font-weight: 600; color: var(--text-secondary);
  text-transform: uppercase; letter-spacing: .02em;
}
.gami-prefs-seg {
  display: flex; gap: 3px; padding: 3px; border-radius: 10px;
  background: var(--body-bg); box-shadow: inset 0 0 0 1px var(--border);
}
.gami-prefs-opt {
  flex: 1 1 0; min-width: 0; padding: 5px 8px; border: 0; border-radius: 7px;
  background: transparent; color: var(--text-secondary);
  font-size: .8rem; font-weight: 600; line-height: 1.25;
  transition: background .15s ease, color .15s ease;
}
.gami-prefs-opt:hover { color: var(--text-primary); background: var(--hover-bg); }
.gami-prefs-opt.is-on {
  background: var(--card-bg); color: var(--accent);
  box-shadow: 0 1px 2px rgba(15, 23, 42, .12), inset 0 0 0 1px var(--border);
}
.gami-prefs-sub { font-weight: 500; opacity: .8; }
.gami-prefs-check { margin: 0; font-size: .82rem; color: var(--text-primary); }
.gami-prefs-hint { font-size: .74rem; color: var(--text-secondary); }
.gami-prefs-hint.is-warn { color: var(--warning); }

.gami-xp {
  height: 10px; border-radius: 999px; background: var(--body-bg);
  overflow: hidden; box-shadow: inset 0 0 0 1px var(--border);
}
.gami-xp-fill {
  height: 100%; border-radius: 999px;
  background: var(--grad-primary);
  transition: width .7s cubic-bezier(.22,1,.36,1);
}
.gami-profile-btn {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 12px 3px 10px; border-radius: 999px;
  font-size: .76rem; font-weight: 600; line-height: 1.5; white-space: nowrap;
  color: var(--accent); text-decoration: none;
  background: var(--accent-light); border: 1px solid transparent;
  transition: background .15s ease, color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.gami-profile-btn .bi { font-size: .95rem; }
.gami-profile-btn:hover {
  color: #fff; background: var(--accent);
  box-shadow: 0 3px 10px rgba(37, 99, 235, .35); transform: translateY(-1px);
}
.gami-profile-btn:active { transform: translateY(0); box-shadow: none; }

.gami-sub { font-size: .78rem; color: var(--text-secondary); margin-top: 5px; }
.gami-sub b { color: var(--text-primary); }

.gami-day-head {
  display: flex; justify-content: space-between; align-items: center;
  font-size: .78rem; color: var(--text-secondary); margin-bottom: 4px;
}
.gami-day-head b { color: var(--text-primary); font-variant-numeric: tabular-nums; }
.gami-day-pct { font-weight: 700; color: var(--accent); font-variant-numeric: tabular-nums; }
.gami-day-badge { font-size: .95rem; }
.gami-day-track {
  height: 8px; border-radius: 999px; background: var(--body-bg);
  overflow: hidden; box-shadow: inset 0 0 0 1px var(--border);
}
.gami-day-fill {
  height: 100%; border-radius: 999px;
  background: var(--grad-warm);
  transition: width .7s cubic-bezier(.22,1,.36,1);
}
.gami-day-fill.is-done { background: var(--grad-success); }

@media (max-width: 575px) {
  .gami-head { flex-direction: column; text-align: center; gap: 12px; }
  .gami-titlerow { justify-content: center; }
  .gami-titlerow .gami-profile-btn { margin-left: 0; }
}

/* ---- Доска рейтинга (Gamify.renderLeaderboard) ---- */
.gami-lb-empty {
  padding: 14px 16px; font-size: .82rem; color: var(--text-secondary);
}
.gami-lb-row {
  display: grid; align-items: center; gap: 10px;
  grid-template-columns: 2rem minmax(0, 1fr) auto 2.2rem;
  padding: 5px 14px; font-size: .82rem;
  font-variant-numeric: tabular-nums;
}
.gami-lb-row + .gami-lb-row { border-top: 1px solid var(--border); }
.gami-lb-row.is-head {
  font-size: .68rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .03em; color: var(--text-muted);
  border-bottom: 1px solid var(--border); padding-bottom: 6px;
}
.gami-lb-row.is-me {
  background: var(--accent-light); font-weight: 700; color: var(--accent);
}
.gami-lb-rank { text-align: center; color: var(--text-secondary); }
.gami-lb-row.is-me .gami-lb-rank { color: inherit; }
.gami-lb-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gami-lb-me {
  margin-left: 6px; padding: 0 6px; border-radius: 999px;
  font-size: .64rem; font-weight: 700; text-transform: uppercase;
  background: var(--accent); color: #fff;
}
.gami-lb-time { font-weight: 700; color: var(--text-primary); }
.gami-lb-row.is-head .gami-lb-time,
.gami-lb-row.is-me .gami-lb-time { color: inherit; font-weight: inherit; }
.gami-lb-ret { text-align: right; color: var(--text-muted); }
.gami-lb-ret.has-ret { color: var(--danger, #dc2626); font-weight: 700; }

/* ---- Достижения (Gamify.renderAchievements) ----
   Цвет рамки и медали — по редкости: какая доля команды уже получила
   (services/achievements._rarity). */
.rar-common    { --rar: #94a3b8; --rar-soft: rgba(148,163,184,.16); }
.rar-rare      { --rar: #3b82f6; --rar-soft: rgba(59,130,246,.14); }
.rar-epic      { --rar: #a855f7; --rar-soft: rgba(168,85,247,.14); }
.rar-legendary { --rar: #f59e0b; --rar-soft: rgba(245,158,11,.16); }

.gami-ach-wrap { padding: 18px 20px; }
.gami-ach-top {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px; margin-bottom: 14px;
}
.gami-ach-title { font-size: 1.05rem; font-weight: 700; color: var(--text-primary); }
.gami-ach-title .bi { color: var(--warm); margin-right: 4px; }
.gami-ach-summary { display: flex; align-items: center; gap: 10px; flex: 1 1 200px; min-width: 0; }
.gami-ach-total { font-size: .82rem; color: var(--text-secondary); white-space: nowrap; }
.gami-ach-total b { font-size: 1rem; color: var(--text-primary); }
.gami-ach-bar {
  flex: 1; height: 8px; border-radius: 999px; overflow: hidden;
  background: var(--body-bg); box-shadow: inset 0 0 0 1px var(--border);
}
.gami-ach-bar > span {
  display: block; height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, #2563eb, #a855f7, #f59e0b);
}
.gami-ach-filters {
  display: flex; gap: 3px; padding: 3px; border-radius: 10px;
  background: var(--body-bg); box-shadow: inset 0 0 0 1px var(--border);
}
.gami-ach-filter {
  border: 0; background: transparent; color: var(--text-secondary);
  font-size: .78rem; font-weight: 600; padding: 4px 10px; border-radius: 7px;
}
.gami-ach-filter:hover { color: var(--text-primary); background: var(--hover-bg); }
.gami-ach-filter.is-on {
  background: var(--card-bg); color: var(--accent);
  box-shadow: 0 1px 2px rgba(15,23,42,.12), inset 0 0 0 1px var(--border);
}

.gami-ach-recent {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  padding: 10px 12px; margin-bottom: 12px; border-radius: 10px;
  background: var(--surface-2); box-shadow: inset 0 0 0 1px var(--border);
}
.gami-ach-recent-k {
  font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .03em;
  color: var(--text-secondary); margin-right: 4px;
}
.gami-ach-recent-item {
  display: inline-flex; align-items: center; gap: 8px; padding: 4px 12px 4px 4px;
  border-radius: 999px; background: var(--card-bg);
  box-shadow: inset 0 0 0 1px var(--rar);
  font-size: .78rem; line-height: 1.15;
}
.gami-ach-recent-item small { display: block; color: var(--text-secondary); font-size: .68rem; }
.gami-ach-recent-emo {
  width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center;
  background: var(--rar-soft); font-size: 1.05rem;
}

.gami-ach-legend {
  display: flex; flex-wrap: wrap; gap: 4px 14px; margin-bottom: 6px;
  font-size: .72rem; color: var(--text-secondary);
}
.gami-ach-legend > span { display: inline-flex; align-items: center; gap: 5px; }
.gami-ach-legend i { width: 9px; height: 9px; border-radius: 50%; background: var(--rar); }
.gami-ach-legend-note { color: var(--text-muted); }

.gami-ach-cat { margin-top: 14px; }
.gami-ach-cat-head {
  display: flex; align-items: center; gap: 8px; margin-bottom: 8px;
  font-size: .78rem; font-weight: 700; text-transform: uppercase; letter-spacing: .03em;
  color: var(--text-secondary);
}
.gami-ach-cat-head::after { content: ""; flex: 1; height: 1px; background: var(--border); }
.gami-ach-cat-count {
  font-size: .7rem; padding: 1px 8px; border-radius: 999px;
  background: var(--chip-bg); color: var(--chip-text); letter-spacing: 0;
}
.gami-ach-cat-count.is-full { background: var(--success-soft); color: var(--success); }

.gami-ach-grid {
  display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(158px, 1fr));
}
.gami-ach {
  position: relative; padding: 14px 10px 10px; border-radius: 12px;
  border: 1px solid var(--border); background: var(--card-bg);
  display: flex; flex-direction: column; gap: 3px; text-align: center; align-items: center;
  color: inherit; text-decoration: none;
  transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
.gami-ach.is-got {
  border-color: color-mix(in srgb, var(--rar) 55%, transparent);
  background:
    radial-gradient(120% 80% at 50% 0%, var(--rar-soft), transparent 70%),
    var(--card-bg);
  box-shadow: var(--shadow-sm);
}
.gami-ach.is-got:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 18px color-mix(in srgb, var(--rar) 25%, transparent);
}
.gami-ach.is-link { cursor: pointer; color: inherit; }
/* Медаль: у полученного — кольцо цвета редкости, у закрытого — кольцо
   прогресса (conic по --p). */
.gami-ach-medal {
  --sz: 52px; width: var(--sz); height: var(--sz); border-radius: 50%;
  display: grid; place-items: center; margin-bottom: 4px;
  background: conic-gradient(var(--rar) calc(var(--p) * 1%), var(--border) 0);
}
.gami-ach-emoji {
  width: calc(var(--sz) - 8px); height: calc(var(--sz) - 8px); border-radius: 50%;
  display: grid; place-items: center; font-size: 1.55rem; line-height: 1;
  background: var(--card-bg);
}
.gami-ach.is-got .gami-ach-emoji { background: var(--rar-soft); }
.gami-ach.is-got.rar-legendary .gami-ach-medal {
  background: conic-gradient(from 0deg, #f59e0b, #fde68a, #f59e0b, #fbbf24, #f59e0b);
  box-shadow: 0 0 14px rgba(245,158,11,.45);
}
.gami-ach.is-got.rar-epic .gami-ach-medal { box-shadow: 0 0 12px rgba(168,85,247,.35); }
.gami-ach.locked .gami-ach-emoji { filter: grayscale(1); opacity: .55; }
.gami-ach.locked .gami-ach-name { color: var(--text-secondary); }
.gami-ach.is-secret { border-style: dashed; }
.gami-ach-name { font-size: .82rem; font-weight: 700; color: var(--text-primary); line-height: 1.2; }
.gami-ach-desc { font-size: .7rem; color: var(--text-secondary); line-height: 1.25; flex: 1; }
.gami-ach-foot {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  width: 100%; margin-top: 6px; font-size: .68rem;
}
.gami-ach-rar { font-weight: 700; color: var(--rar); text-transform: uppercase; letter-spacing: .03em; }
.gami-ach-date { color: var(--text-muted); }
.gami-ach-prog {
  display: block; width: 100%; height: 5px; border-radius: 999px; overflow: hidden;
  background: var(--body-bg); box-shadow: inset 0 0 0 1px var(--border);
}
.gami-ach-prog > span { display: block; height: 100%; background: var(--grad-primary); border-radius: 999px; }
.gami-ach-progtxt { color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.gami-ach-check {
  position: absolute; top: 7px; right: 8px; font-size: .85rem; color: var(--success);
}

/* ---- Гейм-бар: неделя, лимит проверки, ревью, полоска достижений ---- */
.gami-week {
  display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px;
  height: 46px; margin-top: 10px; align-items: end;
}
.gami-week-col { display: flex; flex-direction: column; align-items: center; gap: 3px; height: 100%; }
.gami-week-bar {
  width: 100%; max-width: 26px; margin-top: auto; border-radius: 4px 4px 2px 2px;
  background: color-mix(in srgb, var(--accent) 45%, transparent);
  transition: height .6s cubic-bezier(.22,1,.36,1);
}
.gami-week-col.is-today .gami-week-bar { background: var(--grad-warm); }
.gami-week-col.is-zero .gami-week-bar { background: var(--border); }
.gami-week-wd {
  font-size: .6rem; font-weight: 600; color: var(--text-muted);
  text-transform: uppercase; line-height: 1;
}
.gami-week-col.is-today .gami-week-wd { color: var(--warm-strong); }

.gami-gate {
  --gate: var(--success); --gate-soft: var(--success-soft);
  padding: 10px 12px; border-radius: 10px;
  background: var(--gate-soft);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--gate) 35%, transparent);
}
.gami-gate.is-warn    { --gate: var(--warning); --gate-soft: var(--warning-soft); }
.gami-gate.is-blocked { --gate: var(--danger);  --gate-soft: var(--danger-soft); }
.gami-gate-head {
  display: flex; justify-content: space-between; align-items: center; gap: 8px;
  font-size: .78rem; font-weight: 600; color: var(--text-primary); margin-bottom: 6px;
}
.gami-gate-title .bi { color: var(--gate); }
.gami-gate-num { font-variant-numeric: tabular-nums; color: var(--text-secondary); }
.gami-gate-num b { color: var(--gate); font-size: .95rem; }
.gami-gate-track {
  height: 7px; border-radius: 999px; overflow: hidden;
  background: var(--card-bg); box-shadow: inset 0 0 0 1px var(--border);
}
.gami-gate-fill { height: 100%; border-radius: 999px; background: var(--gate); transition: width .6s ease; }
.gami-gate.is-blocked .gami-gate-fill {
  background: repeating-linear-gradient(45deg, var(--danger) 0 8px, #ef4444 8px 16px);
}
.gami-gate-sub { margin-top: 6px; font-size: .74rem; color: var(--text-secondary); line-height: 1.35; }
.gami-gate.is-blocked .gami-gate-sub { color: var(--danger); font-weight: 600; }
.gami-gate-free { display: block; color: var(--text-muted); font-weight: 500; }

.gami-review {
  padding: 10px 12px 12px; border-radius: 10px;
  background:
    radial-gradient(120% 120% at 100% 0%, rgba(168,85,247,.12), transparent 60%),
    var(--surface-2);
  box-shadow: inset 0 0 0 1px var(--border);
}
.gami-review-head {
  display: flex; justify-content: space-between; align-items: baseline; gap: 8px;
  font-size: .78rem; font-weight: 700; color: #7c3aed; margin-bottom: 8px;
}
.gami-review-note { font-size: .72rem; font-weight: 500; color: var(--text-secondary); }
.gami-review-note b { color: var(--text-primary); }
.gami-review-tiles .gami-fact { background: var(--card-bg); }
.gami-review-tiles .gami-fact.is-main .gami-fact-v { color: #7c3aed; }
.gami-review-tiles .gami-fact.is-ok .gami-fact-v { color: var(--success); }
.gami-review-tiles .gami-fact.is-ret .gami-fact-v { color: var(--warning); }

.gami-strip {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px;
  padding: 8px 12px; border-radius: 10px; text-decoration: none; color: var(--text-primary);
  background: var(--surface-2); box-shadow: inset 0 0 0 1px var(--border);
  transition: box-shadow .15s ease, background .15s ease;
}
.gami-strip:hover {
  color: var(--text-primary); background: var(--hover-bg);
  box-shadow: inset 0 0 0 1px var(--accent);
}
.gami-strip-count { font-size: .78rem; font-weight: 700; color: var(--warm-strong); white-space: nowrap; }
.gami-strip-list { display: inline-flex; gap: 4px; }
.gami-strip-emo {
  width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center;
  font-size: .95rem; background: var(--rar-soft); box-shadow: inset 0 0 0 1.5px var(--rar);
}
.gami-strip-empty { font-size: .74rem; color: var(--text-muted); }
.gami-strip-next {
  display: inline-flex; align-items: center; gap: 6px; flex: 1 1 220px; min-width: 0;
  justify-content: flex-end; font-size: .74rem; white-space: nowrap;
}
.gami-strip-next-k { color: var(--text-secondary); }
.gami-strip-next-bar {
  display: inline-block; width: 54px; height: 5px; border-radius: 999px; overflow: hidden;
  background: var(--card-bg); box-shadow: inset 0 0 0 1px var(--border);
}
.gami-strip-next-bar > span { display: block; height: 100%; background: var(--grad-primary); }
.gami-strip-next-v { color: var(--text-secondary); font-variant-numeric: tabular-nums; }

.gami-chip-free { background: var(--success-soft); color: var(--success); }
.gami-chip-streak.is-hot { background: var(--grad-warm); color: #fff; }
/* Максимальный уровень — золотое кольцо. */
.gamebar.is-max .gami-ring {
  background: conic-gradient(from 0deg, #f59e0b, #fde68a, #f59e0b, #fbbf24, #f59e0b);
  box-shadow: 0 0 18px rgba(245,158,11,.4);
}
/* XP-полоса с бегущим бликом. */
.gami-xp-fill { position: relative; overflow: hidden; }
.gami-xp-fill::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(100deg, transparent 20%, rgba(255,255,255,.45) 50%, transparent 80%);
  transform: translateX(-100%); animation: gami-shine 3.2s ease-in-out infinite 1s;
}
@keyframes gami-shine { 0% { transform: translateX(-100%); } 60%, 100% { transform: translateX(100%); } }

/* Доска: заливка доли от лидера под строкой, тройка — крупнее. */
.gami-lb-row:not(.is-head) {
  background-image: linear-gradient(90deg,
    color-mix(in srgb, var(--accent) 9%, transparent) var(--w, 0%), transparent var(--w, 0%));
}
.gami-lb-review .gami-lb-row:not(.is-head) {
  background-image: linear-gradient(90deg, rgba(168,85,247,.10) var(--w, 0%), transparent var(--w, 0%));
}
.gami-lb-row.is-top .gami-lb-rank { font-size: 1rem; }

/* Строки досок открывают карточку участника (Gamify.openUserCard). */
[data-gami-user] { cursor: pointer; }
.gami-lb-row[data-gami-user]:hover { background-color: var(--hover-bg); }
.gami-lb-row[data-gami-user]:hover .gami-lb-name { text-decoration: underline; text-underline-offset: 2px; }
[data-gami-user]:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* ---- Карточка участника (модалка) ---- */
.gami-card-body { display: flex; flex-direction: column; gap: 16px; }
.gami-card-hero { display: flex; align-items: center; gap: 16px; }
.gami-card-hero .profile-avatar { width: 64px; height: 64px; font-size: 1.6rem; }
.gami-card-id { min-width: 0; }
.gami-card-id .gami-lb-me { vertical-align: middle; }
.gami-card-facts {
  display: flex; flex-wrap: wrap; gap: 4px 16px; margin-top: 6px;
  font-size: .78rem; color: var(--text-secondary);
}
.gami-card-facts .bi { color: var(--text-muted); margin-right: 3px; }
.gami-card-ach .gami-ach-wrap { border: 0; box-shadow: none; padding: 0; background: transparent; }
@media (max-width: 575px) {
  .gami-card-hero { flex-direction: column; text-align: center; }
  .gami-card-facts { justify-content: center; }
}

/* ---- Лестница уровней ---- */
.gami-ladder-list { padding: 6px 0; }
.gami-ladder-row {
  display: grid; align-items: center; gap: 12px;
  grid-template-columns: 2.2rem minmax(0, 1fr) auto 1.4rem;
  padding: 7px 16px; font-size: .82rem;
}
.gami-ladder-row + .gami-ladder-row { border-top: 1px solid var(--border); }
.gami-ladder-emo {
  width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center;
  font-size: 1.15rem; background: var(--body-bg); box-shadow: inset 0 0 0 1px var(--border);
}
.gami-ladder-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.gami-ladder-name { font-weight: 700; color: var(--text-primary); }
.gami-ladder-perk { font-size: .72rem; color: var(--text-secondary); }
.gami-ladder-perk .bi { margin-right: 3px; }
.gami-ladder-min {
  font-size: .74rem; color: var(--text-muted);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.gami-ladder-state { color: var(--text-muted); text-align: center; }
.gami-ladder-row.is-done .gami-ladder-state { color: var(--success); }
.gami-ladder-row.is-done .gami-ladder-emo { background: var(--success-soft); }
.gami-ladder-row.is-next { opacity: .62; }
.gami-ladder-row.is-next .gami-ladder-emo { filter: grayscale(.8); }
.gami-ladder-row.is-cur { background: var(--accent-soft); }
.gami-ladder-row.is-cur .gami-ladder-emo { background: var(--card-bg); box-shadow: 0 0 0 2px var(--accent); }
.gami-ladder-row.is-cur .gami-ladder-state { color: var(--accent); }
.gami-ladder-prog {
  display: block; height: 5px; margin-top: 3px; border-radius: 999px; overflow: hidden;
  background: var(--card-bg); box-shadow: inset 0 0 0 1px var(--border); max-width: 260px;
}
.gami-ladder-prog > span { display: block; height: 100%; background: var(--grad-primary); }

/* ---- «Достижение открыто» — карточки справа снизу ---- */
.gami-unlocks {
  position: fixed; right: 18px; bottom: 18px; z-index: 10001;
  display: flex; flex-direction: column; gap: 10px; align-items: flex-end;
  pointer-events: none;
}
.gami-unlock {
  pointer-events: auto; display: flex; align-items: center; gap: 12px;
  width: min(340px, calc(100vw - 36px)); padding: 12px 14px; border-radius: 14px;
  background:
    radial-gradient(140% 120% at 0% 0%, var(--rar-soft), transparent 60%),
    var(--card-bg);
  border: 1px solid color-mix(in srgb, var(--rar) 60%, transparent);
  box-shadow: 0 10px 30px rgba(17,24,39,.18), 0 0 0 4px var(--rar-soft);
  color: var(--text-primary); text-decoration: none;
  animation: gami-unlock-in .55s cubic-bezier(.22,1.4,.36,1) both;
}
.gami-unlock:hover { color: var(--text-primary); }
.gami-unlock.is-out { animation: gami-unlock-out .3s ease forwards; }
.gami-unlock-medal {
  flex-shrink: 0; width: 50px; height: 50px; border-radius: 50%;
  display: grid; place-items: center; font-size: 1.6rem;
  background: var(--rar-soft); box-shadow: inset 0 0 0 2px var(--rar);
  animation: gami-medal-pop .7s cubic-bezier(.22,1.6,.36,1) .15s both;
}
.gami-unlock-main { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.gami-unlock-k {
  font-size: .66rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--rar);
}
.gami-unlock-name { font-size: .95rem; font-weight: 700; }
.gami-unlock-desc { font-size: .76rem; color: var(--text-secondary); }
@keyframes gami-unlock-in {
  from { opacity: 0; transform: translateX(40px) scale(.95); }
  to   { opacity: 1; transform: none; }
}
@keyframes gami-unlock-out { to { opacity: 0; transform: translateX(40px); } }
@keyframes gami-medal-pop { from { transform: scale(.3) rotate(-30deg); } to { transform: none; } }

/* ---- «Новый уровень» — по центру ---- */
.gami-levelup {
  position: fixed; inset: 0; z-index: 10002; display: grid; place-items: center;
  background: rgba(15,17,21,.45); backdrop-filter: blur(3px);
  animation: gami-fade-in .25s ease both;
}
.gami-levelup.is-out { animation: gami-fade-out .3s ease forwards; }
.gami-levelup-card {
  position: relative; overflow: hidden; text-align: center;
  width: min(380px, calc(100vw - 32px)); padding: 28px 24px 22px; border-radius: 20px;
  background: var(--card-bg); border: 1px solid var(--border);
  box-shadow: 0 24px 60px rgba(0,0,0,.3);
  animation: gami-unlock-in .6s cubic-bezier(.22,1.4,.36,1) both;
}
.gami-levelup-rays {
  position: absolute; inset: -50%; z-index: 0; opacity: .5;
  background: repeating-conic-gradient(from 0deg, rgba(37,99,235,.10) 0 10deg, transparent 10deg 20deg);
  animation: gami-spin 18s linear infinite;
}
.gami-levelup-card > :not(.gami-levelup-rays) { position: relative; z-index: 1; }
.gami-levelup-medal {
  width: 96px; height: 96px; margin: 0 auto 12px; border-radius: 50%;
  display: grid; place-items: center; font-size: 3rem;
  background: var(--card-bg); box-shadow: 0 0 0 5px var(--accent), 0 8px 26px rgba(37,99,235,.45);
  animation: gami-medal-pop .8s cubic-bezier(.22,1.6,.36,1) .1s both;
}
.gami-levelup-k {
  font-size: .72rem; font-weight: 800; text-transform: uppercase;
  letter-spacing: .1em; color: var(--accent);
}
.gami-levelup-name { font-size: 1.35rem; font-weight: 800; color: var(--text-primary); margin: 2px 0 8px; }
.gami-levelup-perk {
  display: inline-block; padding: 5px 12px; border-radius: 999px; font-size: .8rem; font-weight: 600;
  background: var(--success-soft); color: var(--success);
}
.gami-levelup-next { margin-top: 10px; font-size: .78rem; color: var(--text-secondary); }
@keyframes gami-fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes gami-fade-out { to { opacity: 0; } }
@keyframes gami-spin { to { transform: rotate(360deg); } }

/* Плашка лимита проверки над кнопками в /transcription (пара к
   .idle-suspended-note: та — про возвраты, эта — про очередь ревью). */
.idle-review-note {
  padding: 10px 14px; border-radius: 10px; text-align: left;
  font-size: .85rem; font-weight: 600; line-height: 1.4;
  color: var(--warning); background: var(--warning-soft);
  border: 1px solid var(--warning);
}

:root[data-theme="dark"] .gami-chip-streak { background: rgba(249,115,22,.18); color: #fdba74; }
:root[data-theme="dark"] .gami-chip-tempo  { background: rgba(99,102,241,.2); color: #a5b4fc; }
:root[data-theme="dark"] .gami-review-head,
:root[data-theme="dark"] .gami-review-tiles .gami-fact.is-main .gami-fact-v { color: #c4b5fd; }
:root[data-theme="dark"] .gami-unlock { box-shadow: 0 10px 30px rgba(0,0,0,.5), 0 0 0 4px var(--rar-soft); }

@media (max-width: 575px) {
  .gami-ladder-row { grid-template-columns: 2.2rem minmax(0, 1fr) 1.4rem; }
  .gami-ladder-min { display: none; }
  .gami-strip-next { justify-content: flex-start; }
}
@media (prefers-reduced-motion: reduce) {
  .gami-xp-fill::after, .gami-levelup-rays { animation: none; }
  .gami-unlock, .gami-unlock-medal, .gami-levelup-card, .gami-levelup-medal { animation: none; }
}

/* ---- Профиль: hero ---- */
.profile-hero { padding: 22px; }
.profile-hero-top { display: flex; align-items: center; gap: 18px; margin-bottom: 18px; }
.profile-avatar {
  flex-shrink: 0; width: 72px; height: 72px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: 1.9rem; font-weight: 700;
  background: var(--grad-primary);
  box-shadow: 0 4px 14px rgba(37,99,235,.35);
}
.profile-identity { min-width: 0; }
.profile-name { font-size: 1.35rem; font-weight: 700; color: var(--text-primary); line-height: 1.15; }
.profile-login { font-size: .9rem; color: var(--text-secondary); margin-top: 1px; }
.profile-badges { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 9px; }
.profile-badges .badge { font-weight: 600; font-size: .72rem; padding: .35em .7em; }
.profile-meta {
  display: flex; flex-wrap: wrap; gap: 8px 22px;
  margin: 0 0 16px; padding: 12px 0 0; border-top: 1px solid var(--border);
}
.profile-meta:empty { display: none; }
.profile-meta-item { display: inline-flex; align-items: baseline; gap: 6px; font-size: .82rem; }
.profile-meta-item > .bi { color: var(--text-muted); }
.profile-meta-label { color: var(--text-secondary); }
.profile-meta-val { color: var(--text-primary); font-weight: 600; }
@media (max-width: 575px) {
  .profile-hero-top { flex-direction: column; text-align: center; }
  .profile-badges { justify-content: center; }
  .profile-meta { justify-content: center; }
}

/* ---- Конфетти ---- */
.gami-confetti {
  position: fixed; inset: 0; pointer-events: none; z-index: 10000; overflow: hidden;
}
.gami-confetti i {
  position: absolute; top: -12px; display: block; border-radius: 1px;
  animation-name: gami-fall; animation-timing-function: ease-in; animation-fill-mode: forwards;
}
@keyframes gami-fall {
  0%   { transform: translateY(-10px) rotate(0deg); opacity: 1; }
  100% { transform: translateY(102vh) rotate(540deg); opacity: .9; }
}
@media (prefers-reduced-motion: reduce) {
  .gami-confetti { display: none; }
  .gami-xp-fill, .gami-day-fill, .gami-ring { transition: none; }
}

/* ============================================================
   Создание датасета (/synth) — хаб, модалка старта, редактор, суфлёр.
   Только токены: светлая и тёмная тема получаются сами.
   ============================================================ */
.synth-lead { color: var(--text-secondary); font-size: .9rem; max-width: 760px; margin-bottom: 18px; }

/* чипы языка / категории / статуса */
.synth-lang-chip {
  display: inline-flex; align-items: center; padding: 1px 8px; border-radius: var(--radius-pill);
  font-size: .72rem; font-weight: 600; letter-spacing: .02em; white-space: nowrap;
  background: var(--accent-soft); color: var(--accent);
}
.synth-lang-chip.lang-kk    { background: var(--success-soft); color: var(--success); }
.synth-lang-chip.lang-mixed { background: var(--warm-soft);    color: var(--warm-strong); }
.synth-cat {
  display: inline-flex; align-items: center; padding: 1px 8px; border-radius: var(--radius-pill);
  font-size: .72rem; background: var(--chip-bg); color: var(--chip-text); white-space: nowrap;
}
.synth-status {
  display: inline-flex; padding: 1px 8px; border-radius: var(--radius-pill);
  font-size: .72rem; font-weight: 600; white-space: nowrap;
  background: var(--chip-bg); color: var(--chip-text);
}
.synth-status.st-open      { background: var(--accent-soft);  color: var(--accent); }
.synth-status.st-in_work   { background: var(--warning-soft); color: var(--warning); }
.synth-status.st-submitted { background: var(--success-soft); color: var(--success); }

.synth-progress { height: 5px; border-radius: 3px; background: var(--chip-bg); overflow: hidden; }
.synth-progress-fill { height: 100%; background: var(--grad-success); border-radius: 3px; transition: width .3s ease; }

/* хаб: карточки моих заданий */
.synth-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 14px; }
.synth-card {
  display: flex; flex-direction: column; gap: 10px; padding: 14px 16px;
  background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); color: var(--text-primary); text-decoration: none;
  transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease;
}
.synth-card:hover { transform: translateY(-1px); box-shadow: var(--shadow); border-color: var(--accent); color: var(--text-primary); }
.synth-card-top { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.synth-card-top .synth-status { margin-left: auto; }
.synth-card-title { font-weight: 600; line-height: 1.35; min-height: 2.7em; }
.synth-card-meta { display: flex; gap: 12px; flex-wrap: wrap; font-size: .76rem; color: var(--text-secondary); }

/* хаб: админ */
.synth-counts { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 12px; }
.synth-count {
  display: flex; flex-direction: column; min-width: 130px; padding: 8px 14px;
  background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.synth-count b { font-size: 1.3rem; line-height: 1.1; }
.synth-count span { font-size: .78rem; color: var(--text-secondary); }
.synth-count small { font-size: .7rem; color: var(--text-muted); }
.synth-toolbar { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-bottom: 12px; }
.synth-toolbar .form-select, .synth-toolbar .form-control { width: auto; min-width: 140px; }
.synth-table td { font-size: .85rem; }
.synth-td-scn { max-width: 340px; }
.synth-td-scn a { color: var(--text-primary); }
.synth-noise-list { display: flex; flex-direction: column; gap: 6px; }
.synth-noise {
  display: flex; align-items: center; gap: 10px; padding: 8px 12px;
  background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.synth-noise-name { font-weight: 500; }
.synth-pre {
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 10px 12px; font-size: .78rem; white-space: pre-wrap; word-break: break-all;
}

/* модалка старта */
.ss-step-title { font-size: 1.05rem; font-weight: 600; margin-bottom: 14px; }
.ss-tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.ss-tiles-2 { grid-template-columns: repeat(2, 1fr); }
.ss-tile {
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px; text-align: left;
  padding: 16px; border: 1.5px solid var(--border); border-radius: var(--radius);
  background: var(--card-bg); color: var(--text-primary); cursor: pointer;
  transition: border-color .12s ease, transform .12s ease, box-shadow .12s ease;
}
.ss-tile:hover:not(:disabled) { border-color: var(--accent); box-shadow: var(--shadow); transform: translateY(-1px); }
.ss-tile:disabled { opacity: .5; cursor: not-allowed; }
.ss-tile.is-remembered { border-color: var(--accent); background: var(--accent-soft); }
.ss-tile-badge {
  font-size: .78rem; font-weight: 700; padding: 3px 10px; border-radius: var(--radius-pill);
  background: var(--grad-primary); color: #fff;
}
.ss-tile-icon { font-size: 1.6rem; color: var(--accent); }
.ss-tile-title { font-size: 1rem; font-weight: 600; }
.ss-tile-hint { font-size: .8rem; color: var(--text-secondary); line-height: 1.35; }
.ss-tile-meta { font-size: .74rem; color: var(--text-muted); margin-top: auto; }
.ss-cont-list { display: flex; flex-direction: column; gap: 6px; }
.ss-cont {
  display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-radius: var(--radius-sm);
  border: 1px solid var(--border); color: var(--text-primary); text-decoration: none;
}
.ss-cont:hover { background: var(--hover-bg); color: var(--text-primary); }
.ss-cont-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ss-cont-meta { font-size: .76rem; color: var(--text-secondary); white-space: nowrap; }
.ss-scratch { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--border); }
@media (max-width: 640px) { .ss-tiles, .ss-tiles-2 { grid-template-columns: 1fr; } }

/* редактор: каркас */
.synth-ed { display: flex; flex-direction: column; min-height: 100vh; }
/* Колонка высотой в экран: без запрета сжатия короткая лента «сплющивала»
   липкий верх, и волна монтажа уезжала за его край. */
.synth-ed > * { flex-shrink: 0; }
.synth-ed-top {
  position: sticky; top: 0; z-index: 20; display: flex; align-items: center; gap: 12px;
  padding: 12px 24px; background: var(--body-bg); border-bottom: 1px solid var(--border);
}
.synth-ed-title-wrap { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.synth-ed-title {
  border: 0; background: transparent; font-size: 1.1rem; font-weight: 600; color: var(--text-primary);
  padding: 2px 6px; margin-left: -6px; border-radius: var(--radius-sm); width: 100%;
}
.synth-ed-title:hover:not(:disabled), .synth-ed-title:focus { background: var(--card-bg); outline: 1px solid var(--border); }
.synth-ed-title { font-size: .95rem; letter-spacing: .01em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.synth-ed-scenario { font-size: .82rem; color: var(--text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.synth-card-title.font-monospace { font-size: .82rem; min-height: 0; word-break: break-all; }
.synth-card-scn { font-size: .82rem; color: var(--text-secondary); line-height: 1.35; }
.synth-ed-chips { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.synth-chip-label { display: inline-flex; align-items: center; gap: 4px; font-size: .75rem; color: var(--text-secondary); margin: 0; }
.synth-chip-select { width: auto; padding: 0 1.6rem 0 .5rem; height: 22px; font-size: .75rem; border-radius: var(--radius-pill); }
.synth-ed-progress { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.synth-ed-progress .ring-bg { fill: none; stroke: var(--chip-bg); stroke-width: 4; }
.synth-ed-progress .ring-fg { fill: none; stroke: var(--success); stroke-width: 4; stroke-linecap: round; transition: stroke-dashoffset .3s ease; }
.synth-ed-progress-text { display: flex; flex-direction: column; font-size: .8rem; line-height: 1.25; }
.synth-ed-progress-text span { color: var(--text-secondary); font-size: .72rem; }
.autosave-indicator.saving { color: var(--warning); }
.autosave-indicator.saved  { color: var(--success); }
.autosave-indicator.error  { color: var(--danger); }
.synth-banner {
  margin: 12px 24px 0; padding: 10px 14px; border-radius: var(--radius-sm); display: flex; gap: 8px;
  align-items: center; font-size: .85rem; background: var(--accent-soft); color: var(--text-primary);
}
.synth-banner.ok { background: var(--success-soft); }
#ed-main { padding: 16px 24px 24px; flex: 1; }

/* голоса — бейджи спикеров в шапке (разметка и выпадашка — общие с
   транскрипцией: .speaker-badge / .spk-meta-*); иконка — цветом спикера */
.synth-ed-top .speaker-badges { flex-shrink: 1; min-width: 0; }

/* лента */
.synth-timeline { display: flex; flex-direction: column; }
.synth-ins { display: flex; align-items: center; gap: 6px; height: 22px; opacity: 0; transition: opacity .12s ease; }
.synth-ins:hover, .synth-ins:focus-within, .synth-timeline > .synth-ins:last-of-type { opacity: 1; }
.synth-ins-line { flex: 1; height: 1px; background: var(--border); }
.synth-ins button {
  border: 1px solid var(--border); background: var(--card-bg); color: var(--text-secondary);
  border-radius: var(--radius-pill); font-size: .72rem; padding: 1px 10px; display: inline-flex; gap: 4px; align-items: center;
}
.synth-ins button:hover { border-color: var(--accent); color: var(--accent); }
@media (hover: none) { .synth-ins { opacity: 1; } }

.synth-turn {
  background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); transition: border-color .15s ease, box-shadow .15s ease;
}
.synth-turn.speech { border-left: 4px solid var(--spk); }
.synth-turn.speech.voiced { background: linear-gradient(90deg, color-mix(in srgb, var(--spk) 6%, var(--card-bg)), var(--card-bg) 40%); }
.synth-turn.is-current { box-shadow: 0 0 0 2px var(--spk); }
.synth-turn.drop { border-style: dashed; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.synth-turn-head { display: flex; align-items: center; gap: 8px; padding: 8px 12px 0; flex-wrap: wrap; }
.synth-turn-n {
  min-width: 22px; height: 22px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
  background: var(--spk); color: #fff; font-size: .72rem; font-weight: 700;
}
.synth-spk-select, .synth-lang-select { width: auto; font-size: .78rem; padding: .1rem 1.8rem .1rem .5rem; }
.synth-turn-meta { font-size: .72rem; color: var(--text-muted); margin-left: auto; }
.synth-turn-tools { display: flex; }
.synth-turn-tools .btn { color: var(--text-muted); padding: 0 6px; }
.synth-turn-tools .btn:hover { color: var(--text-primary); }
.synth-turn-body { padding: 8px 12px; }
.synth-field { display: flex; flex-direction: column; gap: 4px; margin: 0; }
.synth-field > span { font-size: .72rem; font-weight: 600; color: var(--text-secondary); }
.synth-field > span small { font-weight: 400; color: var(--text-muted); }
.synth-target { font-size: 1rem; line-height: 1.5; }

/* Поля ввода текста (транскрипция, комментарии, продолжение разговора,
   эталон реплики): в одну строку, пока пусто, и растут с текстом. Браузер
   делает это сам (field-sizing), для остальных — core/autogrow.js. */
textarea.autogrow {
  field-sizing: content;
  resize: none;
  min-height: calc(1.5em + .5rem + 2px);
  max-height: 60vh;
  overflow-y: auto;
}

.synth-audio {
  display: flex; align-items: center; gap: 8px; padding: 8px 12px 10px; flex-wrap: wrap;
  border-top: 1px dashed var(--border); margin-top: 2px;
}
.synth-audio.busy { color: var(--text-secondary); font-size: .85rem; }
.synth-rec-btn { background: var(--danger); border-color: var(--danger); color: #fff; }
.synth-rec-btn:hover, .synth-rec-btn:focus { background: #b91c1c; border-color: #b91c1c; color: #fff; }
.synth-rec-btn.is-recording { animation: synth-pulse 1.2s ease-in-out infinite; }
.synth-rec-dot { width: 12px; height: 12px; border-radius: 50%; background: var(--danger); animation: synth-pulse 1s ease-in-out infinite; }
.synth-rec-time { font-variant-numeric: tabular-nums; font-weight: 600; min-width: 36px; }
@keyframes synth-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
.synth-meter { flex: 1; min-width: 120px; max-width: 360px; height: 8px; border-radius: 4px; background: var(--chip-bg); overflow: hidden; }
.synth-meter-fill { height: 100%; width: 0; background: var(--grad-success); transition: width .06s linear; }
.synth-meter-fill.clip { background: var(--danger); }
.synth-play {
  width: 32px; height: 32px; border-radius: 50%; padding: 0; display: inline-flex; align-items: center; justify-content: center;
  background: var(--spk, var(--accent)); color: #fff; border: 0; flex-shrink: 0;
}
.synth-play:hover { filter: brightness(1.1); color: #fff; }
/* мини-волна звука реплики — core/mini-wave, как у сегмента на транскрипции */
.synth-mini { flex: 1; min-width: 160px; height: 36px; display: block; border-radius: 4px; cursor: pointer; }
.synth-dur { font-size: .78rem; font-variant-numeric: tabular-nums; color: var(--text-secondary); }
.synth-origin { color: var(--text-muted); }

.synth-turn.pause, .synth-turn.noise {
  display: flex; align-items: center; gap: 8px; padding: 8px 12px; font-size: .85rem;
  background: var(--surface-2); box-shadow: none; flex-wrap: wrap;
}
.synth-turn.pause > .bi, .synth-turn.noise > .bi { color: var(--text-secondary); font-size: 1.05rem; }
.synth-turn.pause input { width: 80px; }
.synth-turn.noise select { width: auto; max-width: 340px; }
.synth-gain { display: inline-flex; align-items: center; gap: 4px; margin: 0; color: var(--text-secondary); }
.synth-gain input { width: 72px; }

/* --- /synth: липкий верх (шапка + монтаж) и панель монтажа на волне ---------
   Волна — та же, что на транскрипции (#waveform, .wave-controls, .mreg-*): её
   стили общие, здесь только рамка панели и то, чего на транскрипции нет. */
.synth-ed-head {
  position: sticky; top: 0; z-index: 20;
  background: var(--body-bg);
  border-bottom: 1px solid var(--border);
}
.synth-ed-head .synth-ed-top { position: static; border-bottom: 0; }
/* Масштаб страницы (Ctrl±) раскачивал весь интерфейс: оверлеи волны (регионы
   у края, запас «за концом записи») вылезали за #waveform, flex-обёртка
   .main-wrapper по min-width:auto раздавалась под них, волна перерисовывалась
   шире, оверлеи переезжали — и так по кругу (ResizeObserver ~30 раз в секунду,
   ширина скакала на 50 px). Волна режет своё содержимое, обёртка не растёт от
   содержимого, место под полосу прокрутки страницы — постоянное. */
.main-wrapper:has(> .synth-ed) { min-width: 0; }
html:has(.synth-ed) { scrollbar-gutter: stable; }
.synth-mont #waveform { overflow: clip; }
.synth-mont { margin: 0 24px 12px; padding: 10px 16px 12px; }
.synth-mont-head {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-bottom: 6px; min-height: 30px;
}
.synth-mont-title { font-weight: 600; font-size: .9rem; color: var(--text-primary); white-space: nowrap; }
.st-todo { font-size: .78rem; color: var(--warning); white-space: nowrap; }
.st-todo.done { color: var(--success); }
.st-status { font-size: .78rem; color: var(--text-secondary); white-space: nowrap; }
.st-status.error { color: var(--danger); }
.synth-mont-hint {
  flex: 1; min-width: 0; font-size: .74rem; color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: right;
}
.synth-mont-hint kbd { font-size: .68rem; padding: 0 4px; }
.synth-mont-collapse { padding: 0 4px; color: var(--text-secondary); }
.synth-mont.collapsed { padding-bottom: 6px; }
.synth-mont.collapsed .synth-mont-head { margin-bottom: 0; }
.synth-mont.collapsed .synth-mont-body { display: none; }
.synth-mont .wave-controls { margin-top: 8px; }
.st-end {
  position: absolute; z-index: 1; pointer-events: none;
  border-left: 2px dashed var(--text-muted);
  background: repeating-linear-gradient(135deg, rgba(107,114,128,.12) 0 6px, transparent 6px 12px);
}
.st-end span {
  position: absolute; top: 4px; left: 6px; font-size: 10px; font-weight: 600;
  color: var(--text-muted); white-space: nowrap; text-transform: uppercase; letter-spacing: .03em;
}

/* Слева под волной — прогресс озвучки и промежуток по умолчанию. */
.st-gap { grid-column: 1; display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.st-gap label {
  display: inline-flex; align-items: center; gap: 6px; margin: 0;
  font-size: .78rem; color: var(--text-secondary); white-space: nowrap;
}
.st-gap input { width: 76px; }

/* Справа — фон: слои плашками, по клику раскрывается их список. */
.st-bg-summary { display: flex; gap: 4px; flex-wrap: wrap; cursor: pointer; }
.st-bg-chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: .74rem; padding: 2px 8px; border-radius: var(--radius-pill);
  background: var(--chip-bg); color: var(--text-primary); white-space: nowrap;
}
.st-bg-chip b { font-weight: 600; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.st-bg-chip.muted { color: var(--text-muted); }
#st-bg-toggle .bi { transition: transform .15s; }
#st-bg-toggle.open .bi { transform: rotate(180deg); }
.st-layers {
  margin-top: 10px; padding-top: 10px; border-top: 1px dashed var(--border);
  display: flex; flex-direction: column; gap: 6px;
}
.st-layer { display: grid; grid-template-columns: 22px minmax(180px, 320px) minmax(120px, 1fr) 56px 32px; align-items: center; gap: 10px; }
.st-layer-n {
  width: 20px; height: 20px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
  font-size: .7rem; font-weight: 700; background: var(--chip-bg); color: var(--text-secondary);
}
.st-layer .form-range { margin: 0; }
.st-layer-db { font-size: .78rem; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--text-secondary); text-align: right; }
.st-layers-foot { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding-top: 2px; }

/* Карточка ↔ регион: выбранный на волне элемент подсвечен в ленте, а
   прокрутка к нему не прячет его под липкий верх. */
.synth-turn {
  scroll-margin-top: calc(var(--synth-head-h, 0px) + 12px);
  scroll-margin-bottom: 96px;
}
.synth-turn.is-wave-sel { outline: 2px solid var(--accent); outline-offset: 1px; }
.synth-turn[data-uuid] { cursor: default; }

/* Страница монтажа — рабочий инструмент, а не текст: протяжка мышью по волне,
   ручкам и карточкам не должна выделять подписи, значки и картинки. Выделяется
   только то, что правят, — поля ввода. */
.synth-ed, .synth-prompter { -webkit-user-select: none; user-select: none; }
.synth-ed input, .synth-ed textarea, .synth-ed [contenteditable="true"] {
  -webkit-user-select: text; user-select: text;
}
.synth-ed img, .synth-ed svg, .synth-ed canvas { -webkit-user-drag: none; user-drag: none; }
.synth-mont-focus { color: var(--text-muted); padding: 0 6px; }
.synth-mont-focus:hover { color: var(--accent); }

@media (max-width: 900px) {
  .synth-mont { margin: 0 12px 10px; padding: 8px 10px 10px; }
  .synth-mont-hint { display: none; }
  .st-layer { grid-template-columns: 22px 1fr 56px 32px; }
  .st-layer .form-range { grid-column: 2 / span 1; grid-row: 2; }
}

/* суфлёр — всегда тёмный: крупный светлый текст читается с расстояния */
body.synth-prompter-open { overflow: hidden; }
.synth-prompter {
  position: fixed; inset: 0; z-index: 1300; display: flex; flex-direction: column;
  background: #0b0d12; color: #e5e7eb; padding: 18px 28px 22px;
}
.synth-prompter-top { display: flex; align-items: center; gap: 16px; font-size: .82rem; color: #9ca3af; }
.synth-prompter-keys { margin-left: auto; }
.synth-prompter-keys kbd { background: #1f232c; color: #e5e7eb; border: 1px solid #2a2f3a; }
.synth-prompter-cur { flex: 1; display: flex; align-items: center; }
.pr-line { max-width: 1100px; margin: 0 auto; width: 100%; border-left: 5px solid var(--spk); padding-left: 20px; }
.pr-line.prev, .pr-line.next { opacity: .38; padding-top: 14px; padding-bottom: 14px; }
.pr-line.prev .pr-text, .pr-line.next .pr-text { font-size: 1.15rem; }
.pr-who { font-size: .85rem; color: #9ca3af; margin-bottom: 8px; }
.pr-text { font-size: clamp(1.6rem, 3.2vw, 2.6rem); line-height: 1.4; font-weight: 500; }
.pr-mark { color: #fbbf24; font-size: .7em; font-style: italic; }
.synth-prompter-bar {
  display: flex; align-items: center; gap: 12px; justify-content: center; padding-top: 16px;
  border-top: 1px solid #1f232c;
}
.synth-prompter-bar .synth-meter { max-width: 280px; background: #1f232c; }
.synth-prompter-time { font-variant-numeric: tabular-nums; min-width: 48px; font-size: 1.1rem; }
.synth-prompter .synth-rec-btn { min-width: 190px; }

@media (max-width: 900px) {
  .synth-ed-top { flex-wrap: wrap; padding: 10px 16px; }
  #ed-main { padding: 12px 16px; }
  .synth-prompter { padding: 14px 16px; }
  .synth-prompter-keys { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .synth-rec-btn.is-recording, .synth-rec-dot { animation: none; }
}

/* «Создание датасета»: клип шума, подобранный из корпуса, и список подбора */
.synth-noise-auto { color: var(--text-secondary); max-width: 320px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.synth-noise-auto .bi { color: var(--accent); }
.synth-noise-pick { flex-basis: 100%; display: flex; flex-direction: column; gap: 4px;
  padding: 6px 0 2px 26px; border-top: 1px dashed var(--border); margin-top: 2px; }
.synth-pick-row { display: flex; align-items: center; gap: 8px; }
.synth-pick-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---- Правки модели в ревью (tools/llm_check.py → core/text-diff.js) ---------
   Сегмент, текст которого модель (или ревьюер поверх неё) изменила против
   версии разметчика: полоса слева, бейдж в шапке и строка «было → стало». */
.llm-banner {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px;
  padding: 10px 14px; margin-bottom: 12px; border-radius: 8px;
  background: var(--warning-soft); border: 1px solid var(--warning);
  font-size: .85rem;
}
.llm-banner .form-check { margin: 0; }
.segment-card.seg-llm-changed { box-shadow: inset 3px 0 0 var(--warning); }
.seg-llm-badge {
  font-size: .68rem; font-weight: 600; padding: 1px 6px; border-radius: 4px;
  background: var(--warning-soft); color: var(--warning);
}
.seg-diff {
  font-size: .8125rem; line-height: 1.5; padding: 4px 8px; margin-bottom: 6px;
  border-radius: 6px; background: var(--warning-soft);
}
/* pre-wrap только у самого текста: на контейнере он рисовал отступы шаблона
   пустыми строками, и блок выходил в разы выше двух строк текста */
.seg-diff-body { white-space: pre-wrap; word-break: break-word; }
.seg-diff-head {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  font-size: .72rem; color: var(--text-secondary); margin-bottom: 2px;
}
.td-del { color: var(--danger); background: var(--danger-soft); text-decoration: line-through; }
.td-ins { color: var(--success); background: var(--success-soft); text-decoration: none; font-weight: 600; }
.rq-fact-llm { background: var(--warning-soft); color: var(--warning); }

/* Окно гейта формата: что исправлено само и что руками (core/format-report.js). */
.fr-section + .fr-section { margin-top: 18px; }
.fr-head { font-size: .85rem; font-weight: 600; margin-bottom: 2px; }
.fr-hint { font-size: .78rem; color: var(--text-secondary); margin-bottom: 8px; }
.fr-item { padding: 6px 10px; margin-bottom: 6px; border-radius: 6px; background: var(--warning-soft); }
.fr-jump { font-size: .76rem; font-weight: 600; text-decoration: none; }
.fr-text { font-size: .875rem; line-height: 1.5; white-space: pre-wrap; word-break: break-word; }
.fr-mark { background: var(--danger-soft); color: var(--danger); font-weight: 600; padding: 0 2px; border-radius: 3px; }

/* Пресеты эквалайзера под волной — общие у /transcription и /review.
   Сегментированный переключатель (btn-group): пять отдельных пилюль читались
   как пять несвязанных кнопок, хотя выбор всегда ровно один. */
.eq-title { font-size: .78rem; font-weight: 600; color: var(--text-secondary, #4b5563); white-space: nowrap; }
.eq-presets { flex-shrink: 0; }
.eq-preset { padding: .15rem .6rem; font-size: .78rem; }   /* в .wave-controls — общий размер выше */
.eq-preset.active { background: var(--accent, #2563eb); color: #fff; border-color: var(--accent, #2563eb); }

/* Превью перед русской записью в «Получить короткую запись» (askRuContent в
   annotator.js): экран разметки открывается размытым, через секунду поверх —
   предупреждение. Заглушка #ru-preview-fill даёт форму волны и строк. */
.ru-preview-blur #state-task,
.ru-preview-blur #task-toolbar {
  filter: blur(7px);
  pointer-events: none;
  user-select: none;
  transition: filter .3s ease;
}
.ru-preview-fill { padding: 12px 4px; }
.ru-preview-wave {
  height: 96px; border-radius: 8px; margin-bottom: 14px;
  background:
    repeating-linear-gradient(90deg, var(--accent) 0 3px, transparent 3px 7px)
    center / 100% 70% no-repeat,
    var(--surface-2);
  opacity: .55;
}
.ru-preview-row {
  display: flex; gap: 10px; align-items: center;
  padding: 12px; margin-bottom: 8px; border-radius: 8px;
  background: var(--surface-2);
}
.ru-preview-row span {
  height: 12px; border-radius: 6px; flex: 0 0 18%;
  background: var(--text-muted); opacity: .35;
}
.ru-preview-row span:first-child { flex-basis: 8%; }
.ru-preview-row span:last-child { flex: 1 1 auto; }

/* Окно предупреждения перед русской записью (#ru-content-modal). */
.ru-warn { border: 0; border-radius: 14px; overflow: hidden; }
.ru-warn .modal-body { padding: 28px 28px 22px; text-align: center; }
.ru-warn-icon {
  width: 56px; height: 56px; margin: 0 auto 14px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 1.6rem; color: var(--warning);
  background: var(--warning-soft);
}
.ru-warn-title {
  font-size: .8rem; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--warning); margin-bottom: 10px;
}
.ru-warn-lead { font-size: 1.05rem; font-weight: 600; line-height: 1.4; margin-bottom: 6px; }
.ru-warn-sub { font-size: .9rem; color: var(--text-muted); margin-bottom: 18px; }
.ru-warn-remember {
  display: flex; gap: 10px; align-items: flex-start; text-align: left;
  padding: 10px 12px; margin-bottom: 20px; border-radius: 10px; cursor: pointer;
  background: var(--surface-2);
}
.ru-warn-remember .form-check-input { margin-top: 3px; flex: 0 0 auto; }
.ru-warn-remember-title { display: block; font-size: .875rem; font-weight: 600; }
.ru-warn-remember-hint { display: block; font-size: .78rem; color: var(--text-muted); line-height: 1.35; }
.ru-warn-actions { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
.ru-warn-actions .btn { min-width: 190px; }

/* ---- Полоса-превью сегментов (core/seg-minimap.js) ----
   Фиксирована у правого края прокрутки транскрипции, ревью и создания
   датасета: вся лента карточек в сжатом виде + рамка видимого. Заодно зона
   безопасности — над ней колесо и перетаскивание только листают, не попадая
   в поля ввода. Контейнеру добавляется правое поле, чтобы полоса не легла на
   карточки. */
.seg-minimap-host { padding-right: 46px !important; }
.seg-minimap {
  --seg-minimap-w: 22px;
  --seg-minimap-muted: #9ca3af;
  --seg-minimap-accent: var(--accent);
  position: fixed; z-index: 30; width: var(--seg-minimap-w);
  background: var(--surface-sunken); border: 1px solid var(--border); border-radius: 6px;
  cursor: pointer; touch-action: none; user-select: none; overflow: hidden;
}
.seg-minimap canvas { position: absolute; inset: 0; display: block; }
.seg-minimap-thumb {
  position: absolute; left: 0; right: 0; min-height: 14px;
  background: rgba(37,99,235,.10); border: 1.5px solid rgba(37,99,235,.55); border-radius: 4px;
  pointer-events: none; transition: background .12s ease;
}
.seg-minimap:hover .seg-minimap-thumb { background: rgba(37,99,235,.16); }
.seg-minimap.dragging { cursor: grabbing; }
.seg-minimap.dragging .seg-minimap-thumb { background: rgba(37,99,235,.24); border-color: var(--accent); }
.seg-minimap-tip {
  position: fixed; z-index: 1080; max-width: 340px; pointer-events: none;
  padding: 5px 9px; border-radius: 6px; font-size: .75rem; line-height: 1.35;
  background: var(--card-bg); color: var(--text-primary); border: 1px solid var(--border);
  box-shadow: var(--shadow); white-space: pre-line;
}
:root[data-theme="dark"] .seg-minimap { --seg-minimap-muted: #6b7280; }
:root[data-theme="dark"] .seg-minimap-thumb { background: rgba(147,197,253,.10); border-color: rgba(147,197,253,.55); }
@media (max-width: 767px) {
  .seg-minimap, .seg-minimap-tip { display: none !important; }
  .seg-minimap-host { padding-right: 12px !important; }
}

/* ================================================================
   «Продолжение разговора» — чат (core/convo-chat.js)
   Подвал внизу рабочей области (.workspace-layout) и панель, выезжающая из
   него снизу вверх почти на всю высоту. Свёрнутая панель — visibility:hidden:
   поля в ней не ловят Tab, но остаются в DOM (их собирает сохранение).
   ================================================================ */
.workspace-layout { position: relative; }
.convo-dock { flex-shrink: 0; }
.convo-dock-bar {
  width: 100%; display: flex; align-items: center; gap: 8px;
  padding: 9px 24px; border: 0; border-top: 1px solid var(--border);
  background: var(--card-bg); color: var(--text-primary);
  font-size: .875rem; font-weight: 600; text-align: left;
  box-shadow: 0 -2px 8px rgba(17,24,39,.04);
}
.convo-dock-bar:hover { background: var(--hover-bg); }
.convo-dock-bar .convo-dock-hint { font-weight: 400; font-size: .78rem; color: var(--text-secondary); }
.convo-dock-bar .convo-dock-arrow { margin-left: auto; font-size: 1rem; color: var(--text-secondary); }

.convo-panel {
  position: absolute; left: 0; right: 0; bottom: 0; top: 18px; z-index: 40;
  display: flex; flex-direction: column;
  background: var(--body-bg);
  border-top: 1px solid var(--border); border-radius: 16px 16px 0 0;
  box-shadow: 0 -12px 36px rgba(17,24,39,.20);
  transform: translateY(100%); visibility: hidden;
  transition: transform .28s cubic-bezier(.2,.8,.2,1), visibility 0s linear .28s;
}
.convo-dock.open .convo-panel {
  transform: none; visibility: visible;
  transition: transform .28s cubic-bezier(.2,.8,.2,1), visibility 0s;
}
.convo-head {
  flex-shrink: 0; display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 20px; background: var(--card-bg);
  border-bottom: 1px solid var(--border); border-radius: 16px 16px 0 0;
}
.convo-head-title { font-size: .95rem; font-weight: 600; }
.convo-head-sub { font-size: .76rem; color: var(--text-secondary); }
.convo-head-actions { margin-left: auto; display: flex; gap: 6px; align-items: center; }

.convo-stream { flex: 1; overflow-y: auto; padding: 22px 0 28px; }
.convo-stream-inner {
  max-width: 980px; margin: 0 auto; padding: 0 20px;
  display: flex; flex-direction: column; gap: 22px;
}
.convo-turn { display: flex; flex-direction: column; gap: 12px; }
.convo-turns { display: flex; flex-direction: column; gap: 22px; }
.convo-turns:empty { display: none; }
.convo-turn-head {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: .75rem; color: var(--text-secondary);
}
.convo-turn-head::after { content: ''; flex: 1; order: 50; border-top: 1px dashed var(--border); min-width: 20px; }
.convo-turn-head > .convo-turn-tools { order: 60; display: flex; gap: 6px; align-items: center; }
.convo-turn-head .convo-turn-title { font-weight: 600; color: var(--text-primary); }
.convo-turn-head select.form-select { max-width: 300px; font-size: .75rem; padding-top: 1px; padding-bottom: 1px; }

.convo-msg { display: flex; gap: 10px; align-items: flex-start; }
.convo-msg-user { flex-direction: row-reverse; }
.convo-avatar {
  width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0;
  display: grid; place-items: center; font-size: .9rem;
}
.convo-msg-user .convo-avatar { background: var(--accent); color: #fff; }
.convo-msg-model .convo-avatar { background: var(--grad-primary); color: #fff; }
.convo-bubble {
  min-width: 0; max-width: min(820px, 86%);
  padding: 10px 14px; border-radius: 16px;
  font-size: .84rem; line-height: 1.5; color: var(--text-primary);
}
.convo-msg-user .convo-bubble {
  background: var(--accent-soft); border-top-right-radius: 4px;
  min-width: min(440px, 86%);
}
.convo-msg-model .convo-bubble {
  flex: 1; background: var(--card-bg); border: 1px solid var(--border);
  border-top-left-radius: 4px; box-shadow: var(--shadow-sm);
}
.convo-who {
  font-size: .72rem; font-weight: 600; color: var(--text-secondary);
  margin-bottom: 4px; display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
}
.convo-who-note { font-weight: 400; color: var(--text-muted); }
.convo-text { white-space: pre-wrap; overflow-wrap: anywhere; }
.convo-empty { color: var(--text-secondary); font-style: italic; }
.convo-bubble textarea.form-control {
  background: var(--card-bg); font-size: .82rem; line-height: 1.5;
}
.convo-bubble .form-label { font-size: .72rem; color: var(--text-secondary); margin-bottom: 2px; }

/* Текст вместо поля (превью); клик — снова поле ввода. */
.convo-view {
  cursor: text; border-radius: 8px; padding: 2px 4px; margin: 0 -4px;
  overflow-wrap: anywhere;
}
.convo-view:hover { background: rgba(37,99,235,.06); }
.convo-plain { white-space: pre-wrap; }
.convo-view .ds-md { font-size: .84rem; }
.convo-clamp {
  max-height: 9.5em; overflow: hidden;
  -webkit-mask-image: linear-gradient(#000 70%, transparent);
          mask-image: linear-gradient(#000 70%, transparent);
}
.convo-clamp.convo-clamp-open { max-height: none; -webkit-mask-image: none; mask-image: none; }

/* Рассуждение — свёрнутым блоком «мысли», как в чатах с reasoning. */
.convo-think { margin-bottom: 8px; border-left: 3px solid var(--border); padding-left: 10px; }
.convo-think > summary {
  font-size: .75rem; color: var(--text-secondary); cursor: pointer; list-style: none;
  display: inline-flex; align-items: center; gap: 4px;
}
.convo-think > summary::-webkit-details-marker { display: none; }
.convo-think > summary::before { content: "\25B8"; font-size: .7rem; transition: transform .15s; }
.convo-think[open] > summary::before { transform: rotate(90deg); }
.convo-think textarea, .convo-think .convo-view { margin-top: 4px; font-size: .8rem; color: var(--text-secondary); }

/* Расшифровка первого ответа модели. */
.convo-transcript {
  margin: 0; font-family: var(--font-mono); font-size: .74rem; line-height: 1.55;
  white-space: pre-wrap; overflow-wrap: anywhere; color: var(--text-primary);
  max-height: 16.5em; overflow: hidden;
}
.convo-transcript.clamped {
  -webkit-mask-image: linear-gradient(#000 75%, transparent);
          mask-image: linear-gradient(#000 75%, transparent);
}
.convo-transcript.expanded { max-height: none; -webkit-mask-image: none; mask-image: none; }
.convo-more {
  border: 0; background: none; padding: 4px 0 0; font-size: .75rem;
  color: var(--accent); cursor: pointer;
}
.convo-more:hover { text-decoration: underline; }

/* Аудио, «приложенное» к первому сообщению: играет общий плеер страницы. */
.convo-audio {
  margin-top: 8px; display: flex; align-items: center; gap: 10px;
  padding: 7px 12px 7px 7px; border-radius: 12px;
  background: var(--card-bg); border: 1px solid var(--border); max-width: 380px;
}
.convo-audio-play {
  width: 34px; height: 34px; border-radius: 50%; border: 0; flex-shrink: 0;
  background: var(--accent); color: #fff; display: grid; place-items: center; font-size: 1.1rem;
}
.convo-audio-play:hover { background: var(--accent-hover); }
.convo-audio-body { flex: 1; min-width: 0; }
.convo-audio-name { font-size: .74rem; color: var(--text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.convo-audio-bar { height: 5px; margin-top: 5px; border-radius: 3px; background: var(--chip-bg); cursor: pointer; overflow: hidden; }
.convo-audio-bar > span { display: block; height: 100%; width: 0; background: var(--accent); border-radius: 3px; }
.convo-audio-time { font-size: .72rem; color: var(--text-secondary); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* «Генерация ответа» — в подписи «Модель» хода, справа. */
.convo-who .convo-gen-answer {
  margin-left: auto; font-size: .72rem; font-weight: 500;
  padding: 1px 8px; line-height: 1.5;
}
.convo-who .convo-gen-answer .spinner-border-sm { width: .7rem; height: .7rem; border-width: .15em; }

/* «Генерация отчётов»: строка «модель пишет…» под ходом, который пишется. */
.convo-msg-model .convo-bubble.convo-gen {
  flex: 0 1 auto; color: var(--text-secondary); display: flex; align-items: center;
}
.convo-msg-model .convo-bubble.convo-gen-wait {
  color: var(--warning); border-color: var(--warning); background: var(--warning-soft);
}
/* Курсор набора у поля, в которое модель пишет прямо сейчас. */
.convo-typing .convo-plain::after,
.convo-typing .ds-md > :last-child::after {
  content: ''; display: inline-block; width: .5em; height: 1.05em; margin-left: 2px;
  vertical-align: text-bottom; background: var(--accent); border-radius: 1px;
  animation: convo-caret 1s steps(1) infinite;
}
@keyframes convo-caret { 50% { opacity: 0; } }
/* Полоса чтения промта до первого токена. */
.convo-prefill { min-width: min(420px, 70vw); }
.convo-prefill-bar { height: 5px; margin-top: 6px; border-radius: 3px; background: var(--chip-bg); overflow: hidden; }
.convo-prefill-bar > span { display: block; height: 100%; background: var(--accent); transition: width .4s linear; }
.convo-msg-model .convo-bubble.convo-gen-error {
  color: var(--danger); border-color: var(--danger); background: var(--danger-soft);
}

.convo-hint { text-align: center; font-size: .8rem; color: var(--text-secondary); padding: 6px 0; }

/* Полоса «+» внизу панели. */
.convo-composer {
  flex-shrink: 0; border-top: 1px solid var(--border); background: var(--card-bg);
  padding: 10px 20px;
}
.convo-composer-inner { max-width: 980px; margin: 0 auto; display: flex; align-items: center; gap: 12px; }
.convo-plus {
  width: 38px; height: 38px; border-radius: 50%; flex-shrink: 0;
  border: 1px solid var(--border-input); background: var(--card-bg); color: var(--accent);
  font-size: 1.35rem; line-height: 1; display: grid; place-items: center;
}
.convo-plus:hover, .convo-plus.show { background: var(--accent); color: #fff; border-color: var(--accent); }
.convo-composer-hint { font-size: .8rem; color: var(--text-secondary); }
.convo-menu { max-height: 62vh; overflow-y: auto; min-width: 320px; font-size: .84rem; }
.convo-menu .dropdown-header { font-size: .72rem; text-transform: uppercase; letter-spacing: .04em; }
.convo-menu-group { padding: 4px 16px 2px 24px; font-size: .74rem; font-weight: 600; color: var(--text-secondary); }
.convo-menu .convo-menu-sub { padding-left: 36px; }
.convo-menu .dropdown-item:disabled { opacity: .55; }

@media (max-width: 767px) {
  /* Страница на телефоне прокручивается целиком — подвал прибит к низу окна,
     а его место в потоке держит сам .convo-dock, чтобы не закрыть конец ленты. */
  .convo-dock { height: 42px; }
  .convo-dock-bar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 1040; padding: 9px 12px; }
  .convo-panel { position: fixed; top: 0; border-radius: 0; z-index: 1045; }
  .convo-head { border-radius: 0; padding: 10px 12px; }
  .convo-stream-inner, .convo-composer { padding-left: 12px; padding-right: 12px; }
  .convo-bubble { max-width: 100%; }
  .convo-msg-user .convo-bubble { min-width: 0; }
  .convo-avatar { display: none; }
}

/* ---- «Проверить голд» (core/gold-check.js) ---- */
.gc-segs { display: flex; flex-direction: column; gap: 2px; }
.gc-seg {
  display: flex; align-items: flex-start; gap: 8px; padding: 6px 8px;
  border-radius: var(--radius-sm); cursor: pointer; line-height: 1.45;
}
.gc-seg:hover { background: var(--hover-bg); }
.gc-seg.active { background: var(--accent-soft); box-shadow: inset 3px 0 0 var(--accent); }
.gc-seg-aux .gc-seg-text { font-size: .9em; }
.gc-seg-time { font-family: var(--font-mono); font-size: .78rem; color: var(--text-muted); min-width: 52px; padding-top: 2px; }
.gc-seg-text { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.gc-seg-lang { font-weight: 500; font-size: .68rem; }
.gc-comment {
  margin-top: 12px; padding: 8px 12px; border-radius: var(--radius-sm);
  background: var(--surface-2); color: var(--text-secondary); font-size: .9rem;
}
.gc-cat-select { width: auto; max-width: 240px; }
@media (max-width: 575px) {
  #gold-check-modal .modal-footer { flex-wrap: wrap; }
  .gc-cat-select { max-width: none; width: 100%; }
}
