/* Ключи Мастерства · LMS — дизайн-система
   Снята с действующего сайта. Холодный светлый фон, тёплые оранжевые акценты.
   Шрифты темы BuddyBoss: Open Sans (текст) + Roboto Condensed (заголовки).
   Кнопки НЕ таблетки — радиус 10px, как у полей и плашек. */

/* Атрибут hidden обязан побеждать display компонентов.
   Почти каждый класс здесь задаёт display: flex или block, и он перебивает
   правило браузера для [hidden] — спрятанный элемент остаётся на экране.
   Ловится это только глазами: разметка выглядит правильной. */
[hidden] {
  display: none !important;
}

:root {
  /* Цвет */
  --km-accent: #E8703A;
  --km-accent-light: #EE8B5F;
  --km-peach: #FBE3D5;
  --km-warm-bg: #FDF2EB;
  --km-warm-border: #F3C9AE;
  --km-warm-text: #6B5347;
  --km-warm-text-strong: #8A4A28;

  --km-text: #3F4C5C;
  --km-text-secondary: #77869A;
  --km-text-muted: #9AA7B6;
  --km-text-faint: #B5BFCA;
  --km-star-bg: #FFF4D6;
  --km-star-border: #F6D58A;

  --km-page: #F6F8FB;
  --km-surface: #FFFFFF;
  --km-surface-alt: #FAFBFD;
  /* Стрелка выпадающего списка — одна на все места, где её рисуют: `.km-select` здесь и шов админки
     (`admin-rhythm.css`), который своим `background` её затирал (разбор этапа 6 звёзд, 13.10.2026). */
  --km-select-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 14 14' fill='none'%3E%3Cpath d='M3 5.2l4 4 4-4' stroke='%239AA7B6' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  /* Сиреневые фон и черта — карточка «Расписание трансляций» по макету
     `design/schedule-block-v1.html` (слово Алены 30.09.2026: цвет карточки —
     как в макете). Палитра трансляции (`--km-cast-*`) живёт только внутри
     `.km-cast`, а блок стоит и на страницах занятий, поэтому — здесь. */
  --km-lilac-bg: #F8F5FA;
  --km-lilac-line: #EEE7F3;
  --km-border: #E7EBF0;
  --km-border-soft: #F1F4F8;
  --km-track: #EDF1F6;

  /* Служебное — то, что видит ведущий и не видит курсант.
     Холодный серо-синий: он не спорит с тёплыми акцентами занятия
     и сразу читается как «это не часть материала».
     Числа из макета `design/conditional-staff-note-v1.html`. */
  --km-staff: #5B7089;
  --km-staff-bg: #EEF2F7;
  --km-staff-border: #D6DEE8;
  /* Рейтинг по звёздам («Звёзды курса» 1.28, 6.10; макет `design/reyting-vkladka-v1.dc.html`): кружки мест 1–3 —
     золото, серебро, бронза; «···» над своей строкой; буквы имени без фото — пять пар по кругу. */
  --km-medal-gold: #F4B740;
  --km-medal-gold-ink: #6B3F06;
  --km-medal-silver: #D5DCE4;
  --km-medal-bronze: #E9B48C;
  --km-medal-bronze-ink: #5C3216;
  --km-rank-dots: #B7C1CD;
  --km-ava-1: #E7D3E8; --km-ava-1-ink: #5E4270;
  --km-ava-2: #DCE4EF; --km-ava-2-ink: #2F5A7A;
  --km-ava-3: #F3EAD9; --km-ava-3-ink: #7A5A2A;
  --km-ava-4: #E3EEDF; --km-ava-4-ink: #3F6A3A;
  --km-ava-5: #F4DFD2; --km-ava-5-ink: #8A4A28;

  /* Жёлтая плашка — «не сломалось, а не дописано».
     Заведена 27 августа 2026 под строку условного блока «блок не покажется
     никому». Отдельно от `--km-danger`: красный говорит «сломалось», и там,
     где человек просто не заполнил поле, он врёт про причину.
     Числа из макетов `conditional-block-v1.html` и `lesson-blocks-v2.html`. */
  --km-warn-bg: #FEF8E7;
  --km-warn-border: #EFD9A0;
  --km-warn-text: #8A6A16;

  /* Фирменные цвета курса — тёмно-синий заголовка и бирюзовый.
     Сняты 6 сентября 2026 с продающей страницы курса вычисленными
     значениями (`getComputedStyle`), а не подобраны на глаз:
     promo.kluchimasterstva.ru/probuzhdenie-chakr-sentjabr-2026,
     заголовок там разбит на две части ровно так же.

     Токенами, а не по месту: цвет спрашивают заголовок, надзаголовок,
     подпись и имя ведущей, и второе написание разошлось бы молча. */
  --km-brand-navy: #33315E;
  --km-brand-teal: #237C82;

  --km-danger: #B4432B;
  /* Красный «идёт эфир» — свой, а не danger: тревоги тут нет, есть «сейчас». */
  --km-live: #D33A3A;
  --km-danger-bg: #FBE0DA;
  --km-danger-border: #F0BDB0;

  /* Типографика */
  --km-font: 'Open Sans', system-ui, sans-serif;
  --km-font-display: 'Roboto Condensed', 'Open Sans', sans-serif;
  --km-mono: ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Форма */
  --km-ok: #2E7D5B;

  /*
   * ЗЕЛЁНЫЙ «СДЕЛАНО» — цвет системы. Решение Алены 13 сентября 2026.
   *
   * Им помечается пройденное: лента на обложке курса, плашка и полоса
   * в карточке прогресса, а дальше — пройденные занятия на карте
   * и карточка курса в «Моих курсах».
   *
   * **Имя новое, а число старое, и это нарочно.** Тот же зелёный уже
   * два этапа живёт в системе как `--km-ok` — состояние формы, «в порядке».
   * Напиши мы `#2E7D5B` второй раз, и одинаковое правило оказалось бы
   * записано дважды: сменят зелёный в одном месте, второе отстанет молча.
   * Поэтому здесь имя смысла, а значение берётся у того, кто его держит.
   *
   * Смыслов при этом два, и они не сливаются: `--km-ok` — «идёт как надо»
   * у формы, `--km-done` — «сделано» у человека. Разойдутся однажды —
   * правится одна строка, а не поиск по числу.
   */
  --km-done: var(--km-ok);
  --km-done-bg: #E9F4F2;
  --km-done-border: #CBE5DE;
  /*
   * Светлее на наведение — пара к `--km-accent-light` и по той же причине:
   * заливка кнопки обязана отвечать на курсор, а высветлять её по месту
   * значило бы завести оттенок, которого в системе нет.
   *
   * Здесь число, а не ссылка: это самостоятельное значение, а не второе
   * написание `--km-done`. Ссылкой был бы тот же цвет под другим именем.
   */
  --km-done-light: #3A9A70;
  /* Жёлтый «скоро понадобится» — между зелёным «ничего не надо»
     и красным «надо сейчас». До таблицы зачислений его в системе
     не было: цветов было два, а срочностей три. */
  --km-warn: #C77700;

  /*
   * Отступ под подписью блока: подпись прижата к тому, что под ней,
   * а не стоит посередине между верхним и нижним.
   *
   * Числом, а не литералом в двух местах: так стоит подпись на карточке
   * и так же должна стоять подпись блока на странице — человек видит
   * эти два места рядом на одном экране, и разъехаться им негде.
   */
  --km-gap-label: 10px;

  /*
   * Расстояние МЕЖДУ группами: между тем, что подписью друг другу
   * не является. Внутри группы — `--km-gap-label`.
   *
   * Число не новое: это то же шестнадцать, которым `km-stack` разносит
   * блоки по умолчанию. Оно и стояло литералом в трёх местах — здесь
   * получило имя, и литералов не осталось: `.km-stack` и отступ вкладок
   * читают отсюда. Одно число, одно написание.
   *
   * Заведено 3 сентября 2026 по карточке кабинета: там все пять
   * промежутков стояли на `--km-gap-label`, то есть групп не было вовсе,
   * и срок читался второй подписью к полосе прогресса — он стоял к ней
   * на 11 пикселей при 12 у самой подписи.
   */
  --km-gap-group: 16px;

  /*
   * Расстояние между абзацами короткого текста: письма и окна на платформе.
   *
   * Число не новое: это двенадцать, которым `.km-letter-preview` разносил
   * абзацы письма литералом. Имя получило 22 сентября 2026, когда те же
   * абзацы понадобились окну (снимок Алены: всё шло одним комом через 10),
   * — и литерала у письма не осталось. Длинный текст занятия (`.km-prose`)
   * живёт на своих шестнадцати: там читают страницами, здесь — три строки.
   */
  --km-gap-paragraph: 12px;

  --km-radius-card: 16px;
  --km-radius-control: 10px;
  --km-radius-badge: 6px;
  --km-shadow-card: 0 2px 12px rgba(63, 76, 92, 0.06);
  --km-shadow-lift: 0 6px 18px rgba(63, 76, 92, 0.14);

  /* Сколько сверху занимает чужая обвязка: липкая шапка темы, панель
     администратора, промо-полоса Elementor. Считает `assets/js/chrome.js`
     живым замером — числом это записать нельзя, потому что слагаемых три
     и каждое приходит и уходит само: панель видна администратору,
     промо-полоса закрывается крестиком, шапка есть всегда.

     Ноль по умолчанию — значение для стенда и для страницы без темы.
     Ошибка выбрана в заметную сторону: при нуле липкая колонка уезжает
     под шапку, и это видно; при завышенном числе над колонкой пустая
     полоса, и это читается как «так задумано». */
  --km-chrome-top: 0px;

  /* Размер знака узла — ОДНО ЧИСЛО на дерево и на перечни.
     Дерево переопределяет его по уровням (топик мельче, колонка плеера
     мельче обоих), перечень берёт как есть. Написанное дважды, оно
     разъехалось бы на первой же правке лестницы — и разъехалось бы
     незаметно, на несколько пикселей. */
  --km-glyph: 19px;
}

/* ---------------------------------------------------------------------------
   Чужая обвязка: единственное место, где дизайн-система правит не своё
   ---------------------------------------------------------------------------

   `.site` — контейнер темы BuddyBoss, и у него `overflow: hidden auto`.
   Горизонтальная половина там осмысленна: тема гасит боковую прокрутку
   от своих виджетов. Вертикальная — довесок сокращённой записи, и она
   **отменяет липкость всего, что лежит внутри**: `position: sticky` считает
   от ближайшего предка с прокруткой, а `.site` сам не прокручивается —
   прокручивается окно. Прилипать не к чему, и элемент просто стоит
   на месте.

   Так и вышло: колонка навигации плеера и боковая колонка страницы курса
   объявлены липкими с 0.72.0 и 0.73.0 — и ни одна не липла на боевом.
   Обе проверялись стендом, а `.site` там нет вовсе: стенд собран одним
   файлом без темы. Ровно тот класс, что записан в `CLAUDE.md` про экран
   и стенд — каждая часть по отдельности права, а видно это только
   на собранной странице.

   `clip` вместо `hidden` оставляет обрезку и **не заводит прокрутки**:
   для человека поведение то же, для липкости — разница между «работает»
   и «не работает». Проверено живым замером на боевом: колонка едет вдоль
   страницы, горизонтальной прокрутки не появилось.

   **Селектор подобран под чужой, а не взят с потолка.** Тема пишет так:

       body:not(.page-template-page-fullscreen, .elementor-page) .site
       { overflow-x: hidden }

   Это (0,2,1) — простой `.site` слабее и молча проиграл бы.

   **Наш селектор СИЛЬНЕЕ, (0,2,2), и не держится на порядке.** До 17 сентября
   2026 он был той же силы, (0,2,1), и выигрывал ничью тем, что стоял позже:
   `design-system.css` печатался в подвале, после темы. С 1.263.0 (15 сентября)
   таблица печатается в голове — 45-й из 75, тема после неё, — ничья ушла
   теме, и колонка перестала липнуть на всех наших страницах. Заметила
   Алена на снимке 17 сентября: дерево обрывается посреди окна. Лишний `html`
   в начале — единственное, что отличает правило от прежнего, и снимать его
   нельзя: без него победа снова зависит от того, кто подключён позже.

   `:has()` держит охват на наших экранах: правило нужно там, где стоит
   липкая колонка, а не на всех страницах сайта. Двух корней хватает
   и они устойчивы — `.km-page` у всех наших экранов, `.km-player`
   у плеера, где `.km-page` нет по устройству.

   Найдено живым замером на боевом: до правки колонка при прокрутке
   не сдвигалась ни на пиксель, после — едет вдоль страницы, и
   горизонтальной прокрутки не появилось. */
html body .site:has(.km-page, .km-player) {
  overflow-x: clip;
  overflow-y: visible;
}

/* Основа */
body {
  margin: 0;
  background: var(--km-page);
  font-family: var(--km-font);
  font-size: 16px;
  line-height: 1.65;
  color: var(--km-text);
  -webkit-font-smoothing: antialiased;
}
* { box-sizing: border-box; }
a { color: var(--km-accent); text-decoration: none; }
a:hover { color: var(--km-accent-light); }

/* Типографика: H1 36 / H2 32 / H3 26 / H4 24 / H5 20 — по кастомайзеру темы */
.km-h1, .km-h2, .km-h3, .km-h4, .km-h5 {
  font-family: var(--km-font-display);
  font-weight: 700;
  margin: 0;
}
.km-h1 { font-size: 36px; line-height: 1.2; }
.km-h2 { font-size: 32px; line-height: 1.25; }
.km-h3 { font-size: 26px; line-height: 1.3; }
.km-h4 { font-size: 24px; line-height: 1.35; }
.km-h5 { font-size: 20px; line-height: 1.4; }

.km-text { font-size: 16px; line-height: 1.65; }
.km-text-secondary { font-size: 14px; line-height: 1.6; color: var(--km-text-secondary); }
.km-meta { font-size: 12px; line-height: 1.4; color: var(--km-text-muted); }

/* Надзаголовок раздела — заглавными, заметная черта сайта */
.km-eyebrow {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--km-text-muted);
}
.km-section-title {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--km-text-muted);
}

/* Кнопки */
.km-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-family: inherit;
  font-size: 15px;
  font-weight: 600;
  line-height: 1;
  border: none;
  border-radius: var(--km-radius-control);
  padding: 13px 26px;
  cursor: pointer;
  transition: background 0.16s, border-color 0.16s, color 0.16s;
}
/* Состояния перечислены списком — те же, что трогает тема (см. разбор
   у `.km-btn--secondary` ниже). Наведение меняет оттенок строкой ниже. */
.km-btn--primary,
.km-btn--primary:hover,
.km-btn--primary:focus,
.km-btn--primary:active { background: var(--km-accent); color: #fff; box-shadow: none; }
.km-btn--primary:hover { background: var(--km-accent-light); }/* ЧУЖОЕ УМОЛЧАНИЕ КНОПКИ ГАСИТСЯ В ТЕХ ЖЕ СОСТОЯНИЯХ, В КАКИХ ОНО ОБЪЯВЛЕНО.
 *
 * Найдено стендом «Моих работ» 16 сентября 2026 — и найдено только потому,
 * что общую мерку `themeBleed` впервые позвали на **нашу кнопку**. До того
 * её звали на вкладку «Заметили ошибку» и крестик панели, а `.km-btn`
 * не спрашивал никто: дефект жил не потому, что его пропустили, а потому,
 * что вопрос не задавали.
 *
 * Тема BuddyBoss объявляет у `button` фон и тень в `:hover` и `:focus`.
 * Здесь фон стоял в базовом состоянии и в `:focus`, а `:hover` в список
 * не попал — и на наведении тема подкладывала белую плашку со своей тенью.
 * `:focus` при этом фон объявлял, но тень гасить было нечем.
 *
 * Тот же приём, что у `.km-tab` (правка 19 августа 2026) и у
 * `.km-btn--text` с `.km-btn--quiet`: состояния перечисляются списком —
 * ровно те, что перечислила тема. Вес у нас (0,2,0) против её (0,1,1),
 * так что выигрываем объявлением, а не утяжелением селектора.
 *
 * Цена на день находки: 47 употреблений в 24 файлах — каталог, страница
 * курса, занятие, кабинет и десять административных экранов. */
.km-btn--secondary,
.km-btn--secondary:hover,
.km-btn--secondary:focus,
.km-btn--secondary:active {
  background: var(--km-surface);
  color: var(--km-text);
  border: 1px solid var(--km-border);
  box-shadow: none;
}

/* РАЗМЕР — ОТДЕЛЬНЫМ ПРАВИЛОМ, БЕЗ СОСТОЯНИЙ. *Дефект, найденный Аленой
   23 сентября 2026: «кнопка меняет размер и обводку при наведении».*

   Поля стояли в списке состояний, и у списка вес (0,2,0) против (0,1,0)
   у `.km-btn--sm`: без курсора мелкая кнопка держала свои 9/18, под
   курсором её перебивали 12/25 — «Показать ещё» росла со 191×33 до 205×39
   (замер на стенде). Вид решает цвет и рамку, размер решает размерный
   класс — и решает во всех состояниях. Правило стоит ВЫШЕ `--sm` и `--lg`
   с тем же весом: тогда размерный класс выигрывает порядком. */
.km-btn--secondary,
/* Тёплая кнопка своего курса объявлена в разделе каталога, а размер её —
   здесь: правило обязано стоять выше `--sm` и `--lg`, иначе вид перебьёт
   размер уже без всякого наведения. */
.km-btn--warm { padding: 12px 25px; }

/* Наведение меняет ТОЛЬКО рамку и подпись — фон объявлен выше во всех
   четырёх состояниях и перебивать его нечем и незачем. */
.km-btn--secondary:hover { border-color: var(--km-warm-border); color: var(--km-accent); }

/* Кнопка «сделано» — зелёная заливка. Правка Алены 13 сентября 2026.
 *
 * Стоит она на карточке пройденного курса и говорит то же, что плашка над
 * ней: здесь всё закончено. Оранжевая звала бы к действию, а звать больше
 * некуда — человек приходит перечитать.
 *
 * Белым по плотному зелёному: на светлой заливке белый текст пропал бы,
 * а тёмный спорил бы с плашкой. */
.km-btn--done,
.km-btn--done:hover,
.km-btn--done:focus,
.km-btn--done:active { background: var(--km-done); color: #fff; box-shadow: none; }
.km-btn--done:hover { background: var(--km-done-light); }

.km-btn--muted,
.km-btn--muted:hover,
.km-btn--muted:focus,
.km-btn--muted:active { background: var(--km-peach); color: var(--km-warm-text-strong); box-shadow: none; }
.km-btn--muted:hover { background: #F7D6C3; }.km-btn--text,
.km-btn--text:focus{ background: transparent; color: var(--km-accent); }
/* Размер — без состояний, см. разбор у `--secondary`. */
.km-btn--text { padding: 12px 14px; }
.km-btn--text:hover { color: var(--km-accent-light); }

/* Неяркое второстепенное действие: «Отметить пройденным» */
.km-btn--quiet,
.km-btn--quiet:focus {
  background: transparent;
  color: var(--km-text-secondary);
  border: 1px solid var(--km-border);
  font-weight: 500;
}
/* Размер — без состояний, см. разбор у `--secondary`. */
.km-btn--quiet { font-size: 14px; padding: 12px 22px; }
.km-btn--quiet:hover { color: var(--km-accent); border-color: var(--km-warm-border); }

.km-btn--danger,
.km-btn--danger:hover,
.km-btn--danger:focus,
.km-btn--danger:active {
  background: var(--km-surface);
  color: var(--km-danger);
  border: 1px solid var(--km-danger-border);
  font-weight: 500;
  box-shadow: none;
}
.km-btn--danger:hover { background: #FDF0EC; }

/* КВАДРАТНАЯ КНОПКА — только знак, без подписи: стрелки в шапке занятия
   (12.2, решение Алены 23 сентября 2026). Размер задаёт она, вид — класс
   вида, как у любой другой кнопки; поля обнулены, иначе знак уехал бы
   из середины. Стоит выше `--sm` и `--lg` тем же весом: размер решает
   размерный класс, и последний из них выигрывает порядком. */
.km-btn--square { width: 34px; height: 34px; padding: 0; }

.km-btn--sm { font-size: 13px; padding: 9px 18px; }
.km-btn--lg { font-size: 16px; padding: 15px 32px; border-radius: 12px; }
.km-btn--block { width: 100%; }
.km-btn[disabled] { background: #F1F4F8; color: #B6C0CC; cursor: not-allowed; }

/* Бейджи */
.km-badge {
  display: inline-block;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border-radius: var(--km-radius-badge);
  padding: 5px 9px;
  white-space: nowrap;
}
.km-badge--accent { background: var(--km-accent); color: #fff; }
.km-badge--peach { background: var(--km-peach); color: #A8592F; }
.km-badge--neutral { background: #F1F4F8; color: var(--km-text-secondary); }
.km-badge--outline {
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  color: var(--km-text-muted);
  padding: 4px 8px;
}
.km-badge--danger { background: var(--km-danger-bg); color: var(--km-danger); }

/* Плашка «сделано»: светлая заливка, зелёный текст, тонкая рамка.
 *
 * Кегль и строчные буквы — из макета `course-completed-v2.html`, и это
 * не отступление от общего вида бейджа, а его смысл: остальные бейджи
 * помечают ЧТО это (вид курса, скидка), а этот отвечает человеку про него
 * самого — «вы прошли». Заглавные десятым кеглем читаются как ярлык
 * на товаре, и рядом с «Ваш прогресс» это звучало бы чужим голосом.
 *
 * Галочка внутри — `svg` разметкой, а не символом шрифта: у значка нет
 * текста, и диктору читать его нечего. */
.km-badge--done {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	font-size: 12.5px;
	font-weight: 700;
	letter-spacing: 0;
	text-transform: none;
	padding: 5px 11px 5px 9px;
	border-radius: 8px;
	background: var(--km-done-bg);
	color: var(--km-done);
	border: 1px solid var(--km-done-border);
}

/* Крупный бейдж — шапка курса. Отдельный размер, а не «тот же, что в списке»:
   в макете он 11px с разрядкой 0.06em, потому что читается издали и стоит
   один-два, а не двадцать в строке таблицы. */
.km-badge--lg {
	font-size: 11px;
	letter-spacing: 0.06em;
	border-radius: 8px;
	padding: 6px 12px;
}

/* Поверх обложки бейджи полупрозрачны: сплошная заливка на светлой картинке
   выглядит наклейкой, а сквозь неё видно, что под ней фотография.

   ЗДЕСЬ СТОЯЛ ОДИН ЭТОТ КОММЕНТАРИЙ, А ПРАВИЛА ПОД НИМ НЕ БЫЛО. Обещание
   без кода: бейдж носил `km-badge--peach` — светлую заливку, — и на светлой
   обложке не читался вовсе. Найдено 3 сентября 2026 по слову человека.

   Подложка взята у бейджей шапки гостевой (`course-page-guest-v2.html`):
   белая с прозрачностью 0,9 и тёплый тёмный текст. Она перебивает
   `--peach` и любой другой вид: поверх картинки решает место, а не вид,
   и это единственное правило, у которого есть право так делать. */

/* ТЕКСТ ГЛАВНОЙ КНОПКИ ЗАДАЁТСЯ ЯВНО во всех состояниях.
 *
 * Шапка с наложением красит всё внутри белым, а тема добавляет своё
 * правило на нажатую ссылку — и на активной кнопке надпись пропадала:
 * белый по оранжевому превращался в оранжевый по оранжевому. Наследование
 * здесь не годится: цвет кнопки не зависит от того, на каком фоне
 * она стоит. */
.km-btn--primary,
.km-btn--primary:link,
.km-btn--primary:visited,
.km-btn--primary:hover,
.km-btn--primary:focus,
.km-btn--primary:active { color: #fff; }

/* Кнопка ПЕРЕД ценой — так в макете гостя. В липкой полосе порядок
   обратный, и это тоже макет: там цена читается первой, а кнопка стоит
   у самого края. Разметка одна, порядок решает место. */
.km-hero__body .km-actions { flex-direction: row-reverse; justify-content: flex-end; gap: 18px; }
/* ЦЕНА С ПОДПИСЬЮ ПОД НЕЙ ОСТАЁТСЯ РЯДОМ С КНОПКОЙ. Макет: «в одну строку
   по общей средней линии». Подпись («или в три платежа», бесплатный срок)
   делала блок цены шире места рядом с кнопкой, и на 375 он уходил строкой
   ниже (стенд, 19 сентября 2026; у «даровых дней» — с 8 сентября). Блок цены
   сжимается, подпись переносится внутри него. */
.km-hero__body .km-actions > .km-price { flex: 1 1 0; min-width: 0; }

/* ЦЕНА И СЧЁТ КУРСАНТОВ В ШАПКЕ — СВОИМИ ЦВЕТАМИ И РАЗМЕРАМИ.
 *
 * Общие правила писаны под светлый фон: цена тёмная, «от» и счёт серые,
 * подпись мелкая. Поверх обложки это нечитаемо — на снимке боевой цена
 * тонула в картинке, а счёт был почти невидим.
 *
 * Наследованием это не лечится: у цены свой цвет по дизайн-системе,
 * и он верен там, где она стоит на белом. Поэтому правила именно
 * для шапки с наложением, а не правка общих. */
/* Высокая шапка — только продающая страница: там она первое, что видит
   человек, и в неё вложены бейджи, подпись, цена с кнопкой и курсанты.
   У участника шапка это заголовок над рабочим экраном, и 460 отнимали
   у него пол-экрана ни за чем. */
.km-hero--tall .km-hero__body { min-height: 500px; }

.km-hero--over .km-price { color: #fff; font-size: 17px; }
.km-hero--over .km-price__from { color: rgba(255, 255, 255, 0.85); font-size: 15px; }
/* Число платежей поверх обложки: белым, как сама цена, а не приглушённым
   серым. Затемнение обложки к низу почти сходит на нет (0,05 у края),
   и на светлой картинке `#9AA7B6` пропадал — измерено на боевом.

   Значения не новые: цвет от `.km-hero--over .km-price` строкой выше,
   кегль от `.km-price__from` — подпись и подпись. Непрозрачным, в отличие
   от «от»: «от» уточняет, а «× 3» меняет смысл суммы втрое. */
.km-hero--over .km-price__stages { color: #fff; font-size: 15px; }
.km-hero--over .km-meta { color: rgba(255, 255, 255, 0.9); font-size: 14px; }
.km-hero--over .km-hero__lead { color: rgba(255, 255, 255, 0.9); font-size: 16px; max-width: 560px; }

/* Строка курсантов: кружки и подпись рядом, как в макете. */
.km-hero__learners { display: flex; align-items: center; gap: 12px; margin-top: 8px; }

.km-hero--over .km-badge--peach { background: rgba(251, 227, 213, 0.95); color: var(--km-warm-text-strong); }
.km-hero--over .km-badge--accent { background: rgba(232, 112, 58, 0.95); }

/* Крошки: где человек находится. Разделитель — свой элемент, а не
   `::before` у соседа: он есть в макете подписью, и текст экрана должен
   читаться целиком, а не собираться из содержимого псевдоэлементов. */
.km-crumbs {
	display: flex;
	align-items: center;
	gap: 10px;
	font-size: 13px;
	color: var(--km-text-muted);
}

/* Крошки не переносятся, а последняя обрезается многоточием.
 *
 * С переносом длинное название уезжало на вторую строку, а разделитель
 * оставался висеть в конце первой — «Мои курсы ·» и пустота. Ровно та же
 * висящая точка, что у надстрочника модуля на 375, и лечится тем же:
 * строка обязана остаться одной.
 *
 * Обрезать название здесь не потеря: оно стоит целиком строкой ниже,
 * в шапке, крупным. */
.km-crumbs > * { flex: none; }

/* Ссылка в крошках цвета самих крошек, а не общего для ссылок оранжевого.
   Так во всех трёх макетах, где крошки нарисованы: «Мои курсы» серым,
   текущее место тёмным. Оранжевая ссылка в этой строке — единственное
   яркое пятно над обложкой, и глаз идёт к ней вместо названия курса.
   Наведение возвращает акцент: кликабельность остаётся, но по требованию. */
.km-crumbs a { color: inherit; }
.km-crumbs a:hover { color: var(--km-accent); }

/* Крошки библиотеки клиента — как в её макетах (`library-broadcast-*-v3`,
   `library-series-v1`): «Библиотека клиента» ссылкой акцентом, текущее
   место тёмным. Серия на странице трансляции — ссылка на страницу серии
   (решение 25 сентября 2026), а цветом — текущее место, как `<b>` макета. */
.km-crumbs.km-crumbs--library a { color: var(--km-accent); }
.km-crumbs.km-crumbs--library .km-crumbs__here { font-weight: 400; color: var(--km-text); }
/* Крошки библиотеки переносятся, как в её макетах (`flex-wrap: wrap`):
   в три ступени название трансляции на 375 иначе обрезалось до буквы. */
.km-crumbs.km-crumbs--library { flex-wrap: wrap; row-gap: 2px; }
.km-crumbs.km-crumbs--library .km-crumbs__here { flex: 0 1 auto; overflow: visible; white-space: normal; }

.km-crumbs__here {
	flex: 1 1 auto;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	color: var(--km-text);
}

/* Бейдж поверх обложки — левый верхний угол, отступ 10px */
.km-cover { position: relative; overflow: hidden; border-radius: var(--km-radius-card); }
.km-cover__badge {
  position: absolute;
  top: 10px;
  left: 10px;
  pointer-events: none;
  /*
   * ПОДЛОЖКА ЖИВЁТ ЗДЕСЬ, а не вторым определением рядом с комментарием
   * про полупрозрачность: у имени в CSS два определения не спорят,
   * а складываются, и через сессию их читают как один вид. Признак
   * записан в `CLAUDE.md` пятым случаем общего пространства имён.
   *
   * Перебивает `--peach` и любой другой вид намеренно: поверх картинки
   * решает место, а не вид.
   */
  background: rgba(255, 255, 255, 0.9);
  color: var(--km-warm-text-strong);
  /*
   * МЕЖСТРОЧНЫЙ СВОЙ, а не страницы. Правка Алены 19 сентября 2026:
   * «разве в кабинете лейбл курса такой большой?». Кабинет стоит внутри
   * Elementor (межстрочный 1,65 — плашка 27 px), каталог — в странице темы
   * (27 px — плашка 37). Своего числа у плашки не было, и одна и та же
   * плашка была разной высоты на двух страницах; просвет под ней до
   * названия сжимался с 21 до 11.
   */
  line-height: 1.65;
}
.km-cover__badge--right { left: auto; right: 10px; }

/* Плашка «Курс пройден» на обложке карточки. Белым по плотному зелёному —
 * по тому же доводу, что у ленты на странице курса: обложки бывают любые,
 * и светлая по светлой не читается вовсе. */
.km-cover__badge--done {
	background: var(--km-done);
	color: #fff;
	text-transform: none;
	letter-spacing: 0;
	font-size: 11px;
}

/* Плашки */
.km-note {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  border-radius: var(--km-radius-control);
  padding: 12px 14px;
  font-size: 14px;
  line-height: 1.55;
}
.km-note--warm {
  background: var(--km-warm-bg);
  border: 1px solid var(--km-warm-border);
  color: var(--km-warm-text);
}
.km-note--neutral {
  background: var(--km-page);
  border: 1px solid var(--km-border);
  color: var(--km-text-secondary);
}
.km-note--danger {
  background: #FDF0EC;
  border: 1px solid var(--km-danger-border);
  color: #8E3B27;
}
.km-note__icon { flex: none; margin-top: 1px; }

/* Знак цветом акцента. Плашка красит текст в свой приглушённый цвет,
   и знак, наследуя его, теряется на тёплом фоне — видно только глазами. */
.km-note__icon--accent { color: var(--km-accent); }
/* Текст плашки — **одним блоком**, а не россыпью детей.

   `.km-note` это флекс-строка (значок слева, текст справа), и всякий прямой
   ребёнок становится в ней отдельной колонкой. Плашка со ссылкой внутри
   фразы разъезжалась на три колонки: «…Они в разделе», «Мои работы», «.» —
   ссылка вставала у правого края, точка ещё правее. Разметка при этом
   правильная целиком, и ловится это только глазами.

   Отсюда правило: есть в плашке что-то, кроме голого текста, — текст
   заворачивается в `.km-note__text`. */
.km-note__text { flex: 1; }

/* Плашка с действием справа: знак, текст, кнопка.
   Выравнивание по центру, а не по верху: кнопка выше строки текста,
   и при `flex-start` она свисала бы вниз. Кнопка не сжимается —
   иначе на узком экране надпись переносится по буквам.

   Строка переносится (`flex-wrap`), и это не запас на будущее: надпись
   на кнопке — название группы сообщества, а они длинные. «Практикум
   по Местам Вознесения 2026» даёт кнопку в 302 пикселя, и на 375 она
   вылезала за экран на сотню. Нашёл стенд, мерка «ничего не вылезает
   за ширину». */
.km-note--action { align-items: center; flex-wrap: wrap; }
.km-note--action > .km-btn { flex: none; margin-left: auto; }
@media (max-width: 640px) {
  /* На узком кнопка уходит на свою строку целиком: прижатая вправо,
     она читалась бы как продолжение текста. */
  .km-note--action > .km-btn { width: 100%; margin-left: 0; text-align: center; }
}

/* Карточки */
.km-card {
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-card);
  box-shadow: var(--km-shadow-card);
}
.km-card--warm { border-color: var(--km-warm-border); }

/* Приглушённая карточка: тёплая подложка, тёплая рамка, без тени. Секция
   «Что изменится» в макете `course-page-guest-v2.html`.

   Отдельно от `--warm`, у которого меняется только рамка: там карточка
   остаётся белой и выделяется среди белых, здесь — целая секция другого
   тона, и выделять внутри неё нечего. */
.km-card--quiet {
  background: var(--km-warm-bg);
  border-color: var(--km-warm-border);
  box-shadow: none;
}
.km-card--current { border-color: var(--km-warm-border); }
.km-card__body { padding: 16px 18px 18px; display: flex; flex-direction: column; gap: var(--km-gap-label); }
.km-card__pad { padding: 24px; }

.km-course-card { display: flex; flex-direction: column; overflow: hidden; }

/* «ПРОДОЛЖИТЬ ОБУЧЕНИЕ» — блок вкладки «Обзор» (12.2). Строка: обложка,
   курс с прогрессом и занятием остановки, кнопка. Прогресс — полосой
   и словами в занятиях, процентов нет. Строке уже 380 px — кнопка уходит
   под текст во всю ширину: рядом с обложкой и названием она сжала бы текст
   в столбик. Решает ширина СПИСКА, а не экрана (задача Алены 30.09.2026):
   на планшете блок стоит в узкой колонке кабинета, и по ширине экрана кнопка
   оставалась рядом, зажимая «Пробуждение чакр» в две строки. 380 — замер
   30.09: при нём на текст остаётся 170 px, и название курса и «Пройдено 2
   из 18 занятий» встают в одну строку; уже — в две. */
.km-continue .km-card__body { gap: 8px; }
/* Вид как у соседнего «Ближайшие трансляции» на «Обзоре»: заглавными, 17px, разрядка — слово Алены 15 сентября 2026. */
.km-continue__title { margin: 0; font-size: 17px; font-weight: 700; line-height: 1.35; text-transform: uppercase; letter-spacing: 0.5px; color: var(--km-text); }
.km-continue__list { container: km-continue / inline-size; list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.km-continue__row { display: flex; align-items: center; gap: 14px; padding: 12px 0; border-top: 1px solid var(--km-border-soft); }
.km-continue__row:first-child { border-top: none; }
.km-continue__cover { flex: none; width: 64px; height: 64px; border-radius: 10px; overflow: hidden; background: var(--km-warm-bg); }
.km-continue .km-continue__cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.km-continue__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.km-continue__body > p { margin: 0; }
.km-continue__name { font-size: 15px; font-weight: 600; line-height: 1.35; color: var(--km-text); text-decoration: none; overflow-wrap: anywhere; }
.km-continue__name:hover { color: var(--km-accent); }
.km-continue__lesson { font-size: 13px; line-height: 1.4; color: var(--km-text-secondary); overflow-wrap: anywhere; }
.km-continue__row > .km-btn { flex: none; }

@container km-continue (max-width: 379.98px) {
  .km-continue__row { flex-wrap: wrap; }
  .km-continue__row > .km-btn { flex: 1 0 100%; }
}
/*
 * ОБЛОЖКА ДЕРЖИТ ПРОПОРЦИЮ, А НЕ РАСТЁТ ПОД КАРТИНКУ.
 *
 * Найдено 3 сентября 2026 на боевых данных: у двух карточек из
 * одиннадцати обложка выходила 240 px вместо 202 при ОДИНАКОВОЙ ширине
 * карточек. Развалившимися выглядели колонки, а колонки были ровные —
 * разброс ширин ноль на всех проверенных ширинах окна.
 *
 * Причина: обложка — элемент внутри колонки (`.km-course-card` это flex),
 * и `min-height` у неё `auto`, то есть «не меньше содержимого».
 * Содержимое — картинка, и её собственная высота при ширине колонки
 * больше, чем даёт пропорция, когда картинка выше 16:9. Тогда `auto`
 * побеждает `aspect-ratio`, и обложка растёт.
 *
 * Задевало ровно тех, у кого картинка выше 16:9: «Техники трансформации»
 * 1521×1014 и «Самоценность» 1920×1280 — обе 3:2. Остальные девять
 * от 1,78 и шире, и у них 202.
 *
 * Проверено опытом на живых данных: с `min-height: 0` все одиннадцать
 * дают 202.
 */
.km-course-card__cover { position: relative; aspect-ratio: 16 / 9; min-height: 0; }
/* Сила (0,2,1), а не (0,1,1): внутри Elementor `.elementor img { height: auto }` той же силы подключён позже и выигрывал ничью — картинка брала свою пропорцию вместо рамки (боевой, 19 сентября 2026; `ThemeSiteOverrideTest`). */
.km-course-card .km-course-card__cover img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* НАЗВАНИЕ НА ОБЛОЖКЕ КАРТОЧКИ — КАК В ШАПКЕ КУРСА.
   Правка Алены 6 сентября 2026, вторая редакция по образцу.

   Первая ставила название внизу, одной строкой и с затемнением во всю
   обложку. Образец другой: наверху под бейджем, двумя строками и двумя
   цветами, а текст лежит на светлой части картинки — ровно как в шапке.

   Кегль 22 — подобран под ширину карточки 359. При 26 «Практикум по Местам
   Вознесения» уходил в четыре строки, при 18 название переставало быть
   главным на карточке.

   Цвета — те же токены, что у шапки: второго написания не заводится. */
.km-cover__title {
	position: absolute;
	left: 14px;
	right: 14px;
	/* Под бейджем: он стоит на 10 сверху и высотой 27. Просвет 21 —
	   правка 6 сентября 2026, название просили опустить. */
	top: 58px;
	margin: 0;
	font-family: var(--km-font-display);
	font-size: 26px;
	font-weight: 700;
	line-height: 1.02;
	letter-spacing: -0.01em;
	text-transform: uppercase;
	z-index: 1;
}

/* Две строки: первое слово одной, остальные другой — как в шапке. */
.km-cover__title-lead,
.km-cover__title-rest { display: block; }

/* Длинные названия обрезаются, а не выталкивают карточку. */
.km-cover__title-lead { overflow-wrap: anywhere; }

.km-cover__title-rest {
	/* Просвет между первой частью и второй — отступом, а не межстрочным:
	   межстрочный раздвинул бы и строки ВНУТРИ второй части, а она бывает
	   двухстрочной («по Местам Вознесения»). Правка Алены 6 сентября 2026. */
	margin-top: 4px;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/* Тёмное название на светлой обложке — затемнения нет вовсе, как в шапке. */
.km-cover--ink .km-cover__title-lead { color: var(--km-brand-navy); }
.km-cover--ink .km-cover__title-rest { color: var(--km-brand-teal); }

/* Светлое — на тёмной обложке. Затемнение МЯГКИМ ПЯТНОМ под текстом,
   а не полосой поперёк всей обложки. Решение человека 6 сентября 2026.

   Полоса во всю ширину съедала картинку: в карточке обложка и так теряет
   бока — коробка 16:9 режет широкой по 122–550 пикселей, — и затемнять
   сверху донизу значило отнимать у неё второй раз.

   Пятно радиальное и смещено к левому верху, где стоят бейдж и название;
   к низу и вправо оно сходит на нет, и сюжет остаётся виден. */
.km-cover--lume .km-cover__title-lead,
.km-cover--lume .km-cover__title-rest { color: #fff; }

.km-cover--lume::after {
	content: '';
	position: absolute;
	inset: 0;
	background: radial-gradient(
		125% 78% at 6% 12%,
		rgba(28, 26, 46, 0.74) 0%,
		rgba(28, 26, 46, 0.46) 38%,
		rgba(28, 26, 46, 0.12) 66%,
		rgba(28, 26, 46, 0) 82%
	);
	pointer-events: none;
}

/* Бейдж поверх затемнения и названия. */
.km-cover__badge { z-index: 2; }
.km-course-card__title {
  font-family: var(--km-font-display);
  font-size: 20px;
  font-weight: 700;
  line-height: 1.3;
}

/*
 * КАРТОЧКА ПО СВОЕМУ СОДЕРЖИМОМУ — СЕТКА ЕЁ НЕ РАСТЯГИВАЕТ.
 *
 * Решение человека 3 сентября 2026, и оно ОТМЕНЯЕТ вчерашнее выравнивание
 * по ряду. Низы карточек в ряду не совпадут — это принято.
 *
 * СВОИМ ИМЕНЕМ, а не у `.km-grid-cards` целиком, и это не украшение.
 * Ту же сетку берут ещё двое: каталог и «Варианты участия» гостевой.
 * У вторых прижатие к низу — действующее решение 7.4 (`.km-plan .km-btn
 * { margin-top: auto }`), и оно держится ровно растяжкой: у одной карточки
 * три строки про содержимое, у другой пять. Сними растяжку у всех — и там
 * кнопки встанут лесенкой, то есть починка кабинета сломала бы гостевую.
 *
 * Второе определение `.km-grid-cards` завелось бы и без этого довода:
 * у имени стало бы два смысла, и они смешались бы молча — ровно случай
 * `.km-hint`, записанный в CLAUDE.md.
 *
 * Отсюда снято всё, что под растяжку заводилось:
 *   `align-items: stretch` у сетки — умолчание, поэтому явный `start`;
 *   `flex: 1 1 auto` у тела — растить его больше не нужно и нечем;
 *   `margin-top: auto` у кнопки — свободного места в карточке нет,
 *     `auto` вычислялся бы в ноль, и правило стало бы мёртвым.
 *
 * Разрыв перед кнопкой теперь один и тот же у всех: обычный ритм тела.
 * Ради этого и снимали — растянутая карточка отдавала весь излишек
 * в одно место, и разрыв гулял от карточки к карточке.
 */
.km-grid-cards--own {
  align-items: start;
  /*
   * НЕ БОЛЬШЕ ТРЁХ В РЯДУ. Правка Алены 19 сентября 2026: на `/kabinet-lms`
   * кабинет во всю страницу (1180 px), и «сколько влезет по 272» давало
   * четыре. Дорожка — не уже трети колонки за вычетом двух промежутков
   * `.km-grid-cards` (по 20) и не уже 272: в узкой колонке их меньше,
   * и считается это от КОЛОНКИ, а не от окна — кабинет стоит и во вкладке
   * рядом с меню, и во всю страницу.
   */
}
/* Сила (0,2,0): общее `.km-grid-cards` той же силы стоит в файле ниже
   и выиграло бы ничью порядком — первая редакция так и осталась с четырьмя. */
.km-grid-cards.km-grid-cards--own {
  grid-template-columns: repeat(auto-fill, minmax(max(272px, calc((100% - 40px) / 3)), 1fr));
}

/*
 * ЧИСЛО СТРОК ЗАКРЕПЛЕНО — и это про ДЛИНУ ТЕКСТА, а не про растяжку.
 *
 * ЗАКРЕПЛЕНИЕ ВЫСОТЫ СНЯТО 3 сентября 2026, обрезка осталась. Здесь
 * стояло `height: calc(...)` у обоих — под выравнивание по ряду, — и оно
 * пережило отмену растяжки, хотя заводилось ровно ради неё.
 *
 * ЧТО ОНО ДЕЛАЛО НА ЭКРАНЕ. Коробка на две строки при тексте в одну —
 * это пустая вторая строка, и в зазоре она не видна: зазор честно
 * отвечал 10 при провале в 40. Замер диапазонами по боевым данным,
 * одиннадцать карточек:
 *
 *   пустота в названии   29 у ВОСЬМИ из одиннадцати (текст 23, коробка 52)
 *   пустота в описании   28 у «Диагностики чакр маятником» (17 против 45)
 *   буквы назв.→опис.    14 у трёх двухстрочных, 40 у восьми однострочных
 *   буквы опис.→прогр.   14 у десяти, 37 у «Диагностики»
 *
 * ПОЧЕМУ МЕРИЛОСЬ НЕ ТО. Расстояние между соседними строками — не только
 * их зазор: у элемента с закреплённой высотой пустая строка лежит ВНУТРИ
 * коробки, и `getBoundingClientRect()` про неё молчит. Видно её только
 * диапазоном — `Range.selectNodeContents()`, — и это записанный в проекте
 * класс «текст меряется диапазоном, а не коробкой ячейки».
 *
 * ЧЕМ ЗА ЭТО ПЛАТИМ, названо вслух. Строки ниже названия по ряду теперь
 * разойдутся: у карточки с двухстрочным названием всё под ним стоит
 * на 29 пикселей ниже, чем у соседки с однострочным. Срок на одной линии
 * не встанет. Это принято — растяжка отменена категорически, низы в ряду
 * и так не совпадают, и держать пустоту ради совпадения одной строки
 * дороже, чем совпадение стоит.
 *
 * `line-clamp` остаётся и без высоты: он обрезает длинное. Половина,
 * которая «не поднимает короткое», больше не нужна — поднимать и есть
 * то, ради чего высота снята.
 */
.km-course-card__title,
.km-course-card .km-card__body > .km-text-secondary {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}
/*
 * ДВЕ ГРУППЫ ВНУТРИ КАРТОЧКИ, а не пять равных промежутков.
 *
 * Тело карточки разносит своих детей на `--km-gap-label` — на десять,
 * то есть «подпись и то, к чему она относится». Для соседей внутри группы
 * это верно, а между группами читается неправдой: строка «Доступ до…»
 * стояла к полосе прогресса ближе, чем сама полоса к своей подписи —
 * 11 пикселей между буквами против 12, — и человек читал срок второй
 * подписью к прогрессу. Найдено глазами на боевом 3 сентября 2026.
 *
 * Разница в буквах при равных зазорах коробок берётся из выносного
 * просвета: у текстовой строки он есть, у `<progress>` нет вовсе.
 * Поэтому равные десятки на экране равными не выглядят.
 *
 * Группы такие:
 *   название + описание   — про что курс;
 *   строка прогресса + полоса — где человек в нём;
 *   срок                  — до какого числа он открыт;
 *   кнопка.
 *
 * ГРУППА — НАСТОЯЩИЙ УЗЕЛ, а не отступ на строке, и это не украшение.
 *
 * Первая редакция вешала `margin-top` прямо на строку прогресса и на строку
 * срока. Она провалила общую проверку стендов «у абзацев в колонках нет
 * своих полей» — и провалила по делу: та проверка заведена на браузерном
 * поле у `<p>`, которое молча складывается с `gap`, и отличить наше поле
 * от чужого она не может по устройству. Ослабить её значило бы завести
 * второе место, где решают, «какой отступ правильный».
 *
 * Узлом это выражается честнее: группа на экране есть, значит есть
 * и в разметке. Поле стоит на обёртке, а не на абзаце, и проверка
 * молчит не потому, что её обманули, а потому, что беды нет.
 *
 * Отступ ставится СВЕРХУ у каждой группы, а не снизу: последняя группа
 * не должна отодвигать кнопку — до неё ритм остаётся тесным.
 *
 * Считается разностью двух имён, а не числом: `gap` тела уже дал десять,
 * добрать надо остаток. Правка любого из двух не разъедется с этим местом.
 *
 * Группа из одной строки — не странность: «до когда» сегодня одна строка,
 * а завтра к ней встанет вторая, и правило не придётся переписывать.
 */
.km-course-card__group {
  display: flex;
  flex-direction: column;
  gap: var(--km-gap-label);
  margin-top: calc(var(--km-gap-group) - var(--km-gap-label));
}
.km-course-card--archived .km-course-card__cover { filter: grayscale(1); }

/* Цена на карточке каталога (7.3).
   Крупно и шрифтом заголовков: на карточке это второе, что читают после
   названия. «от» — приставка, и она тише самой суммы: главное здесь число,
   а «от» только объясняет, что бывает и дороже. */
.km-price {
  font-family: var(--km-font-display);
  font-size: 20px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--km-text);
}

.km-price__from {
  font-family: var(--km-font);
  font-size: 14px;
  font-weight: 600;
  color: var(--km-text-muted);
}

/* Число платежей у цены: «от 6 200 ₽ × 3». Раздел 7.14, решение Алены
   4 сентября 2026.

   Тем же кеглем и цветом, что «от»: обе подписи говорят про одно — что
   написанное число не вся сумма. Крупнее — начнёт спорить с самой ценой;
   мельче — перестанет читаться там, где нужна больше всего, то есть
   у рассрочки втрое дешевле полной оплаты. */
.km-price__stages {
  font-family: var(--km-font);
  font-size: 14px;
  font-weight: 600;
  color: var(--km-text-secondary);
  /* Отступ от суммы, а не пробел в строке: неразрывный пробел давал
     четыре пикселя, и «×» читался хвостом значка валюты. Ступень
     `--km-gap-label` — ровно про это отношение: подпись и то, к чему
     она относится. */
  margin-left: var(--km-gap-label);
  white-space: nowrap;
}

/* Подпись ПОД ценой: «14 дней, потом 2 400 ₽». Макет
   `design/free-period-hero-v1.html`, 9 сентября 2026.

   Отдельно от `.km-price__stages`, и это не дубль: тот стоит В СТРОКЕ
   с суммой и говорит про саму сумму («× 3» — что число не вся оплата).
   Эта — ПОД суммой и говорит про то, что будет дальше. Слепи их в одно
   правило, и «14 дней, потом 2 400 ₽» встало бы хвостом к цене, растянув
   строку вдвое; на узком экране она и так делит место с кнопкой.

   Обычный вес и мелкий кегль: подпись не должна спорить с ценой —
   у бесплатного периода цена и так слово, а не число, и жирная подпись
   рядом читалась бы второй ценой. */
.km-price__note {
  display: block;
  margin-top: 3px;
  font-family: var(--km-font);
  font-size: 13px;
  font-weight: 400;
  line-height: 1.35;
  color: var(--km-text-muted);
  white-space: normal;
}

/* Поверх обложки — как у соседей по шапке: общие цвета писаны под белое,
   и подпись на картинке тонет ровно так же, как тонула цена. */
.km-hero--over .km-price__note { color: rgba(255, 255, 255, 0.75); }

/* Вкладки.
 *
 * Поле сверху и снизу — правка вёрстки 4. `km-stack` разносит блоки
 * страницы на шестнадцать, а макет страницы курса разносит на двадцать
 * четыре; восемь — разница, и написана она разницей, а не итогом:
 * поменяется ритм стопки — вкладки поедут вместе со всем остальным,
 * а не останутся единственным блоком со своим числом.
 *
 * Поле, а не зазор у соседа: полоса вкладок стоит на трёх экранах,
 * и в каждом соседи свои.
 *
 * **Разница считается, а не записана числом.** Восьмёрка была верна ровно
 * до того дня, когда у страницы курса появился свой ритм: макет разносит
 * её блоки на 24, а стопка по умолчанию на 16. Стой здесь литерал —
 * вкладки получили бы 40 воздуха вместо 24, и заметил бы это глаз,
 * а не проверка. */
/* РЯД ПЕРЕНОСИТСЯ ЦЕЛЫМИ ПАРАМИ. Правка Алены 15 сентября 2026.
   В колонке кабинета на планшете (768: колонка 460 px) вкладки сжимались:
   названия в две строки, числа отрывались вниз, «Архив 0» уезжал за край
   на 44 px. Ряд переносится между вкладками: строка ломается раньше, чем
   вкладка успела бы сжаться, и пара «название + число» остаётся целой.
   Своего запрета сжиматься у вкладки нет намеренно: он был, и слом «снять
   его» уцелел — перенос ряда делает то же самое, вторая проверка лишняя.
   Подчёркивания у выбранной нет — только цвет, — и вторая строка ничего
   не ломает. На телефоне остаётся прокрутка: узкое правило стоит ниже
   в файле, перебивает перенос и само не даёт вкладкам сжиматься. */
.km-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 28px;
  border-bottom: 1px solid var(--km-border);
  margin: calc(24px - var(--km-stack-gap, var(--km-gap-group))) 0;
}
.km-tab {
  padding: 0 0 12px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--km-text-muted);
  cursor: pointer;
  background: none;
  border: none;
  font-family: inherit;
}
/* ЦВЕТ ТЕКСТА — ТО ЖЕ ЧУЖОЕ ПРАВИЛО, ШЕСТОЕ СВОЙСТВО. Задача 9.27.
 *
 *   button:focus, button:hover { color: var(--bb-primary-button-text-hover) }
 *
 * ЗНАЧЕНИЕ РАЗНОЕ В РАЗНЫХ СРЕДАХ, и это довод сильнее любого одного цвета:
 * локально переменная равна `#ffffff`, на боевом — `#000000` (прочитано
 * живым запросом 25 августа 2026). То есть подпись в фокусе локально белела,
 * а на боевом чернела; и там и там — не своим цветом.
 *
 * *Здесь стояло «На боевом это белый». Неправда: цвет мерился локально,
 * а записан был про боевой — ровно та ошибка, от которой проект защищается
 * правилом «проверено на среде — это две разные записи».*
 *
 * Наш `:hover` чужой цвет перебивал, а `:focus` — нет, и вкладка в фокусе
 * БЕЗ наведения теряла свой цвет целиком.
 *
 * Пряталось это за наведением: мышью нажимают туда, куда смотрят, и `:hover`
 * с `:focus` приходят вместе — тогда выигрывает наш `:hover`. Видно дефект
 * ровно тогда, когда указатель ушёл, а фокус остался: после клика мышь
 * сдвинули, и подпись пропала. Измерено, а не выведено.
 *
 * Стоит ДО `:hover` намеренно: у обоих (0,2,0), и решает порядок. Ниже —
 * состояние наведения, ещё ниже выбранная вкладка. */
.km-tab:focus { color: var(--km-text-muted); }
.km-tab:hover { color: var(--km-text); }

/* ЧУЖОЕ УМОЛЧАНИЕ КНОПКИ ГАСИТСЯ В ТЕХ ЖЕ СОСТОЯНИЯХ, В КАКИХ ОНО ОБЪЯВЛЕНО.
 *
 * Найдено человеком на боевом 19 августа: при наведении на вкладку под ней
 * появлялась белая скруглённая плашка шире самой вкладки. Нашего `:hover`
 * в этом нет ни строчки — он меняет только цвет.
 *
 * Даёт её тема BuddyBoss, и механизм стоит записать целиком, потому что
 * он повторится:
 *
 *   button:hover, button:focus { background-color: #FFFFFF }   (0,1,1)
 *   .km-tab                    { background: none }            (0,1,0)
 *
 * Мы объявили фон в БАЗОВОМ состоянии, тема — в СОСТОЯНИИ НАВЕДЕНИЯ,
 * и её правило специфичнее нашего. Порядок подключения здесь ни при чём:
 * наш файл печатается позже, и это не помогает — сравниваются классы.
 *
 * Радиус приезжает оттуда же и другим путём: `button { border-radius:
 * var(--bb-button-radius) }` — на боевом это **100px**, — а `.km-tab`
 * радиуса не объявлял вовсе. Пока фон прозрачен, скругления не видно;
 * появился фон — появилась капсула.
 *
 * Прецедент в проекте уже есть и записан рядом: `.km-btn--primary` пришлось
 * задать цвет во всех состояниях, потому что тема красит нажатую ссылку.
 * Правило общее: **чужое умолчание гасится в том состоянии, в котором оно
 * объявлено**, а не в базовом.
 *
 * Стендом это НЕ ЛОВИТСЯ САМО СОБОЙ: стенд собран одним файлом, темы в нём
 * нет, и проверка была бы зелена при любом сломе. Поэтому общая мерка
 * подмешивает то самое правило селектором и специфичностью — и меряет
 * `:focus`, который тема объявляет тем же правилом и который можно вызвать
 * из скрипта. */
.km-tab,
.km-tab:hover,
.km-tab:focus,
.km-tab:active {
  background: none;
  border: none;
  border-radius: 0;
}

/* ТЕНЬ ФОКУСА — ЧЕТВЁРТОЕ СВОЙСТВО ТОГО ЖЕ ЧУЖОГО ПРАВИЛА. Задача 9.27.
 *
 * Найдено человеком на боевом: при нажатии мышью вкладка обводится серым.
 * Правило выше гасило у того же механизма ТРИ свойства — фон, рамку
 * и радиус, — и этого оказалось мало: тема объявляет ещё и тень.
 *
 *   button:focus { box-shadow: var(--bb-primary-button-focus-shadow) }  (0,1,1)
 *   .km-tab:focus { box-shadow: none }                                  (0,2,0)
 *
 * Значение переменной прочитано живым запросом к боевому 25 августа 2026
 * и совпало с локальным побайтно:
 *
 *   0 0 1px 2px rgba(0,0,0,.05), inset 0 0 0 2px rgba(0,0,0,.08)
 *
 * Это серый ободок снаружи плюс серый ободок внутри — та самая рамка.
 *
 * ЭТО ТЕНЬ, А НЕ `outline`, и в этом вся тонкость. Сам `outline` тема гасит
 * нулём в тех же состояниях (`button, button:focus, button:hover,
 * button:active { outline: 0 }`), поэтому браузерного кольца нет вовсе:
 * до этой правки человек, идущий табом, не видел **ничего** — ни нашего,
 * ни чужого, ни своего браузерного.
 *
 * ОБЪЯВЛЕНО У ТЕМЫ НА `:focus`, ЗНАЧИТ И ГАСИТСЯ НА `:focus`. Перенеси
 * гашение на `:focus-visible` — и тень вернётся от мыши, а выглядеть
 * написанное будет аккуратнее прежнего. Отдельная проверка держит именно
 * это, а не только наличие строки.
 *
 * Список — все наши `<button>`. Они страдают одинаково, потому что чужое
 * правило смотрит на имя элемента, а не на наш класс; чинить их по одному
 * значит гарантировать следующий такой же разговор. */
.km-tab:focus,
.km-btn:focus,
.km-chip:focus,
.km-act:focus,
.km-link:focus { box-shadow: none; }

/* Признак фокуса С КЛАВИАТУРЫ — свой, потому что чужого не осталось.
 *
 * `:focus-visible`, а не `:focus`: мышью нажимают в то место, куда смотрят,
 * и обводка там лишняя; идущий табом без неё не знает, где он.
 *
 * `.km-link` и `.km-act` сюда НЕ входят намеренно — у них свой
 * `:focus-visible` уже объявлен, и второе определение того же селектора
 * означало бы два места, где живёт один признак. */
.km-tab:focus-visible,
.km-btn:focus-visible,
.km-chip:focus-visible {
  outline: 2px solid var(--km-accent);
  outline-offset: 2px;
}

/* Те же двое, найденные поиском по той же причине: фон объявлен только
   в базовом состоянии, и на наведении тема подкладывает белое. У них это
   заметно меньше — рамка и радиус свои, — но неверно так же. */
.km-btn--text,
.km-btn--text:hover,
.km-btn--text:focus,
.km-btn--text:active { background: transparent; }

.km-btn--quiet,
.km-btn--quiet:hover,
.km-btn--quiet:focus,
.km-btn--quiet:active { background: transparent; }

/* Выбранная вкладка отличается ЦВЕТОМ, и только им. Правка вёрстки 3,
 * решение человека 8 августа 2026.
 *
 * Подчёркивания под активной вкладкой в `course-page-member.html` нет.
 * Расхождение с `design/library.html` при этом настоящее и названо вслух:
 * там, в библиотеке дизайн-системы, у активной вкладки нарисована черта
 * `inset 0 -2px 0`, и жила она отсюда. Решение принято по экрану курса —
 * тому, на который смотрят люди, — и распространено на компонент целиком:
 * вкладки стоят ещё в кабинете и на «Моих работах», и два разных признака
 * «где я сейчас» у одного компонента были бы двумя правдами.
 *
 * Что различие осталось, охраняет общая мерка стенда «выбранная вкладка
 * отличается видом от невыбранной»: она спрашивает отличие, а не способ. */
.km-tab.is-active,
.km-tab.is-active:focus { color: var(--km-accent); }

/* Чипы-фильтры */
.km-chips { display: flex; flex-wrap: wrap; gap: 8px; }/* ЧУЖОЕ УМОЛЧАНИЕ КНОПКИ ГАСИТСЯ В ТЕХ ЖЕ СОСТОЯНИЯХ, В КАКИХ ОНО ОБЪЯВЛЕНО.
 *
 * Найдено стендом «Моих работ» 16 сентября 2026, тем же заходом, что
 * и у `.km-btn--secondary`: общую мерку `themeBleed` впервые позвали
 * на чип.
 *
 * Не хватало двух вещей, и они разного рода.
 *
 * **`line-height` не объявлен вовсе.** Чип задавал кегль, начертание,
 * разрядку, цвет, фон, рамку и поля — а высоту строки нет, и её ставила
 * тема (`1.3`). То есть рост чипа на боевом задавали не мы. У `.km-btn`
 * это решено давно (`line-height: 1`), у `.km-tab` своё; чип остался
 * единственным без.
 *
 * **Тень не объявлена в состояниях.** Сегодня тема ставит `box-shadow`
 * только в `:focus`, и в `:hover` гасить нечего — но требование мерки
 * не «перебей то, что есть», а «объяви там, где чужое правило трогает
 * кнопку». Разница видна на следующем обновлении темы: то, что объявлено,
 * переживёт его молча, а то, что совпало случайно, — нет.
 *
 * Состояния перечислены списком, как у `.km-tab` и `.km-btn--secondary`:
 * вес (0,2,0) против темы (0,1,1), выигрываем объявлением, а не
 * утяжелением селектора. */
.km-chip,
.km-chip:hover,
.km-chip:focus,
.km-chip:active {
  font-size: 13px;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--km-text-secondary);
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-control);
  padding: 8px 17px;
  cursor: pointer;
  box-shadow: none;
}
.km-chip:hover { color: var(--km-accent); border-color: var(--km-warm-border); }
.km-chip.is-active {
  background: var(--km-peach);
  border-color: transparent;
  color: #A8592F;
  padding: 9px 18px;
}
/*
 * ЧИСЛО ОТДЕЛЕНО ОТ СЛОВА. Найдено человеком на боевом 16 сентября 2026:
 * «ЗАДАНИЯ2», «ВСЁ1».
 *
 * Отступ здесь обязателен, а пробела в разметке нет и быть не может:
 * число лежит отдельным `<span>`, чтобы его можно было приглушить.
 * Отступ у `--segment` был, у базового чипа — нет.
 */
.km-chip__count { font-weight: 600; opacity: 0.6; margin-left: 6px; }

/* Выбор программы: два экрана, одна карточка.
   Макет `design/program-picker-v1.html`, принят 23 августа 2026.

   И редактор дерева, и корзина показывали только название — карточка
   не отвечала на вопрос «зачем туда идти». Стало: название, строка чисел,
   статус точкой и стрелка вправо. */
.km-picker__head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}

.km-picker__search { flex: 1 1 240px; min-width: 0; max-width: 340px; }

.km-picker {
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-card);
  overflow: hidden;
}

.km-picker__row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--km-border-soft);
  text-decoration: none;
  color: inherit;
}

.km-picker__row:last-child { border-bottom: none; }
.km-picker__row:hover { background: var(--km-bg); }

/* Пустое приглушено целиком: ни дерева, ни корзины там нет, и звать
   туда взглядом незачем. Пустая корзина вдобавок не ссылка — заходить
   в неё не за чем; пустое дерево ссылкой остаётся, за этим туда и идут. */
.km-picker__row--empty { opacity: 0.62; }
.km-picker__row--empty:hover { background: transparent; }
a.km-picker__row--empty:hover { background: var(--km-bg); }

.km-picker__body { flex: 1; min-width: 0; }

.km-picker__name {
  display: block;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.35;
}

.km-picker__facts {
  display: block;
  margin-top: 4px;
  font-size: 13px;
  color: var(--km-text-secondary);
  line-height: 1.5;
}

.km-picker__muted { color: var(--km-text-muted); }

/* Статус точкой и словом. Прежде здесь стояла серая плашка капсом:
   она кричала громче названия и говорила то же, что говорит цвет. */
.km-picker__state {
  flex: none;
  font-size: 12px;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.km-picker__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex: none;
  background: currentColor;
}

.km-picker__state--live { color: var(--km-ok); }
.km-picker__state--draft { color: var(--km-text-muted); }

/* Стрелка: видно, что строка ведёт дальше. Оранжевое название читалось
   как ссылка, но куда — не говорило. */
.km-picker__go {
  flex: none;
  width: 17px;
  height: 17px;
  color: var(--km-text-muted);
}

@media (max-width: 640px) {
  /* Статус уходит под название: в строку с ним и стрелкой он не влезает,
     а перенесённый — рвёт карточку пополам. */
  .km-picker__row { flex-wrap: wrap; }
  .km-picker__body { flex: 1 1 100%; }
  .km-picker__state { order: 3; }
  .km-picker__go { margin-left: auto; order: 4; }
  .km-picker__search { max-width: none; flex: 1 1 100%; }
}

/* Слияние аккаунтов: пара полей и стрелка между ними.
   Макет `design/merge-v1.html`, принят 23 августа 2026.

   Два поля рядом не говорят, откуда куда, а ошибка здесь необратима.
   Сеткой, а не флексом: средняя колонка обязана быть ровно под стрелку,
   а флекс отдал бы ей долю от свободного места и на узком раздавил бы
   поля ради неё. */
.km-pair {
  display: grid;
  grid-template-columns: 1fr 30px 1fr;
  gap: 10px;
  align-items: start;
}

/* Стрелка стоит на уровне поля, а не подписи над ним: `1lh` подписи плюс
   её отступ. Считается это здесь, а не подбирается на глаз, — иначе
   первая же правка кегля подписи сдвинет стрелку молча. */
.km-pair__arrow {
  align-self: start;
  padding-top: calc(1.4em + var(--km-gap-label));
  color: var(--km-text-muted);
}

.km-pair__arrow svg {
  width: 20px;
  height: 20px;
  display: block;
}

/* Выбранный человек — карточкой: имя, почта, номер и крестик.
   Строкой в поле ввода он не помещался, а без почты и номера двух
   однофамильцев не различить. */
.km-picked {
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-control);
  padding: 9px 12px;
  background: var(--km-bg);
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

.km-picked__body { flex: 1; min-width: 0; }
.km-picked__name { font-weight: 600; }

.km-picked__meta {
  font-size: 12px;
  color: var(--km-text-muted);
  margin-top: 2px;
}

/* Номер аккаунта — моноширинным и мельче почты: его сверяют по знакам,
   а не читают. Своё имя, а не общий `km-num`: тем в системе назван
   крупный показатель с подложкой (см. `km-nums`). */
.km-picked__id {
  font-family: var(--km-mono);
  font-size: 11px;
}

/* Крестик — кнопка, а не значок: он снимает выбор, и нажимать его будут. */
.km-picked__drop {
  flex: none;
  font: inherit;
  font-size: 14px;
  line-height: 1;
  color: var(--km-text-muted);
  background: none;
  border: none;
  padding: 2px;
  cursor: pointer;
}

.km-picked__drop:hover { color: var(--km-accent); }

/* Выбранное В ПОЛЕ формы — одной строкой и ровно высотой поля ввода.

   Поле «выбор из списка с поиском» (`choose.js`, задача Алены 01.10.2026)
   стоит в `.km-row` рядом с обычными полями, а ряд равняет поля по нижнему
   краю: карточка в две строки (68 px против 48,5) поднимала свою подпись
   на 20 px над соседней. Отступы, кегль и межстрочный — те же, что
   у `.km-input`, поэтому и высота та же; не влезшее уходит в многоточие,
   целиком текст — в подсказке. */
.km-picked--field {
  padding: 12px 14px;
  align-items: center;
  font-size: 15px;
  line-height: 1.5;
}

.km-picked--field .km-picked__body {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.km-picked--field .km-picked__name,
.km-picked--field .km-picked__meta {
  display: inline;
}

.km-picked--field .km-picked__meta {
  margin: 0 0 0 8px;
}

/* Сводка — в той же карточке, отделена волоском, а не своей секцией. */
.km-sum {
  border-top: 1px solid var(--km-border-soft);
  padding-top: 14px;
}

.km-sum__title {
  font-size: 11px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--km-text-muted);
  font-weight: 600;
  margin: 0 0 10px;
}

/* Строка сводки: что и сколько. Число справа и не переносится —
   в колонке чисел его и ищут глазами. */
.km-line {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 0;
  border-bottom: 1px solid var(--km-border-soft);
}

.km-line:last-child { border-bottom: none; }

.km-line__glyph {
  width: 16px;
  height: 16px;
  flex: none;
  color: var(--km-text-muted);
}

.km-line__text { flex: 1; min-width: 0; }

.km-line__count {
  font-weight: 600;
  white-space: nowrap;
}

/* «Нечего» — приглушённо и без насыщенности: это не число, и вставать
   в один ряд с числами оно не должно. Признак существует не тогда, когда
   поставлен, а когда отличается. */
.km-line__count--none {
  font-weight: 400;
  color: var(--km-text-muted);
}

/* Пояснение строки сводки — под своей строкой, а не общим абзацем внизу
   (документ сообщества 1.124). Строка переносится, пояснение берёт её
   всю, отступ слева — значок и промежуток, чтобы текст встал под названием. */
.km-line--noted { flex-wrap: wrap; }

.km-line__note {
  flex-basis: 100%;
  padding-left: 26px;
  font-size: 13px;
  line-height: 1.45;
  color: var(--km-text-muted);
}

@media (max-width: 640px) {
  /* Поля встают друг под друга — стрелка вправо показывала бы не туда. */
  .km-pair { grid-template-columns: 1fr; }

  .km-pair__arrow {
    transform: rotate(90deg);
    margin: 0 auto;
    padding-top: 0;
  }
}

/* Журнал действий: запись — строка-фраза, а не набор столбцов.
   Макет `design/audit-log-v1.html`, принят 23 августа 2026.

   Таблицей это было до того дня, и два её столбца — «Что случилось»
   и «Действие» — говорили одно и то же. Строка вместо таблицы читается
   сверху вниз, а не слева направо, и на узком экране не разваливается
   вовсе: колонок в ней две, и вторая — время. */
.km-log {
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-card);
  overflow: hidden;
}

.km-rec {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 13px 18px;
  border-bottom: 1px solid var(--km-border-soft);
}

.km-rec:last-child { border-bottom: none; }
.km-rec:hover { background: var(--km-bg); }

/* ПРИГЛУШЕНО ТО, ПОСЛЕ ЧЕГО У ЛЮДЕЙ НИЧЕГО НЕ ИЗМЕНИЛОСЬ.

   До 23 августа 2026 все семь записей на боевом выглядели одинаково
   тревожно, а пять из них были «делать было нечего»: глаз переставал
   отличать настоящее событие от пустого.

   Признак существует не тогда, когда поставлен, а когда **отличается**,
   — поэтому меняется цвет самой фразы, а не подложка строки: подложку
   съедает `:hover`, и под указателем разница пропадала бы. */
.km-rec--none .km-rec__text { color: var(--km-text-muted); }

.km-rec__body { flex: 1; min-width: 0; }

/* Фраза — она же кнопка разбора: по ней открывают «было и стало».
   Кнопкой, а не ссылкой: никуда не ведёт. Видом — обычный текст,
   потому что читают её как текст, а не как действие. */
.km-rec__text {
  font: inherit;
  color: var(--km-text);
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  text-align: left;
  line-height: 1.45;
  cursor: pointer;
}

.km-rec__text:hover { color: var(--km-accent); }

.km-rec__meta {
  margin-top: 4px;
  font-size: 12px;
  color: var(--km-text-muted);
  display: flex;
  gap: 7px;
  flex-wrap: wrap;
  align-items: center;
}

/* Время — второй колонкой, и она не сжимается: «21 авг, 14:12» на двух
   строках читается как две даты. */
.km-rec__when {
  flex: none;
  font-size: 12px;
  color: var(--km-text-muted);
  white-space: nowrap;
  text-align: right;
  padding-top: 1px;
}

/* Давность рядом с моментом — и ещё тише его: она подсказка, а не ответ. */
.km-rec__ago { display: block; opacity: 0.75; }

/* Над чем: вход в отбор по этому объекту. Кнопка, а не ссылка — адреса
   у отбора нет, он живёт в состоянии скрипта. */
.km-rec__object {
  font: inherit;
  font-size: 12px;
  color: var(--km-accent);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}

.km-rec__object:hover { text-decoration: underline; }

.km-sep { color: var(--km-border); }

/* Прогресс */
.km-progress { display: flex; flex-direction: column; gap: 7px; }

/* Полоса и число В СТРОКУ — для ячейки таблицы.

   Столбиком (как на карточке курса) прогресс занимает три высоты строки
   и растит весь список. В строке он занимает одну и читается тем же
   взглядом, что и соседние столбцы. */
.km-progress--row {
  flex-direction: row;
  align-items: center;
  gap: 9px;
  min-width: 130px;
}

.km-progress--row .km-progress__bar { flex: 1; min-width: 60px; }

/* Число — цифрами одинаковой ширины: в столбце из двадцати пяти строк
   разъезжающиеся «1 / 15» и «11 / 15» читаются хуже, чем выровненные. */
.km-progress__num {
  font-size: 13px;
  color: var(--km-text-secondary);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* У не начавшего вместо числа слово, и приглушённое: «0 / 15» глаз
   читает как число и сравнивает с соседями, а сказать надо «не приступал
   вовсе» — это другой человек и письмо ему пишут другое. */
.km-progress__zero {
  font-size: 13px;
  color: var(--km-text-muted);
  white-space: nowrap;
}
.km-progress__head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.km-progress__label { font-size: 15px; font-weight: 600; }
.km-progress__percent { font-size: 14px; font-weight: 700; color: var(--km-accent); }
.km-progress__track {
  height: 5px;
  border-radius: 3px;
  background: var(--km-track);
  overflow: hidden;
}
.km-progress__fill { height: 100%; border-radius: 3px; background: var(--km-accent); }
.km-progress__meta { font-size: 12px; color: var(--km-text-muted); }
.km-progress--thin .km-progress__track { height: 4px; border-radius: 2px; }
.km-progress--soft .km-progress__fill { background: var(--km-accent-light); }

/* Полоса прогресса элементом `<progress>`, а не двумя `div` с шириной.
   ------------------------------------------------------------------

   Ширина заливки — единственная величина на весь фронт, которая зависит
   от данных, и посчитать её негде, кроме как в браузере. Через `style`
   это запрещено правилом 13, и правильно: правило заведено, чтобы
   оформление не переезжало из макетов в шаблоны. Но `value` и `max`
   у `<progress>` — **данные, а не оформление**: те же восемь и двадцать,
   что написаны рядом словами. Оформление при этом целиком здесь,
   как и требует правило.

   Заодно полоса получает голос: экранный диктор читает её как «8 из 20»,
   а `div` с шириной сорок процентов не читает никто.

   Псевдоэлементы у `progress` разные в движках, поэтому правил три:
   сама полоса — подложка, `::-webkit-progress-bar` — она же в WebKit,
   а заливку красят `::-webkit-progress-value` и `::-moz-progress-bar`. */
.km-progress__bar {
  appearance: none;
  -webkit-appearance: none;
  display: block;
  width: 100%;
  min-width: 60px;
  height: 5px;
  border: none;
  border-radius: 3px;
  background: var(--km-track);
  overflow: hidden;
}

.km-progress__bar::-webkit-progress-bar { background: var(--km-track); border-radius: 3px; }
.km-progress__bar::-webkit-progress-value { background: var(--km-accent); border-radius: 3px; }
.km-progress__bar::-moz-progress-bar { background: var(--km-accent); border-radius: 3px; }

/* ПОЛОСА ПРОЙДЕННОГО КУРСА — зелёная. Решение Алены 13 сентября 2026.
 *
 * Красится и заливка, и доля рядом: это одно число, показанное дважды,
 * и позелени мы только полосу, на экране получилась бы зелёная полоса
 * с оранжевым «100%» — то есть два ответа про одно.
 *
 * Псевдоэлементы у `progress` разные в движках, поэтому правил три, как
 * и у основной полосы выше. */
.km-progress--done .km-progress__percent { color: var(--km-done); }
.km-progress--done .km-progress__bar::-webkit-progress-value { background: var(--km-done); }
.km-progress--done .km-progress__bar::-moz-progress-bar { background: var(--km-done); }

/* ТА ЖЕ ЗЕЛЁНАЯ ПОЛОСА, НО КЛАССОМ НА САМОЙ ПОЛОСЕ.
 *
 * Нужна карточке кабинета: доли рядом там нет, красить нечего, кроме полосы,
 * и оборачивать её в контейнер ради одного класса незачем. Тот же порядок,
 * что у `--soft` ниже: у показателя есть вид на уровне группы и на уровне
 * самой полосы.
 *
 * Написано это здесь, а не сложено из первого правила, потому что селектор
 * там **потомок**: `.km-progress--done .km-progress__bar` не совпадает
 * с полосой, которая носит класс сама. Первая редакция карточки именно
 * на это и налетела — класс стоял, полоса оставалась оранжевой, а проверка
 * спрашивала наличие класса и была зелена. */
.km-progress__bar--done::-webkit-progress-value { background: var(--km-done); }
.km-progress__bar--done::-moz-progress-bar { background: var(--km-done); }

/* Полоса второстепенного показателя — тусклее основной. */
.km-progress__bar--soft::-webkit-progress-value { background: var(--km-accent-light); }
.km-progress__bar--soft::-moz-progress-bar { background: var(--km-accent-light); }

/* Колонка чтения: 980px.
 *
 * **Расхождение с макетом, и это решение человека 8 августа 2026, а не
 * недосмотр.** `design/lesson-player.html` рисует 780; измерение на боевом
 * показало, что мы ровно на этом числе и стоим и что тема ничего не режет
 * (`site`, `entry-content`, `site-main` — все во всю ширину). Дефекта
 * не было — узко оказалось само макетное число: на ноутбуке 780 посреди
 * 1440 читается колодцем.
 *
 * Записано здесь потому же, почему записаны исключения правил 6 и 9:
 * молча разошедшееся с макетом число через этап найдут как «отступление
 * от эталона» и вернут обратно.
 *
 * Довод самого ограничения не отменяется: строка во всю ширину монитора
 * не дочитывается до конца, а видео 16:9 на такой ширине занимает экран
 * целиком. Ширину задаёт колонка, а не сами блоки — иначе каждый следующий
 * блок пришлось бы ограничивать заново и по-своему. */
.km-column { width: 100%; max-width: 980px; margin: 0 auto; }

/* ---------------------------------------------------------------------------
   Плеер занятия (5.5)
   ---------------------------------------------------------------------------

   Две колонки по макету `design/lesson-player.html`: слева навигация
   по курсу, справа чтение. Левая липкая и со своей прокруткой — человек
   ходит по занятиям чаще, чем прокручивает страницу до конца, и терять
   навигацию при прокрутке значит заставлять его возвращаться наверх.
   --------------------------------------------------------------------------- */
.km-player {
	display: grid;
	grid-template-columns: 320px minmax(0, 1fr);
	align-items: start;
	min-height: 100vh;
}

.km-player__side {
	position: sticky;
	/* Отступ и высота считаются от чужой обвязки, а не от нуля.
	   При `top: 0` колонка прилипает к краю окна — то есть под липкую шапку
	   темы, — и первым уезжает её верх: «К карте курса», название курса
	   и полоса прогресса. Это ровно то, что в макете видно всегда. */
	top: var(--km-chrome-top);
	/* Высота, а не «не выше»: у короткого курса колонка иначе обрывается
	   белым прямоугольником посреди страницы, и граница читается как конец
	   содержимого. В макете она во весь экран — за вычетом того, что
	   рисует тема. */
	height: calc(100vh - var(--km-chrome-top));
	overflow-y: auto;
	background: var(--km-surface);
	border-right: 1px solid var(--km-border);
	padding: 22px 18px 32px;
	display: flex;
	flex-direction: column;
	gap: 10px;
}

.km-player__main { min-width: 0; padding: 32px 28px 96px; }

/*
 * НАША СТРАНИЦА ОТ КРАЯ ОКНА, А НЕ НА 10 PX ЛЕВЕЕ. Задача Алены 17.10.2026: у подсветки строки в колонке плеера слева
 * около 10 px, справа 18. Сдвигает пара чужих правил: сетка `.bb-grid` (theme.css) держит поля −10 px в расчёте на
 * подбивку ячейки 10 px, а на странице Elementor «на всю ширину» эту подбивку снимает elementor.css
 * (`.elementor-page.page-template-page-fullwidth-content #primary`). Наша страница начиналась на −10, и `.site`
 * с `overflow-x: clip` прятал ушедшее.
 *
 * Правило одно на все наши страницы и названо по условию, а не по странице: тело с теми же двумя классами, что у
 * правила Elementor, и наш корень `[data-lms-page]` внутри. Замер на боевом 17.10 (1280, 900, 375): условие держит
 * только плеер; у курса, «Моего профиля», «Сообщества», библиотеки и трансляции шаблон не Elementor, подбивка
 * `#primary` 10 гасит −10 и сдвига нет — их правило не задевает. На всех ширинах (слово Алены 17.10: «ограничение
 * „шире 1100“ снимаю»). Тему и Elementor не правим; сила (0,5,0) против темы (0,1,0) — держится селектором.
 * Мерка — `playerSide()` в общей обвязке стендов, стенд плеера повторяет цепочку темы и Elementor.
 */
.elementor-page.page-template-page-fullwidth-content .bb-grid.site-content-grid:has([data-lms-page]) { margin-left: 0; margin-right: 0; }

/* Створка колонки. На широком экране её нет: колонка открыта всегда,
   и кнопка «свернуть навигацию» там означала бы только способ её потерять. */
.km-player__toggle { display: none; }

/* «К карте курса»: путь назад, а не действие. Поэтому ссылкой, а не кнопкой. */
.km-back {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	font-size: 13px;
	color: var(--km-text-secondary);
	text-decoration: none;
}

.km-back:hover { color: var(--km-accent); }

/* Компактный вид дерева: тот же компонент, что на карте курса, но плотнее.
   Разделительных черт между узлами в колонке нет — в списке из сорока строк
   они превращают навигацию в решётку. */
/* СТРОКА В КОЛОНКЕ НЕ ПЕРЕНОСИТСЯ, и знак состояния места не теряет.
 *
 * Стояло `flex-wrap: wrap`, и на 283 пикселя галочка уезжала под название
 * отдельной строкой — у «1. Компоненты духовного роста» она висела внизу,
 * а у коротких названий стояла в строке. Человек прочитал это поломкой,
 * и был прав: строка выглядела двумя.
 *
 * Записано это было наблюдением «не задача» и прожило так до 19 августа.
 * Перенос убран целиком: место отдаёт название, а не знак. Название
 * сжимается (`min-width: 0` у него уже есть) и переносится ВНУТРИ своей
 * колонки — знак при этом остаётся на первой строке и стоит по её верху
 * (слово Алены 14.10.2026; до того — по центру всей строки).
 *
 * Метки потока и «по желанию» в колонке не показываются (правило ниже),
 * так что переносить, кроме названия, тут нечего. */
.km-tree--compact .km-node { padding: 8px 6px; gap: 9px; border-bottom: none; flex-wrap: nowrap; }

/* Лестница уровней в колонке своя, и она мельче. Кегль здесь стоял и раньше,
   а вес и размеры кружка брались у базового класса — то есть правка 1 подняла
   бы их и тут, в колонке шириной 283 пикселя, где макет плеера рисует знаки
   16 и 13 пикселей. Названо явно, чтобы правка карты не переделывала плеер
   молча. */
.km-tree--compact .km-node__title { font-size: 14px; font-weight: 400; }
.km-tree--compact .km-tree__topics .km-node__title { font-size: 13px; }
.km-tree--compact .km-node { --km-node-line: calc(14px * 1.35); }
.km-tree--compact .km-tree__topics .km-node { --km-node-line: calc(13px * 1.35); }

/* Счёт над деревом — счёт, доля и полоса, отделённые чертой от списка.
   Нарисован он в одном месте, `design/lesson-player.html`, и виден там же:
   в колонке плеера.

   **На странице курса блока нет вовсе**, и это решение, а не пропажа.
   Макет страницы курса над модулями не рисует ни заголовка, ни счёта —
   счёт стоит выше, в карточке прогресса. Показанный здесь второй раз, он
   отвечал на один вопрос двумя дорогами: карточку считает `course.js`,
   эту строку — `course-map.js`, и разойтись они могли только молча. */
.km-mapcount { display: none; flex-direction: column; gap: 7px; }
.km-mapcount__percent { font-size: 13px; font-weight: 700; color: var(--km-accent); }
.km-mapcount__bar { display: none; }

/* Плотный вид узнаётся по СОСЕДУ, а не по второму классу на себе.
 *
 * Режим объявлен один раз — `km-tree--compact` на самом дереве, — и ставит
 * его тот, кто подключает карту. Счёт стоит строкой выше и класса не несёт;
 * дописать ему второй значило бы объявить один и тот же режим дважды,
 * и однажды поставили бы только один. */
.km-mapcount:has( + .km-tree--compact ) {
  display: flex;
  padding: 0 6px 16px;
  border-bottom: 1px solid var(--km-border-soft);
}
.km-mapcount:has( + .km-tree--compact ) .km-mapcount__bar { display: block; height: 5px; }
/* Счёт слева, доля справа — как в макете. Общее правило прижимает счёт
   вправо (`.km-row > .km-meta { margin-left: auto }`); здесь счёт первый
   в строке, и прижимать надо долю. */
.km-mapcount:has( + .km-tree--compact ) .km-meta { font-size: 13px; color: var(--km-text-secondary); margin-left: 0; }
.km-mapcount:has( + .km-tree--compact ) .km-mapcount__percent { margin-left: auto; }

/* НАЗВАНИЕ МОДУЛЯ — СТРОКА НА СЕРОМ МЕЖДУ КАРТОЧКАМИ, 15 полужирным.
 *
 * Принятый вид 19 августа 2026, `design/course-tree-v3.html`. Обычным
 * текстом: ни верхнего регистра, ни разрядки, ни бледности.
 *
 * Это ОТМЕНЯЕТ надстрочник из `design/lesson-player.html` — «МОДУЛЬ 2 ·
 * ТЕЛО КАК ОПОРА» бледным в одиннадцать пикселей. Довод человека записан
 * дословно: «забракован был не модуль, а способ его подачи — бледный
 * надстрочник с разрядкой». Отменяет и промежуточную редакцию 1.0.0,
 * где заголовок стоял 13 полужирным на белом внутри одной общей карточки.
 *
 * Модуль В ЛЕСТНИЦУ КЕГЛЯ НЕ ВХОДИТ: он разделитель, а не старший
 * уровень. Совпадение с занятием по кеглю (15) поэтому не оплошность —
 * различают их фон под строкой и место: заголовок стоит на сером
 * между карточками, занятие — на белом внутри своей.
 *
 * Тёплым у того модуля, где человек стоит: без отличия колонка не
 * отвечает на вопрос «где я», ради которого она и стоит. */
.km-tree__heading {
  font-size: 15px;
  font-weight: 600;
  line-height: 1.35;
  color: var(--km-text);
  padding: 16px 4px 8px;
}
.km-tree__heading:first-child { padding-top: 0; }
.km-tree__heading--current { color: var(--km-warm-text-strong); }

/* КАРТОЧЕК В КОЛОНКЕ ПЛЕЕРА НЕТ, и это не забытый сброс.
 *
 * Колонка сама лежит на белом (`.km-player__side` — `--km-surface`),
 * и белая карточка на белом фоне не рисует ничего, кроме рамки: сорок
 * рамок подряд на 283 пикселя превращают навигацию в решётку. Серого
 * фона, между которым карточки и разделяются, там нет вовсе.
 *
 * Сбрасывается ПОЛНОСТЬЮ, включая поля: карточка несёт их для страницы
 * курса, а в колонке отступы задаёт сама колонка. */
.km-tree--compact .km-tree__card {
  background: none;
  border: none;
  border-radius: 0;
  box-shadow: none;
  overflow: visible;
  margin-bottom: 0;
}
.km-tree--compact .km-tree__card > .km-node,
.km-tree--compact .km-tree__fold-head > .km-node { padding: 8px 6px; border-radius: 10px; }

/* Строка узла в колонке: своя подложка у текущего, скруглённая, как в макете.
   Черты между строками нет — сорок строк с ними превращаются в решётку. */
.km-tree--compact .km-node { border-radius: 10px; }

/* В КОЛОНКЕ ПОДЛОЖКУ НОСИТ ТОЛЬКО ОТКРЫТЫЙ УЗЕЛ. Решение человека
 * 19 августа 2026, вечер.
 *
 * Найдено им на боевом: тёплый фон несли ДВЕ строки — занятие «Протокол
 * сеанса» и топик «1. Введение» под ним. Причина не в том, что занятие
 * получило подложку как контейнер: оно несло её ПО СОБСТВЕННОМУ СОСТОЯНИЮ
 * `started`, а топик — как открытый в плеере. Два разных признака,
 * нарисованных одинаково.
 *
 * Решение записано дословно: **в плеере место человека — это открытый
 * узел.** Открыл топик — он и есть «здесь я». Отдельного места остановки
 * в колонке нет: оно нужно там, где человек ещё ничего не открыл, то есть
 * на странице курса. Экраны при этом не расходятся видом — светится ровно
 * одна строка и там, и там, — расходится только источник.
 *
 * Второго признака не заводится: у места в колонке нет НИКАКОГО. Поэтому
 * гасится не только заливка, но и тёплый шеврон с полужирным названием —
 * иначе строка осталась бы «светящейся» наполовину, и различие, от которого
 * уходили, вернулось бы слабее и незаметнее.
 *
 * На странице курса всё остаётся как было: открытого узла там нет, и
 * подложку носит место.
 *
 * `--active` объявлен ЯВНО и после: у одной строки могут стоять оба класса
 * сразу — человек открыл то самое занятие, где остановился, — и без этой
 * строки погашенное состояние утащило бы за собой и открытый узел. */
.km-tree--compact .km-node--current { background: none; }
.km-tree--compact .km-node--current .km-node__title { font-weight: 400; }
.km-tree--compact .km-node--current .km-tree__chevron { color: var(--km-text-muted); }
.km-tree--compact .km-node--active { background: var(--km-warm-bg); }
.km-tree--compact .km-node--active .km-node__title { font-weight: 700; }
/*
 * Открытая тема, на которой человек остановился, — и «текущая», и подсвеченная. Общее правило «текущей» темы
 * выводит подложку на 10 px за колонку текста (`.km-tree__topics .km-node--current`), и в компактном дереве плеера
 * она уходила в правое поле колонки: до разделителя 8 px вместо 18 на 1280, на 10 px глубже строки занятия и на
 * узком (задача Алены 17.10.2026). Справа подложка кончается там же, где у строки занятия; слева — как была.
 * На всех ширинах.
 */
.km-tree--compact .km-tree__topics .km-node--current { margin-right: 0; padding-right: 6px; }

/* В колонке 283 пикселя метки в строку с названием не встают: «Эфир 14 марта»
   ломался вокруг «Весна 2026» и читался как три разных строки. Название
   занимает строку целиком, метки встают под ним с отступом под кружок. */
.km-tree--compact .km-node__link { flex: 1 1 auto; min-width: 0; }
/* Метки потока и «по желанию» в колонке не показываются.
   В макете плеера их нет вовсе, а занимают они целую строку под узлом —
   на сорока строках это сорок лишних. Сведения не теряются: обе метки
   стоят у того же узла на странице курса, где строка вдвое шире. */
.km-tree--compact .km-node__tags { display: none; }
/* В КОЛОНКЕ ПРАВЫЙ СТОЛБЕЦ НЕСЁТ ТОЛЬКО ЗНАКИ, без текста.
 *
 * Решение человека 19 августа 2026: значение у столбца одно и то же
 * на обоих экранах, а способ зависит от ширины — знак в колонке, знак
 * или слово на странице курса.
 *
 * Довод виден на боевом: колонка 283 пикселя, и «вы здесь» рядом
 * с названием не помещается — название ломалось на две строки, а галочка
 * уезжала под него и читалась отдельным элементом списка.
 *
 * Текущий узел в колонке различается подложкой, цветом знака
 * и полужирным названием — три признака, и текст четвёртым не нужен.
 * Место остановки и дата эфира остаются на странице курса, где ширина
 * позволяет.
 *
 * ЗАМОК ЗДЕСЬ НЕ ДОБАВЛЯЕТСЯ: он стоит СЛЕВА, на месте знака содержимого,
 * решением от 19 августа — сервер за замком содержимого не отдаёт вовсе.
 * Второй замок справа повторял бы его в той же строке. */
.km-tree--compact .km-node__state--here,
.km-tree--compact .km-node__state--at,
.km-tree--compact .km-node__state--when { display: none; }

/* СЧЁТ ЧАСТЕЙ ОСТАЁТСЯ И В КОЛОНКЕ ПЛЕЕРА — решение человека 8 сентября
 * 2026, и записано оно правилом, а не оставлено умолчанием.
 *
 * Соседи выше спрятаны по решению 19 августа: «правый столбец колонки
 * несёт только знаки, без текста» — «вы здесь» рядом с названием ломало
 * строку на 283 пикселях. Довод верен и здесь по форме, и всё же счёт
 * остаётся: человек просил, чтобы отметки читались НА ОБЕИХ страницах
 * одинаково, а спрятанный счёт — это ровно то расхождение, из-за которого
 * правка и делается.
 *
 * Место отдаёт название, а не счёт: он короче любого из спрятанных
 * («4 из 13» против «в среду, 19:00») и стоит у строки занятия, а не
 * у части, где имена длиннее всего.
 *
 * Написано отдельным правилом, чтобы следующий не дописал `--parts`
 * в список выше по сходству имени. */
.km-tree--compact .km-node__state--parts { display: flex; font-size: 11px; }
/* Причина закрытия в колонку плеера не помещается и не нужна: 283 пикселя
   заняты названием, а «почему закрыто» человек читает на карте курса.
   Имя сменилось с `km-node__reason` 27 августа 2026 вместе с местом:
   причина переехала из абзаца под строкой в правый столбец самой строки. */
.km-tree--compact .km-node__why { display: none; }

/* Узел, открытый прямо сейчас. Отдельно от состояния `current` из карты:
   то — «здесь человек остановился», это — «на это он смотрит». Совпадают
   они часто, но не всегда: вернувшись к пройденному занятию, человек
   смотрит на одно, а остановился на другом. */
.km-node--active { background: var(--km-warm-bg); border-radius: var(--km-radius-control); }
.km-node--active .km-node__title { font-weight: 700; color: var(--km-text); }

/* Узел в дереве кликабелен: вся строка, а не только название. Знак — по верху первой строки названия (как у `.km-node`). */
.km-node__link {
	display: flex;
	align-items: flex-start;
	gap: 9px;
	flex: 1;
	min-width: 0;
	color: inherit;
	text-decoration: none;
}

/* В ШАПКЕ СКЛАДКИ ССЫЛКА НЕ РАСТЯГИВАЕТСЯ, и это про нажатие,
   а не про вид.
 *
 * Строка занятия с топиками лежит в `<summary>`. Растянутая ссылка
 * занимает всё свободное место, и нажатие по «пустому» месту строки
 * уходит по адресу — складке остаётся полоска правого столбца.
 * Дефект жил с 1.0.0 и нашёлся руками на боевом: занятие не
 * раскрывалось вовсе.
 *
 * Теперь ссылка шириной по названию, а свободное место принадлежит
 * складке. Шеврон стоит вне ссылки — его приставляет `row()`. */
.km-tree__fold-head .km-node__link {
	flex: 0 1 auto;
	margin-right: auto;
}

.km-divider { height: 1px; background: var(--km-border); }

/* Полоса «Назад · Отметить · Дальше».
   Отметка посередине и неяркая: она доступна всегда (8.3), но не должна
   выглядеть основным способом пройти занятие. */
.km-lesson-nav { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.km-lesson-nav__middle { flex: 1; display: flex; justify-content: center; }

/* Карточка «Дальше»: что ждёт за кнопкой. */

/* ПОДСКАЗКА ПРО ОТМЕТКУ. Решение человека 19 августа 2026.
 *
 * Заменяет окно `km-ask` на странице занятия: то переспрашивало решение,
 * принятое секунду назад, и главной в нём стояла кнопка, которую человек
 * не выбирал.
 *
 * Подсказка **не спрашивает и не удерживает**. Отсюда и вид: она стоит
 * в потоке под кнопками, а не всплывает поверх. Всплывающее перекрывает
 * то, на что человек смотрел, и требует его убрать — то есть снова
 * требует действия.
 *
 * Тёплая, а не тревожная, — по тому же доводу, что у мягкого вопроса
 * ниже: это не ошибка и не запрет, человеку сообщают, что здесь осталось
 * несделанное. Рамки нет: рамка читается как отдельный блок, требующий
 * внимания, а подсказка живёт полторы секунды и уходит вместе со
 * страницей.
 *
 * Галка мельче текста подсказки: она про будущее, а не про сейчас. */
/* ИМЯ СМЕНЕНО 23 АВГУСТА 2026: было `.km-hint`, и оно уже было занято.

   Тем же словом ниже (и на девяти административных экранах) называется
   мелкая серая подпись под полем ввода. Два смысла на одно имя не спорили
   за победу — они **складывались**: подпись получала тёплую подложку
   и отступы отсюда, а кегль и цвет оттуда. Выходила помесь, которой никто
   не задумывал: объяснение под полем в плашке размером с само поле.

   Нашлось глазами на слиянии аккаунтов; тестами не ловится по устройству —
   каждое из двух правил само по себе верно. Ровно та болезнь, что записана
   про общее пространство имён: префикс `km` защищает от чужих и не защищает
   от нас самих во времени. */
.km-nudge {
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: var(--km-warm-bg);
  border-radius: var(--km-radius-control);
  padding: 14px 18px;
}
.km-nudge__text { margin: 0; font-size: 15px; line-height: 1.5; color: var(--km-warm-text); }
.km-nudge__mute { font-size: 13px; color: var(--km-text-secondary); }

/* Мягкий вопрос (8.4).
   Тёплый, а не тревожный: это не ошибка и не запрет — человеку сообщают,
   что здесь осталось несделанное, и обе двери оставляют открытыми. */
.km-ask {
	background: var(--km-warm-bg);
	border: 1px solid var(--km-warm-border);
	border-radius: var(--km-radius-card);
	padding: 22px 24px;
	display: flex;
	flex-direction: column;
	gap: 14px;
}

.km-ask__title { font-size: 17px; font-weight: 700; }

/* СПИСОК ЦЕЛЕЙ ПЕРЕМЕЩЕНИЯ. Задача 21 августа 2026.

   Главная жалоба человека: на 119 узлах перетащить топик через сто строк
   невозможно. Список — то же дерево отступами, и отступ здесь единственное,
   чем видно вложенность: кегль одинаков, потому что это выбор, а не чтение.

   Своя высота с прокруткой: сто целей в окне подтверждения выдавили бы
   кнопки за экран, и человек не нашёл бы, чем согласиться. */
.km-move {
  max-height: 46vh;
  overflow-y: auto;
  border: 1px solid var(--km-border);
  border-radius: 10px;
  background: var(--km-surface);
}

.km-move__row {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 12px;
  border: none;
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.km-move__row:hover { background: var(--km-bg); }
.km-move__row[aria-pressed="true"] { background: var(--km-warm-bg); font-weight: 600; }

/* Отступ уровня — переменной, а не тремя правилами: уровней у списка целей
   столько же, сколько у дерева, и заводить класс на каждый значило бы
   переписать лестницу второй раз. */
.km-move__row--1 { padding-left: 32px; }
.km-move__row--2 { padding-left: 56px; }

/* Цена выбора, если она есть: «четвёртый уровень». Приглушённо и справа —
   это не запрет, а предупреждение. */
.km-move__cost { margin-left: auto; font-size: 12px; color: var(--km-text-muted); white-space: nowrap; }
.km-ask__text { font-size: 15px; line-height: 1.6; color: var(--km-warm-text); }
.km-ask__actions { display: flex; gap: 10px; flex-wrap: wrap; }

/* Нехватка словами: «У эфира нет ссылки на трансляцию».
   Не бейдж: бейджи набраны заглавными и коротки по устройству, а здесь
   фраза, которую человек читает целиком. Не `km-meta`: она серая и теряется
   среди прочих подписей строки, а эта говорит, что чего-то не хватает.
   Про любой экран — то же понадобится карточке потока с её чеклистом. */
/* Поля свои сняты: в колонке промежутки задаёт стопка, и абзац со своим
   полем ломает ритм. Найдено стендом адреса материала 4 сентября 2026 —
   общая мерка «у абзацев в колонках нет своих полей» держит это с 3.6,
   а `km-warn` и `km-caution` в колонке до того дня не стояли. */
.km-warn { font-size: 13px; line-height: 1.4; color: var(--km-danger); margin: 0; }

/*
 * НЕЗАКРЫТОЕ, КОТОРОЕ НЕ МЕШАЕТ. Заведено 4 сентября 2026 под чеклист
 * готовности потока.
 *
 * Три пункта из пяти стали предупреждениями: ссылки эфиров, группа
 * и куратор доделываются по ходу и продажу не запрещают. Но с экрана
 * они не уходят — спрятанное предупреждение вернуло бы прежнюю беду
 * целиком.
 *
 * Значит на экране их надо ОТЛИЧАТЬ от запрещающих, а не только
 * от пройденных. Красным, как запрет, — человек решит, что застрял;
 * серым, как пройденное, — не заметит вовсе. Жёлтый здесь тот же,
 * что у «скоро понадобится» в таблице зачислений: между зелёным
 * «ничего не надо» и красным «надо сейчас».
 *
 * Кегль и межстрочный те же, что у `km-warn`: строки стоят в одном
 * списке друг под другом, и разниться им можно только цветом.
 */
.km-caution { font-size: 13px; line-height: 1.4; color: var(--km-warn); margin: 0; }

/* Строка кнопок. Про любой экран, а не про эфир: такая же нужна была
   мягкому вопросу, и `km-ask__actions` осталась там только потому, что
   у неё своя обвязка. Переносить его сюда — отдельная правка, а плодить
   третью копию под каждый новый блок незачем. */
.km-actions { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }

/* Блоки материала: типографика достаётся от темы, здесь только ритм.
   Своих правил на заголовки и абзацы нет намеренно — материал верстают
   штатным редактором, и перебивать его оформление плагином значит
   отобрать у редактора то, ради чего он и нужен.

   РИТМ ЗАДАЁТСЯ `gap`, А НЕ `margin-top`. Правка 27 августа 2026, и она
   не про вкус — про то, что полями этот ритм не держался.

   Было `.km-content > * + * { margin-top: 28px }`, и оно проигрывало
   сбросу полей у типографики: там `.km-note` стоит в общем списке
   с `margin: 0`, специфичность у обоих правил ОДИНАКОВАЯ (один класс),
   а сброс лежит ниже по файлу — значит побеждал он. Полоса обратной связи
   прилипала к соседнему блоку вплотную, зазор ноль при 28 у остальных.
   Измерено на собранной странице: 28 → 0 → 28.

   `gap` этим не перебивается вовсе: он свойство контейнера, и никакой
   сброс полей у ребёнка до него не дотягивается. Чинит по устройству,
   а не по специфичности — иначе следующий, кто допишет сброс ниже,
   сломал бы снова и так же молча.

   Кого это задевало, кроме обратной связи: ВСЕ сообщения об отказе,
   которые блоки печатают правящему (`km-note km-note--danger` у задания,
   звука, вложения и «После просмотра видео»), — они из того же списка. */
.km-content { display: flex; flex-direction: column; gap: 28px; }

/* НАШ БЛОК САМ ДЕРЖИТ ЗАЗОР ТАМ, ГДЕ КОНТЕЙНЕР ЕГО НЕ ДАЁТ.
   Правка 27 августа 2026, найдена измерением на боевой странице.

   Ритм `.km-content` (gap: 28) доходит только до ПРЯМЫХ детей. А материал
   человек собирает как хочет: «Расписание и тариф» целиком завёрнут
   в группу Гутенберга, и у `.km-content` там **один ребёнок** — сама
   группа. Внутри неё расстояние дают поля соседей, а наша карточка
   не даёт ни сверху, ни снизу: измерено — 0 и 0. Под соседом без верхнего
   поля блок слипается с ним вплотную.

   Тема здесь ни при чём, и это проверено: `blockGap` у неё не объявлен,
   и WordPress правил `margin-block-start` детям группы не печатает вовсе.

   Поля, а не `gap`: контейнер чужой, и договориться с ним нельзя. Поля
   при этом СХЛОПЫВАЮТСЯ — два наших блока подряд дадут 28, а не 56,
   и сосед с полем в 16 не прибавит их к нашим.

   Внутри своего ритма поля снимаются: там расстояние задаёт `gap`,
   и сложенные с ним они дали бы 56. Специфичность (0,2,0) против (0,1,0) —
   побеждает по устройству, а не по порядку в файле. */
[data-lms-block] { margin-block: 28px; }
.km-content > [data-lms-block] { margin-block: 0; }

/* А В ОБЁРТКЕ, КОТОРУЮ МЫ САМИ ПОМЕТИЛИ, ЗАЗОР УЖЕ ЕСТЬ.
   Решение человека 10 сентября 2026, найдено измерением на стенде.

   Плеер помечает `data-lms-block` чужую обёртку, внутри которой лежит
   готовый блок и ничего своего, — чтобы она не получила карточки. Но
   правило выше продолжало давать блоку внутри его собственные 28,
   и они складывались с ритмом колонки: замерено **56 над блоком против
   28 между соседями**, ровно вдвое.

   Снимаются только КРАЯ, а не поля вообще: обёртка может держать два
   готовых блока, и между собой им расстояние по-прежнему нужно.

   Правило узкое намеренно — только внутри помеченной нами обёртки,
   которая сама лежит в колонке занятия. В группе со своим текстом
   обёртка не помечена, карточку она получает, и зазор внутри неё
   по-прежнему держит сам блок. */
.km-content > [data-lms-block] [data-lms-block]:first-child { margin-block-start: 0; }
.km-content > [data-lms-block] [data-lms-block]:last-child { margin-block-end: 0; }

/* БЛОКИ ЗАНЯТИЯ ЧИТАЮТСЯ КАК ОДНА СЕМЬЯ: один радиус и одна вертикаль.
   Макет `design/lesson-blocks-v2.html`, правка 27 августа 2026.

   Измерено на собранной странице до правки: радиусы 20 / 16 / 10 / 20,
   а знаки блоков стояли на 367 и 363 — разъехались на четыре пикселя,
   потому что горизонтальные поля у `.km-files` и `.km-note` разные.
   Четыре пикселя не видны по отдельности и видны в паре: два блока
   читаются как один разъехавшийся, ровно как сказано в макете.

   Правится ТОЛЬКО внутри `.km-content`: `.km-note` живёт ещё на девяти
   административных экранах, и общий радиус там ни при чём. Тот же довод,
   по которому у имени спрашивают не «занято ли», а «сколько определений».

   ОБРАТНОЙ СВЯЗИ В ЭТОМ СПИСКЕ НЕТ, и это не пропуск: с 27 августа она
   `.km-feedback` со своим радиусом 20 выше. Своё имя носит своё число —
   иначе полоса в предпросмотре редактора, где `.km-content` нет, снова
   поехала бы с чужим. */
.km-content > .km-files,
.km-content > .km-note,
/* Двадцать — то же число, что у `.km-player__main .km-card` ниже. Взято
   литералом, а не переменной: переменной с таким смыслом в системе нет,
   а выдуманная читалась бы как настоящая. Меняется здесь и там вместе. */
.km-content > .km-audio { border-radius: 20px; }

.km-content > .km-note { padding-left: 18px; padding-right: 18px; }

/* Карточка вокруг кадра — БЕЗ ПОЛЕЙ.
 *
 * В `design/lesson-player.html` видео идёт встык до краёв карточки:
 * рамка кадра и есть её верх. Поля здесь утапливали кадр на 24 пикселя
 * с каждой стороны — 930 внутри 980, — и карточка читалась как рамка
 * вокруг картинки, а не как сама картинка.
 *
 * `overflow: hidden` обязателен: без него прямые углы кадра торчат
 * из скруглённых углов карточки. */
.km-card--media { padding: 0; overflow: hidden; }
.km-card--media > * { display: block; width: 100%; }

/* Проза занятия в карточке — макет плеера. Поля крупнее обычных 24:
   колонка чтения широкая, и текст, прижатый к рамке, читается тяжело.
   Числа с макета: 28 сверху и снизу, 32 по краям, строка 1.75. */
.km-prose { padding: 28px 32px; }

/* СВОИ ПОЛЯ У ДЕТЕЙ ОБНУЛЯЮТСЯ, И ЭТО НЕ УКРАШЕНИЕ. Правка 8 сентября 2026.

   Содержимое приходит чужой разметкой и живёт по правилам темы, а тема
   даёт каждому абзацу поле снизу:

       p { margin: 0 0 1.6875rem }      ← buddyboss-theme/assets/css/theme.css

   Двадцать семь пикселей темы складывались с нашим промежутком, и между
   абзацами на гостевой странице выходило СОРОК ТРИ. Померено на боевом;
   пустых абзацев в содержимом при этом не было ни одного.

   Расстояние задаётся отношением соседей, а не полем у каждого: тогда
   сумма не набегает, у первого элемента нет лишнего отступа сверху,
   а у последнего снизу — и коробке не приходится его вычитать.

   Обнуляется ТОЛЬКО внутри `.km-prose` и только у прямых детей: абзацы
   вне прозы живут по правилам темы законно. */
.km-prose > * { margin: 0; }
.km-prose > * + * { margin-top: 16px; }
.km-prose p { line-height: 1.75; }

/* Заголовкам внутри прозы воздуха больше: они начинают кусок, а не
   продолжают абзац. Первому сверху не нужно — он и так первый. */
.km-prose > h2 + *,
.km-prose > h3 + *,
.km-prose > h4 + * { margin-top: 12px; }
.km-prose > * + h2,
.km-prose > * + h3,
.km-prose > * + h4 { margin-top: 32px; }

.km-prose ul,
.km-prose ol { padding-left: 22px; }
.km-prose li { line-height: 1.7; }
.km-prose li + li { margin-top: 6px; }

/* Пустой абзац из редактора схлопывается. В содержимом 12-rays таких нет,
   но в чужом тексте они появляются сами: редактор оставляет `<p>&nbsp;</p>`
   между кусками, и к отступу прибавляется целая пустая строка. */
.km-prose > p:empty,
.km-prose > p > br:only-child { display: none; }


/* Шапка занятия — числа с макета плеера.

   Крошка обычной строкой, без верхнего регистра: `km-eyebrow` носит
   надстрочники по всему фронту, и правка его ради одного экрана уехала бы
   на восемь других. Заголовок крупнее общего `km-h3` — колонка чтения
   здесь одна и широкая, и заголовку есть где стоять. */
.km-lesson-place { margin: 0; font-size: 12px; color: var(--km-text-muted); }
.km-lesson-title {
  margin: 0;
  font-family: var(--km-font-display);
  font-size: 34px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.15;
}

/* ПУСТЫЕ КРОШКА И ЗАГОЛОВОК МЕСТА НЕ ЗАНИМАЮТ. Правка Алены 15 сентября 2026.
   Их рисует ответ карты — на боевом он приходит на 5,2 с от начала загрузки, —
   и до него пустые элементы держали два промежутка шапки по 24 px: на телефоне
   это пустота между «Программой курса» и «Править». */
.km-lesson-place:empty,
.km-lesson-title:empty { display: none; }

/* ШАПКА ЗАНЯТИЯ СО СТРЕЛКАМИ — липкая (12.2, решение Алены 23 сентября 2026:
   «на телефоне не надо крутить до низа»).

   `top` считается от чужой обвязки, а не от нуля: сверху стоит липкая шапка
   темы, промо-полоса и панель администратора, и их высоту замеряет живьём
   `assets/js/chrome.js` (исключение правила 13). С нулём шапка занятия
   прилипла бы ПОД шапку темы, и первым уезжал бы её верх — ровно тот дефект,
   что уже был у колонок дерева.

   ПОДЛОЖКИ У ШАПКИ НЕТ ВОВСЕ. *Слово Алены 23 сентября 2026: «у шапки цвет
   какой-то есть — отличается от фона страницы», «сделай вообще без цвета».*

   Разница была настоящей и замерена: страницу красит тема
   (`--bb-body-background-color`, #FAFBFD), а шапка бралась за наш
   `--km-page` (#F6F8FB) — на четыре единицы оттенка светлее, и полоса
   читалась глазом. Брать чужую переменную значило бы завести чужой
   контракт у себя; своя же всегда будет спорить с темой.

   Цена названа вслух: содержимое при прокрутке проходит ПОД шапкой,
   и разделяет их только линия снизу. */
.km-lesson-head {
  position: sticky;
  top: var(--km-chrome-top, 0px);
  z-index: 5;
  display: flex;
  align-items: flex-start;
  gap: var(--km-gap-group);
  padding: 12px 0 10px;
  border-bottom: 1px solid var(--km-border);
}
.km-lesson-head__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }

/* Пара стрелок не сжимается и не переносится: без одной из них пара
   читается как сбой вёрстки. */
.km-lesson-head__nav { flex: none; display: flex; gap: 6px; padding-top: 4px; }
.km-lesson-head__nav:empty { display: none; }

@media ( max-width: 560px ) {
  .km-btn--square { width: 32px; height: 32px; }
  .km-lesson-head { gap: var(--km-gap-label); }
}

/* ЧУЖОЕ ПОЛЕ НАД ЗАГОЛОВКОМ ГАСИТСЯ. Сниппет сайта «Объединённый CSS» (раздел
   «1. LearnDash CSS», «Header Issue on LearnDash Lesson») ставит всякому `h1`
   до 782 px `padding-top: 30px !important` — старая починка шапки урока
   LearnDash. Замер на боевом 15 сентября 2026, ширина 375: 30 px над заголовком
   занятия и над «Мои курсы».
   `!important` — ответ той же силой, а не привычка: без него чужое правило
   побеждает любым весом. Класс сильнее `h1`, и порядок подключения не важен.
   Остальные наши `h1` — «Мои работы», страница курса — несут те же 30 px
   и не тронуты: решает Алена. У каталога сняты 19 сентября 2026 её словом
   («убрать все отступы, как у кабинета»). */
.km-lesson-title,
.km-page.km-dashboard h1,
.km-page.km-catalog h1 { padding-top: 0 !important; }

/* Карточки читальной колонки скруглены сильнее общих. Так в макете плеера:
   там радиус 20 у всех — у прозы, у видео, у аудио и у задания, — а общий
   в дизайн-системе 16, и его держит страница курса, где нарисовано 16.
   Разные числа на двух экранах — решение макетов, а не расхождение. */
.km-player__main .km-card { border-radius: 20px; }

/* ---------------------------------------------------------------------------
   Кабинет и страница курса (5.6)
   ---------------------------------------------------------------------------

   Обе — две колонки: слева навигация или содержимое, справа второстепенное.
   На узком обе становятся одной колонкой, и порядок в разметке уже такой,
   каким он нужен телефону: сначала главное.
   --------------------------------------------------------------------------- */
/* Кабинет — одна колонка: левое меню даёт тема (BuddyPanel), а не мы. */
.km-dashboard {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	align-items: start;
}

/* НАД «МОИМИ КУРСАМИ» — НОЛЬ. Правка Алены 15 сентября 2026.
   Кабинет стоит во вкладке Elementor рядом с меню «Личного кабинета»,
   и заголовок начинается вровень с первым пунктом меню. Замер на боевом:
   панель и меню — 200, заголовок — 232; эти 32 — общий `padding-top`
   у `.km-page`, ни тема, ни Elementor к нему не прибавляют. Общее правило
   делят каталог, курс и «Мои работы», поэтому ноль — у самого кабинета. */
.km-page.km-dashboard { padding-top: 0; }

/* У КАТАЛОГА ОТСТУПОВ НЕТ НИ С ОДНОЙ СТОРОНЫ. Слово Алены 19 сентября 2026:
   «в шорткоде каталога курсов нужно убрать все отступы сверху-снизу-справа-
   слева — мы так делали для шорткода кабинета». Замер на боевом: 32 сверху
   и 96 снизу — общий `padding` у `.km-page`; боковые сняты `--flush`
   с 15 сентября. Ширина — во всю колонку: предел 1180 оставлял бы поля
   по бокам там, где колонка Elementor шире. Поля ставит хозяйка страницы. */
.km-page.km-catalog { padding: 0; max-width: none; }

.km-dashboard__main { min-width: 0; }

.km-course {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 320px;
	gap: 32px;
	align-items: start;
}

.km-course__main { min-width: 0; }

/* Верх центральной колонки — по верху первой карточки справа, на любой вкладке (решение Алены 14.10.2026).
 *
 * Панели вкладок — соседи в разметке, а видна всегда одна. Ритм секций `.km-section + .km-section` (28 px)
 * давал отступ сверху каждой панели, кроме первой («Курс»), даже когда та спрятана: на боевом первый блок
 * «Трансляций», «Материалов», «Прогресса», «Награды» и «Рейтинга» стоял на 28 px ниже карточки «Награда за курс»
 * (замер 14.10.2026: 910 против 882). Отступ снят там, где появлялся, — между панелями; сила (0,3,0) выше ритма
 * (0,2,0), порядок в таблице не решает. На телефоне колонки идут одна под другой — там как было. Держит мерка
 * стенда страницы курса «верх первого блока — по верху первой карточки справа».
 */
@media (min-width: 641px) {
	.km-course__main > .km-section + .km-section { margin-top: 0; }
}
/* Боковая колонка ИДЁТ ВДОЛЬ СТРАНИЦЫ, а не кончается на своей высоте.
 *
 * Обрыва в смысле обрезки здесь не было: ни своей высоты, ни прокрутки,
 * ни `overflow` у колонки нет — прочитано на боевом. Кончалась она просто
 * потому, что кончалось её содержимое: четыре карточки дают 1400 пикселей,
 * а дерево раскрытого модуля — 3250, и `align-items: start` оставляет
 * под колонкой полторы тысячи пустоты.
 *
 * В макете этого не видно: там дерево короткое, и обе колонки кончаются
 * вместе. Случай, которого макет не рисует, — тот же род, что одиночный
 * узел верхнего уровня.
 *
 * Липкость выбрана вместо растягивания: растянутая колонка пустоту
 * не убирает — карточки всё равно лежат сверху, — а липкая едет вместе
 * с человеком, и справа от дерева всегда что-то есть.
 *
 * **Оговорка, и она честная:** колонка выше окна (1400 против 990),
 * и в прилипшем состоянии её низ остаётся за краем. Пока карточек четыре,
 * человек видит их все в начале прокрутки; станет больше — понадобится
 * своя прокрутка у колонки, и это уже другое решение.
 *
 * Отступ сверху — под липкую шапку темы: без него первая карточка
 * уезжает под неё.
 *
 * **Здесь стояло `top: 90px`, и число было выдумано.** Чужая обвязка сверху
 * складывается из трёх слагаемых — шапка темы 70, промо-полоса Elementor 64,
 * панель администратора 32, — и на боевом это 134 у курсанта и 166 у нас.
 * Девяносто не совпадало ни с одним из двух. Считает теперь `chrome.js`
 * живым замером; двадцать сверху — воздух, а не поправка на чужое. */
.km-course__side {
	display: flex;
	flex-direction: column;
	gap: 20px;
	position: sticky;
	top: calc(var(--km-chrome-top) + 20px);
}

/* Счётчик у вкладки: сколько курсов внутри. Тусклее самой вкладки —
   это подсказка, а не значение. */
.km-tab__count { font-weight: 600; opacity: 0.55; margin-left: 6px; }

/* Шапка курса.
 *
 * Два вида, и второй — не украшение. Простой: обложка сверху, название
 * в белой карточке под ней. С наложением (`--over`): название и бейджи
 * лежат **поверх** обложки по градиенту, как нарисовано в обоих макетах
 * страницы курса — и участнику, и гостю.
 *
 * До 9-го этапа комментарий здесь обещал наложение, а код рисовал простой
 * вид. Слом такого комментария ничего не роняет — он и не должен: обещание
 * жило в прозе, а не в правиле.
 */
.km-hero { position: relative; overflow: hidden; border-radius: var(--km-radius-card); }
.km-hero__cover { aspect-ratio: 21 / 9; background: var(--km-track); }
.km-hero .km-hero__cover img { width: 100%; height: 100%; object-fit: cover; display: block; }

.km-hero__body {
	display: flex;
	flex-direction: column;
	gap: 8px;
	padding: 20px 24px 24px;
	background: var(--km-surface);
	border: 1px solid var(--km-border);
	border-top: none;
	border-radius: 0 0 var(--km-radius-card) var(--km-radius-card);
}

.km-hero__title { font-family: var(--km-font-display); font-size: 32px; font-weight: 700; line-height: 1.25; }

/* Полоса прогресса над вкладками: счёт и доля слева, действия справа.
 *
 * Кнопки не переносятся, пока помещаются, и уходят под полосу, когда нет:
 * `flex-wrap` у полосы плюс `min-width` у левой колонки. Число 260 из
 * макета — ниже него «Пройдено 8 занятий из 20» рвётся на две строки. */
.km-headline {
	display: flex;
	align-items: center;
	gap: 28px;
	flex-wrap: wrap;
}

.km-headline > .km-progress { flex: 1; min-width: 260px; }
.km-headline > .km-actions { flex: none; }

/* ЛЕНТА «КУРС ПРОЙДЕН» на обложке. Макет `course-completed-v2.html`.
 *
 * Стоит поверх шапки в правом верхнем углу — так её видно до прокрутки,
 * а прокрутка на странице курса длинная.
 *
 * `z-index: 2` не украшение: затемнение обложки рисуется псевдоэлементом
 * `.km-hero--over::after`, а тело шапки лежит на первом слое. Без второго
 * лента ушла бы под затемнение и позеленела бы вполсилы — то есть осталась
 * бы на месте и перестала бы отличаться, а это ровно то, чего признак
 * не должен делать.
 *
 * Белым по плотному зелёному, а не светлой плашкой: обложки бывают любые,
 * и светлая по светлой не читается вовсе. Ошибка выбирается в ту сторону,
 * где она заметна. */
.km-hero__ribbon {
	position: absolute;
	top: 18px;
	right: 18px;
	z-index: 2;
	display: inline-flex;
	align-items: center;
	gap: 8px;
	font-size: 12.5px;
	font-weight: 700;
	padding: 8px 14px 8px 11px;
	border-radius: 999px;
	background: var(--km-done);
	color: #fff;
	box-shadow: 0 2px 10px rgba(20, 28, 37, 0.3);
}

/* Место под ленту в шапке БЕЗ обложки.
 *
 * С обложкой текст стоит по центру и до угла не достаёт, а без неё шапка —
 * это белое тело, и первая его строка начинается ровно там, где лежит лента.
 * Без отступа надзаголовок уезжал бы под неё. */
.km-hero--done:not(.km-hero--over) .km-hero__body { padding-right: 170px; }

/* На узком место под ленту берётся СВЕРХУ, а не справа — так и в макете.
 *
 * Справа его брать нечего: на 375 отступ в 170 пикселей оставляет заголовку
 * половину колонки, и «Дневник желаний · поток 2024» рвётся на четыре
 * строки. Проверено глазами на стенде, а не рассуждением. */
@media (max-width: 640px) {
	.km-hero--done:not(.km-hero--over) .km-hero__body {
		padding-right: 24px;
		padding-top: 56px;
	}
}

.km-hero__badges { display: flex; flex-wrap: wrap; gap: 8px; }
.km-hero__lead { font-size: 15px; line-height: 1.6; max-width: 500px; text-wrap: pretty; }

/* Наложение. Ставится **только когда обложка есть**: без картинки под
   текстом остался бы белый прямоугольник в 280 пикселей, то есть ровно
   то пустое место, из-за которого в 5.6 решили не рисовать полосу
   обложки вовсе. Решает это тот, у кого есть данные, — скрипт. */
.km-hero--over .km-hero__cover {
	position: absolute;
	inset: 0;
	aspect-ratio: auto;
}

/* Картинка ОБЯЗАНА заполнить коробку, и без этого правила шапка выходит
   пустой: коробка растянута абсолютно, а картинка внутри стоит своим
   размером, и белому тексту наложения лечь не на что. Ровно это
   и случилось в 0.88.0. */
.km-hero--over .km-hero__cover img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

/* Затемнение — псевдоэлементом, а не своим `div`: оно ничего не значит
   и читать его нечем. Разметке от него не должно доставаться ни строки. */
.km-hero--over::after {
	content: '';
	position: absolute;
	inset: 0;
	background: linear-gradient(
		to bottom,
		rgba(63, 52, 46, 0.6) 0%,
		rgba(63, 52, 46, 0.22) 55%,
		rgba(63, 52, 46, 0.05) 100%
	);
}

.km-hero--over .km-hero__body {
	position: relative;
	z-index: 1;
	/* Высота общая — 280. ВЫСОКАЯ ШАПКА ТОЛЬКО У ГОСТЯ, и это правлено
	   после того, как 460 уехали и на страницу участника: класс
	   `km-hero--over` носят обе, и число, поставленное здесь, досталось
	   обеим. Ровно тот случай, что записан правилом про имена: своё
	   пространство общее с самим собой. */
	/* 320: 280 по макету плюс сорок решением человека 8 августа 2026.
	   Прибавка одна на обе страницы — просили и там, и там. */
	min-height: 320px;
	/* Содержимое по центру шапки, а не прижато к верху — так в макете. */
	justify-content: center;
	gap: 12px;
	padding: 30px 36px 34px;
	background: none;
	border: none;
	border-radius: 0;
	color: #fff;
}

.km-hero--over .km-hero__title {
	font-size: 42px;
	letter-spacing: -0.02em;
	line-height: 1.12;
	color: #fff;
}

.km-hero--over .km-hero__lead { color: rgba(255, 255, 255, 0.9); }

/* ФИРМЕННАЯ ШАПКА КУРСА У УЧАСТНИКА. Правка Алены 6 сентября 2026.
 *
 * Своим классом, а не поверх `km-hero--over`: тот носят **обе** страницы,
 * участника и гостя, и это записано абзацем выше. Правка «только шапку
 * участника» через общий класс досталась бы и гостю — ровно та беда,
 * которую здесь уже ловили числом 460.
 *
 * Заголовок тёмный, значит затемнение картинки снимается: оно заведено
 * под белый текст и под тёмным делает ровно обратное.
 */
/* ПРОПОРЦИИ У КОРОБКИ КАРТИНКИ В НАЛОЖЕНИИ НЕТ, и это правка 6 сентября
   2026 по замеру. Стояло `aspect-ratio: 32 / 9` — при ширине 1124 это
   316 пикселей, а шапка задана в 274, и коробка торчала вниз на 42.
   Картинка центрируется внутри коробки, а видно окно шапки, прижатое
   к верху: обрезка выходила 29 сверху и 71 снизу вместо поровну.

   Правило снято целиком, а не переопределено: в наложении коробку задаёт
   `position: absolute; inset: 0` соседним правилом — она и так равна
   шапке, — а на узком экране пропорцию ставит мобильное правило ниже.
   Третьего случая у этой коробки нет: без обложки она спрятана вовсе. */

/* Затемнение снимается только у тёмного заголовка: оно заведено под белый
   текст и под тёмным делает ровно обратное. */
.km-hero--brand.km-hero--ink.km-hero--over::after { content: none; }

/* А у СВЕТЛОГО заголовка затемнение своё, и оно горизонтальное.
   Общее — сверху вниз, и заведено оно под текст, стоявший в шапке
   высотой 320. Текст теперь стоит слева и ниже, где прежний градиент
   уже сошёл на нет, — белые буквы оказывались на светлой картинке.
   Найдено глазами: вид выглядел не законченным, а запасным.

   Слева направо — потому что заголовок прижат влево: тёмное там, где
   буквы, и чистая картинка там, где сюжет. */
.km-hero--brand.km-hero--lume.km-hero--over::after {
	background: linear-gradient(
		to right,
		rgba(28, 26, 46, 0.72) 0%,
		rgba(28, 26, 46, 0.55) 38%,
		rgba(28, 26, 46, 0.12) 72%,
		rgba(28, 26, 46, 0) 100%
	);
}

.km-hero--brand.km-hero--over .km-hero__body {
	color: inherit;
	/* ВЫСОТА ШАПКИ — 374, и число выбрано, а не подобрано на глаз.
	   Правка 6 сентября 2026: было 274, и человек сказал, что шапка узкая.

	   Начали с 420. Картинка дышит — но при ширине 1124 коробка становится
	   выше своей обложки, и та режется ПО БОКАМ: 68 пикселей с каждой
	   стороны у трёхкратных обложек и 159 у «Энергетического апгрейда»,
	   где справа воздушный шар. Поймала это мерка обрезки, заведённая
	   накануне, а не глаза.

	   374 — порог: 1124 делить на 3, самую широкую из ходовых пропорций.
	   На нём обложка показана целиком — бока и верх с низом по нулю, —
	   а тексту достаётся 202 из 374.

	   Поднимут число — мерка покраснеет и назовёт, сколько срезано
	   и с какой стороны. Она же и есть объяснение, почему здесь не 420.

	   И это же число держит форму до ответа: разметка едет пустой,
	   и без него шапка подпрыгивает, когда приходит ответ. */
	min-height: 374px;
	justify-content: center;
	align-items: flex-start;
	gap: 6px;
	padding: 26px 32px 28px;
	color: var(--km-brand-navy);
}

/* Надзаголовок — строкой, без плашки. Плашка была бейджем и спорила
   с заголовком за внимание; здесь она подпись, а не метка. */
.km-hero--brand .km-hero__eyebrow {
	font-family: var(--km-font-display);
	font-size: 13px;
	font-weight: 700;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}

.km-hero--brand.km-hero--ink .km-hero__eyebrow { color: var(--km-brand-navy); }
.km-hero--brand.km-hero--lume .km-hero__eyebrow { color: rgba(255, 255, 255, 0.92); }

/* Заголовок двумя цветами и двумя строками. Части — `span` с `display:
   block`, а не два заголовка: `<h1>` у страницы один, и разбивать его
   на два значило бы соврать про структуру тому, кто читает диктором. */
.km-hero--brand.km-hero--over .km-hero__title {
	font-family: var(--km-font-display);
	font-size: 58px;
	font-weight: 700;
	line-height: 0.98;
	letter-spacing: -0.01em;
	text-transform: uppercase;
}

.km-hero--brand.km-hero--ink.km-hero--over .km-hero__title { color: var(--km-brand-navy); }
.km-hero--brand.km-hero--lume.km-hero--over .km-hero__title { color: #fff; }

.km-hero__title-lead,
.km-hero__title-rest { display: block; }

/* Вторая часть заголовка красится только у тёмного вида: у светлого
   заголовок белый целиком, и второй цвет на затемнении не читался бы. */
.km-hero--brand.km-hero--ink .km-hero__title-rest { color: var(--km-brand-teal); }

.km-hero--brand.km-hero--ink.km-hero--over .km-hero__lead { color: var(--km-brand-navy); }
.km-hero--brand.km-hero--lume.km-hero--over .km-hero__lead { color: rgba(255, 255, 255, 0.92); }

.km-hero--brand.km-hero--over .km-hero__lead {
	font-size: 15px;
	line-height: 1.45;
	max-width: 430px;
}

/* Свои поля абзацам не положены: расстояние задаёт `gap` колонки, и два
   способа раздвигать строки разошлись бы на первой же правке. Проверка
   дизайн-системы это ловит, и она права. */
.km-hero__eyebrow,
.km-hero__author { margin: 0; }

.km-hero--brand .km-hero__author {
	font-size: 14px;
	font-weight: 600;
}

.km-hero--brand.km-hero--ink .km-hero__author { color: var(--km-brand-navy); }
.km-hero--brand.km-hero--lume .km-hero__author { color: rgba(255, 255, 255, 0.92); }

/* ПОЛОСА ПРОГРЕССА ПЛОТНЕЕ. Подпись мелко сверху, под ней счёт,
   под ним полоса с долей справа. Прежде счёт и доля стояли строкой,
   а подписи не было вовсе — высота уходила на пустой промежуток. */
.km-headline .km-progress { gap: 4px; }

.km-headline .km-progress__caption {
	font-family: var(--km-font-display);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--km-text-muted);
}

/* Подпись и плашка «Курс пройден» — одной строкой, как в макете.
 *
 * `flex-wrap` не украшение: на 375 подпись и плашка вместе не помещаются,
 * а без переноса плашка выдавила бы карточку за край экрана. Неразрывных
 * слов в ней нет, но вдвоём они шире колонки. */
.km-progress__caption-row {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 10px;
}

.km-headline .km-progress__head { display: block; }

.km-headline .km-progress__label { font-size: 16px; font-weight: 700; }

/* Доля уезжает к полосе, а не стоит своей строкой. */
.km-headline .km-progress__line { display: flex; align-items: center; gap: 12px; }
.km-headline .km-progress__line .km-progress__bar { flex: 1; }
.km-headline .km-progress__line .km-progress__percent { flex: none; }

/* Числа вкладки «Прогресс»: крупное значение, подпись под ним. */
.km-stats { display: flex; flex-wrap: wrap; gap: 28px; }
/* Черты между числами нет, и это решение, а не пропуск.

   В макете страницы курса она нарисована — там три числа в одну строку.
   На настоящем курсе типов пять, строка переносится, и `+`-черта достаётся
   первому числу второго ряда: висящая палка слева от «1 чек-поинтов».
   Средствами CSS «первый в ряду» не спрашивается никак.

   Тот же род, что «мерка, верная на трёх карточках, врёт на пяти», только
   про оформление: макет нарисован под то число элементов, которое в нём
   было. Расстояние разносит числа и без черты. */
.km-stat { display: flex; flex-direction: column; gap: 2px; }
.km-stat__value { font-family: var(--km-font-display); font-size: 28px; font-weight: 700; line-height: 1.1; color: var(--km-accent); }
.km-stat__label { font-size: 13px; color: var(--km-text-secondary); }

/* Файлы занятия — блок вложения.
   Список в одной карточке: знак по типу слева, имя, под ним формат и размер,
   действие справа. Макет `design/lesson-blocks-v1.html`, 19 августа 2026.

   Черта между строками, а не отступ: файлов в блоке сколько угодно,
   и на пяти строках отступы читались бы как пять отдельных карточек. */
/* Группа файлов во вкладке «Материалы» (5.8.3, макет шага 3).

   КАРТОЧКУ НЕСЁТ СТРОКА, А НЕ ГРУППА — правка 28 августа 2026, найдена
   глазами на снимке. Первая редакция надела рамку на группу, и файлы
   внутри слиплись в таблицу с разделительными линиями; в макете
   наоборот: каждый файл — своя карточка, а имя занятия стоит голым
   текстом над списком, без рамки и без подложки.

   Отсюда же и промежуток: 20 между группами берётся у самой группы,
   а не складывается из двух рамок подряд. */
/* Обёртка панели: своя, чтобы промежуток между группами задавала
   только группа. Внутри стопки, раздающей зазор детям, 20 у группы
   складывалось бы с зазором стопки — намерено 20, на экране выходило 44. */
.km-materials { display: block; }
.km-grp { margin-bottom: 20px; }
.km-grp:last-child { margin-bottom: 0; }
.km-grp__h {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  margin: 0 0 8px;
}
.km-grp__name { flex: 1; min-width: 140px; font-size: 14.5px; font-weight: 700; color: var(--km-text); }
/* Причина не сжимается и переносится целиком: «откроется 5 сентября»
   без даты — не причина, а намёк. */
.km-grp__why { flex: none; font-size: 12.5px; color: var(--km-text-muted); }
/* Закрытая группа глуше, но читается: файлы видны и названы — правило
   отображения закрытых узлов, то же самое (12.2). */
.km-grp--locked .km-grp__name { color: var(--km-text-muted); }

/* СТРОКА-КАРТОЧКА — ТОЛЬКО ВНУТРИ ВКЛАДКИ, и это не осторожность.

   `.km-file` общий с блоком вложения в занятии, и там он выглядит иначе:
   плоская строка внутри карточки `.km-files`. Так рисует его свой макет,
   `lesson-blocks-v2.html`, и так человек видит его с 1.108.0.

   То есть один класс носит два вида в двух макетах — родня `.km-hint`,
   у которого было два определения. Разница в том, что здесь они не
   складываются: вид выбирается тем, внутри чего строка стоит. Сними
   область — и блок в занятии переоденется заодно. */
.km-grp .km-file {
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: 14px;
  padding: 12px 16px;
  margin-bottom: 7px;
  border-bottom: 1px solid var(--km-border);
}
.km-grp .km-file:last-child { margin-bottom: 0; border-bottom: 1px solid var(--km-border); }
/* Закрытая — на тусклой подложке, тем же цветом, каким помечены
   спокойные поверхности в системе. Своего цвета для этого заводить
   не пришлось: `--km-surface-soft` в системе не объявлен вовсе,
   а `--km-surface-alt` есть и означает ровно это. */
.km-grp .km-file--locked { background: var(--km-surface-alt); }
.km-grp--locked .km-file__name { color: var(--km-text-muted); }
.km-grp--locked .km-file__glyph { color: var(--km-text-muted); }

/* Заголовок «Материалы для скачивания» — над карточкой файлов, как у блока расписания (слово Алены 09.10.2026). */
.km-files-block > .km-files-block__title { margin: 0 0 12px; }
.km-files {
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-card);
  padding: 4px 18px;
}
.km-file {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 13px 0;
  border-bottom: 1px solid var(--km-border-soft);
  text-decoration: none;
  color: inherit;
}
.km-file:last-child { border-bottom: none; }
/* Закрытая строка — не ссылка, и указателя «нажми» у неё нет:
   живая на вид, но неработающая, она обещала бы переход, которого
   не будет. Файл при этом виден и назван (12.2). */
.km-file--locked { cursor: default; }
.km-file--locked .km-file__action { color: var(--km-text-muted); }
.km-file__glyph { flex: none; width: 22px; height: 22px; color: var(--km-accent); }
.km-file__body { flex: 1; min-width: 0; }
/* 14,5 — из макета `design/lesson-blocks-v2.html`, правка 27 августа 2026.
   Было 15, потому что рядом полоса обратной связи держала 14.

   ЧИСЛО СОСЕДА С ТЕХ ПОР СМЕНИЛОСЬ, и строка правится вместе с ним: макет
   `design/feedback-block-v3.html` даёт `.km-feedback__text` те же 14,5.
   Оба числа измерены в макетах, а не подобраны на глаз, и теперь они
   одинаковые — два блока стоят рядом на одной странице. */
.km-file__name { display: block; font-size: 14.5px; line-height: 1.35; color: var(--km-text); }
.km-file__meta { display: block; font-size: 12px; color: var(--km-text-muted); margin-top: 2px; }

/* Действие бледнее подписи намеренно: оно повторяет то, что и так понятно
   из строки, и спорить с именем файла за внимание не должно. */
.km-file__action { flex: none; width: 19px; height: 19px; color: #B7C1CD; }
.km-file:hover .km-file__name { color: var(--km-accent); }
.km-file:hover .km-file__action { color: var(--km-accent); }

/* Файл удалили, строка осталась. Не ссылка и потому не притворяется живой:
   место, за которым нет данных, называет причину. */
.km-file--missing { cursor: default; }
.km-file--missing .km-file__glyph,
.km-file--missing .km-file__name { color: var(--km-text-muted); }

/* ПОЛОСА ОБРАТНОЙ СВЯЗИ — ОДНА КАРТОЧКА, ЗАГОЛОВОК ВНУТРИ НЕЁ.
   Макет `design/feedback-block-v3.html`, 27 августа 2026.

   До этого блок собирался из `.km-note km-note--warm km-note--action`,
   а заголовок стоял НАД плашкой отдельной строкой — и читался как два
   блока подряд: подпись и почему-то тёплая полоса под ней. Макет v2,
   по которому это собиралось, заголовка не содержал вовсе; v3 заменяет
   в нём блок обратной связи целиком и говорит прямо: карточка одна.

   Своё имя, а не модификатор плашки. `.km-note` — флекс-СТРОКА (значок
   слева, текст справа), и всякий прямой ребёнок в ней становится колонкой;
   здесь же две строки друг под другом. Модификатором это выражалось бы
   переопределением `display` у чужого компонента, то есть второй правдой
   о том, как `.km-note` устроен.

   ЗНАК ПЕРЕЕХАЛ НАВЕРХ, К ЗАГОЛОВКУ — довод из макета дословно: «два знака
   на разной высоте в одной карточке читались бы как два блока».

   Радиус 20 — то же число, что у соседних блоков занятия ниже, и стоит оно
   ЗДЕСЬ, а не только в `.km-content`: полосу показывает ещё и предпросмотр
   в редакторе, где `.km-content` нет вовсе. До этой правки она приезжала
   туда с радиусом плашки (10) — то есть предпросмотр показывал не то, что
   увидит курсант. Меняется вместе с числом в `.km-content` ниже. */
.km-feedback {
  background: var(--km-warm-bg);
  border: 1px solid var(--km-warm-border);
  border-radius: 20px;
  padding: 16px 18px;
  color: var(--km-warm-text);
}

/* Шапка: знак и заголовок в одной строке, по центру друг друга. */
.km-feedback__head {
  display: flex;
  align-items: center;
  gap: 11px;
  margin-bottom: 10px;
}
.km-feedback__glyph { flex: none; width: 22px; height: 22px; color: var(--km-accent); }

/* Заголовок — свой кегль, а не `km-h5`.

   `km-h5` это 20px заголовочным шрифтом: он верен для заголовка НАД
   карточкой и слишком крупен внутри тёплой полосы, где спорил бы
   с самой фразой. Шрифт назван явно: заголовок здесь `h2`, и без этого
   он взял бы заголовочный шрифт темы, которого в макете нет. */
.km-feedback__title {
  margin: 0;
  font-family: var(--km-font);
  font-size: 15px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--km-warm-text);
}

/* Строка под шапкой: фраза и кнопка. Кнопка не сжимается — иначе на узком
   надпись переносится по буквам; строка переносится целиком, потому что
   надпись это название группы сообщества, а они длинные. */
.km-feedback__row {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}
.km-feedback__row > .km-btn { flex: none; }
.km-feedback__text {
  flex: 1;
  min-width: 180px;
  font-size: 14.5px;
  line-height: 1.5;
}

@media (max-width: 640px) {
  /* Кнопка уходит на свою строку целиком: прижатая вправо, она читалась бы
     как продолжение фразы. Число то же, что у `.km-note--action` выше:
     «Практикум по Местам Вознесения 2026» даёт кнопку в 302 пикселя. */
  .km-feedback__row > .km-btn { width: 100%; text-align: center; }
}

/* «После просмотра видео»: одна фраза со ссылкой на занятие.
   Макет `design/lesson-blocks-schedule-v1.html`, 26 августа 2026.

   Своих правил у блока два, и оба про фразу: карточку, заголовок и отступы
   он берёт готовыми — `km-card km-card__pad` и `km-h5`. Заводить под него
   третье имя значило бы завести второе определение карточки. */
.km-after__text { font-size: 16px; line-height: 1.65; margin: 0; }

/* Подчёркивание на наведении — здесь, а не у глобальной ссылки: в сплошной
   фразе ссылку надо отличать от текста не только цветом, а в карточках
   и кнопках подчёркивание было бы лишним. */
.km-after__text a:hover { text-decoration: underline; text-underline-offset: 2px; }

/* КАРТОЧКА БЛОКА В РЕДАКТОРЕ — шапка, тело, метка вида.
   Макет `design/lesson-blocks-schedule-v1.html`, раздел «Изнутри»,
   решение Алены 27 августа 2026.

   До этого блоки выглядели стандартным Gutenberg: чёрные подписи полей,
   объяснение прозой абзацем. Вид у него не наш, и на странице занятия
   человек видит одно, а правит в другом. Карточка возвращает узнаваемость:
   шапка говорит, ЧТО это за блок, метка справа — какого он вида.

   Заведено пока для одного блока. Остальные пять приводятся отдельной
   задачей: у каждого свои поля, и переписывать их скопом значит править
   пять экранов вслепую. */
.km-ed {
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-card);
  overflow: hidden;
}
.km-ed__head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  padding: 12px 16px;
  border-bottom: 1px solid var(--km-border);
}
.km-ed__title {
  flex: 1;
  min-width: 150px;
  font-size: 13.5px;
  font-weight: 600;
  margin: 0;
}

/* Метка вида — тёплая и мелкая: она подпись к заголовку, а не второй
   заголовок. Спорить с названием блока за внимание ей незачем. */
.km-ed__kind {
  flex: none;
  font-size: 11px;
  padding: 2px 8px;
  border-radius: 6px;
  background: var(--km-warm-bg);
  color: var(--km-warm-text);
}
.km-ed__body { padding: 14px 16px 16px; }

/* ПРЕДПРОСМОТР В РЕДАКТОРЕ БЛОКА — «Как увидит курсант».
   Макет `design/lesson-blocks-v2.html`, 27 августа 2026.

   Отделён пунктиром намеренно: сплошная черта читалась бы как край
   карточки, и предпросмотр стал бы похож на ещё одно поле. Пунктир
   говорит «дальше не настройка, а результат». */
.km-preview {
  margin-top: 14px;
  padding-top: 13px;
  border-top: 1px dashed var(--km-border);
}
.km-preview__cap {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--km-text-muted);
  margin: 0 0 9px;
}

/* ПРЕДПРОСМОТР ПОКАЗЫВАЕТ БЛОК ТАК ЖЕ, КАК СТРАНИЦА. Правка 27 августа 2026.

   На странице радиус блокам занятия задаёт `.km-content` — контейнера этого
   в редакторе нет, и карточка файла приезжала туда с базовым 16 вместо 20,
   а тёплая плашка с 10. Подпись при этом обещает «как увидит курсант»,
   то есть предпросмотр показывал не то, что обещал.

   Селектор ПОТОМКА, а не прямого ребёнка: `ServerSideRender` кладёт ответ
   сервера внутрь своей безымянной обёртки, и `>` не совпал бы. Проверено
   в настоящем редакторе, а не предположено: цепочка родителей карточки —
   `DIV.` → `DIV.km-preview`. */
.km-preview .km-files,
.km-preview .km-audio,
.km-preview .km-note { border-radius: 20px; }

/* СПРЯТАНО ОТ ГЛАЗ, НО НЕ ОТ КЛАВИАТУРЫ И НЕ ОТ ДИКТОРА.

   Не `display: none` и не `[hidden]`: скрытое ими поле выпадает из обхода
   табуляцией вовсе. Заведено под выбор файла с компьютера — родное поле
   `input[type=file]` рисует серую кнопку браузера, которую не оформить
   ничем, поэтому кнопкой служит подпись `label`, а само поле прячется
   этим классом и остаётся рабочим. */
.km-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* РАСПИСАНИЕ ТРАНСЛЯЦИЙ — своя карточка по макету
   `design/schedule-block-v1.html`, часть «Предлагаю» (задача Алены
   30.09.2026: блок сливался с текстом — ни своей границы, строки не с того
   края, названия пляшут за датами разной длины, приписка вплотную к
   следующему заголовку).

   Значения — из макета; цвета — ближайшие токены дизайн-системы: палитра
   трансляции (`--km-cast-*`) объявлена только внутри `.km-cast`, а блок стоит
   и на страницах занятий. Фон #F8F5FA и рамка #EEE7F3 — свои токены
   `--km-lilac-bg` и `--km-lilac-line` (слово Алены 30.09.2026: цвет карточки —
   как в макете; до 1.375.3 стояли серо-голубые `--km-page` и `--km-border`),
   дата #3E3654 → `--km-brand-navy`, день недели →
   `--km-text-muted`, плашка → `--km-warm-text-strong` на `--km-peach`,
   низ → `--km-text-secondary`. Название — ссылкой цвета своей страницы.

   ИМЯ `km-schedule`, А НЕ `km-live-row` из прежнего макета: рядом живёт
   семья `.km-live__*` — карточка ближайшего эфира на странице курса, —
   и имена в один знак разницы спутали бы в первый же раз. */

/* Край карточки — край текста над ней; снизу до следующего — 40 px, как
   в макете. На странице занятия, где блок стоит между карточками, отступ
   задаёт `gap` колонки (`.km-content > [data-lms-block]`). */
.km-schedule-block { margin-block: 28px 40px; }
/* В разделах трансляции ритм задаёт `.km-cast .km-cast-prose > *` (0,2,0,
   17 px снизу) — он сильнее класса и срезал бы отступ макета. Последний
   в разделе блок отступа не держит: дальше край раздела. */
.km-cast .km-cast-prose .km-schedule-block:not(:last-child) { margin-bottom: 40px; }
.km-schedule-block__title { margin: 0 0 12px; }

/* Колонка даты ОДНОЙ ШИРИНЫ: строки — подсетка карточки, и ширину колонки
   задаёт самая длинная дата, но не меньше 210 px макета. У отдельной сетки
   на строку «29 сентября» и «6 октября» сдвигали бы названия. */
.km-schedule {
  display: grid;
  grid-template-columns: minmax(210px, max-content) minmax(0, 1fr) auto;
  column-gap: 12px;
  padding: 10px;
  background: var(--km-lilac-bg);
  border: 1px solid var(--km-lilac-line);
  border-radius: 18px;
}
.km-schedule__row {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
  align-items: center;
  padding: 14px 16px;
  border-radius: 12px;
  font-size: 16px;
}
.km-schedule__row + .km-schedule__row { border-top: 1px solid var(--km-lilac-line); }

.km-schedule__when { grid-column: 1; white-space: nowrap; color: var(--km-brand-navy); }
.km-schedule__day { color: var(--km-text-muted); font-size: 14.5px; font-weight: 400; }
.km-schedule__name {
  grid-column: 2;
  min-width: 0;
  color: var(--km-accent);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 5px;
}
.km-schedule__tag {
  grid-column: 3;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 6px 11px;
  border-radius: 999px;
}

/* БЛИЖАЙШИЙ — белая строка внутри карточки с лёгкой тенью, дата жирным,
   плашка «Ближайший». Черта над ней и под ней не нужна: строку отделяет
   тень. */
.km-schedule__row--next {
  background: var(--km-surface);
  border-top-color: transparent;
  box-shadow: 0 1px 0 var(--km-lilac-line), 0 6px 18px rgba(63, 76, 92, 0.06);
}
.km-schedule__row--next + .km-schedule__row,
.km-schedule__row--now + .km-schedule__row { border-top-color: transparent; }
.km-schedule__row--next .km-schedule__when { font-weight: 700; }
.km-schedule__row--next .km-schedule__tag { background: var(--km-peach); color: var(--km-warm-text-strong); }

/* ИДЁТ СЕЙЧАС — красным, и красный здесь свой, а не `--km-danger`:
   тревоги нет, есть «сейчас». В макете этого состояния нет; строка
   держится как ближайшая — белой нет, — а отличается подложкой и цветом. */
.km-schedule__row--now { background: var(--km-danger-bg); border-top-color: transparent; }
.km-schedule__row--now .km-schedule__when { font-weight: 700; color: var(--km-live); }
.km-schedule__row--now .km-schedule__tag { background: #F8D7D3; color: var(--km-live); }
.km-schedule__row--now .km-schedule__name { color: var(--km-live); font-weight: 600; }

/* Низ карточки: слева «Дальше по курсу ещё N трансляций», справа «Все
   трансляции курса →». Нет следующих — низа нет (решает сервер). Селекторы тремя
   классами: на странице трансляции `.km-cast .km-cast-prose p` (0,2,1)
   переписал бы кегль и цвет приписки. */
.km-schedule__foot {
  grid-column: 1 / -1;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 12px 16px 6px;
  font-size: 14.5px;
  color: var(--km-text-secondary);
}
.km-schedule-block .km-schedule__foot .km-schedule__more { margin: 0; font-size: 14.5px; line-height: 1.5; color: var(--km-text-secondary); }
.km-schedule__all { flex: none; font-size: 14.5px; font-weight: 600; color: var(--km-accent); }

/* Неделя после последнего эфира: список пуст, и это сказано словами —
   в той же карточке. Пустая карточка читалась бы как поломка. */
.km-schedule--empty { display: block; padding: 14px 16px; }
.km-schedule__empty { font-size: 14.5px; color: var(--km-text-secondary); line-height: 1.6; margin: 0; }

/* На телефоне: дата сверху, название под ней, плашка справа от даты;
   низ карточки — в две строки (задача Алены 30.09.2026). Подсетка на узком
   не нужна: колонка одна. */
@media (max-width: 560px) {
  /* Поля и кегль на узком меньше, чем в макете: в разделе трансляции на 375
     строке остаётся ~257 px, а жирная дата «6 октября, вт · 19:00 МСК» и
     плашка «Ближайший» вместе — ~291 px, и время уходило под плашку
     (снимок боевого 30.09.2026). Дата при этом может и переноситься — это
     последний рубеж: две строки даты лучше, чем дата под плашкой, — и тогда
     только по «·» (неразрывные пробелы в разметке), без «МСК» одной строкой. */
  .km-schedule { display: block; padding: 4px; }
  .km-schedule__row {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "when tag" "name name";
    row-gap: 4px;
    column-gap: 6px;
    padding: 12px 8px;
  }
  .km-schedule__when { grid-area: when; font-size: 15px; white-space: normal; }
  .km-schedule__name { grid-area: name; }
  .km-schedule__tag { grid-area: tag; justify-self: end; align-self: start; font-size: 10px; letter-spacing: 0.04em; padding: 4px 8px; }
  .km-schedule__foot { flex-direction: column; align-items: flex-start; gap: 4px; padding: 12px 8px 6px; }
}


/* СЛУЖЕБНАЯ ПОЛОСА — ТО, ЧТО ВИДИТ ВЕДУЩИЙ И НЕ ВИДИТ КУРСАНТ.
   Макет `design/conditional-staff-note-v1.html`, 27 августа 2026.

   ПУНКТИР И ПРИГЛУШЁННЫЙ ЦВЕТ — не украшение: ведущий смотрит ту же
   страницу, что курсант, и сплошная рамка читалась бы как часть занятия.
   Пунктир говорит «это служебное», не крича об этом.

   Радиус тот же, что у блоков занятия (20), а у полосы сверху он на пиксель
   меньше — иначе её угол торчит из угла рамки. */
.km-staff {
  border: 1px dashed var(--km-staff-border);
  border-radius: 20px;
  background: transparent;
}
.km-staff__bar {
  display: flex;
  align-items: baseline;
  gap: 9px;
  flex-wrap: wrap;
  padding: 8px 14px;
  background: var(--km-staff-bg);
  border-radius: 19px 19px 0 0;
  border-bottom: 1px dashed var(--km-staff-border);
}
.km-staff__eye {
  flex: none;
  width: 15px;
  height: 15px;
  color: var(--km-staff);
  position: relative;
  top: 2px;
}

/* Условие — первым и весомее примечания: ведущий видит содержимое
   и первым делом спрашивает, кому оно показано. */
/* Полоса БЕЗ ТЕЛА — когда содержимое идёт следом само, а не внутри рамки.
   Так помечена страница закрытого дрипом занятия (27 августа 2026): материал
   под полосой обычный, и заворачивать его нельзя — плеер собирает прозу
   в карточки и пропускает всё, помеченное `data-lms-block`.

   Нижняя черта снимается: она разделяет полосу и тело, а тела здесь нет,
   и без этого у рамки выходила бы двойная линия снизу. */
.km-staff--alone .km-staff__bar { border-bottom: none; }

/* ПОМЕТКА И «ПОЧЕМУ ВИДНО ВАМ» — оба весомее подписи и оба УМЕЮТ СЖИМАТЬСЯ.

   `flex: none` здесь стоял с 27 августа и был верен ровно до того дня, когда
   в пометку приехало настоящее название занятия: «Не сдал задание „Правила
   участия в курсе“» — 39 знаков, и `0 0 auto` значит «не сжимайся ни за что».
   На 375 полоса от этого уезжала за край вместе со страницей. Та же семья,
   что неразрывное имя тега CRM в строке правила: перенос по словам возможен,
   а флексу запрещено даже пробовать.

   `min-width: 0` обязателен рядом: у флексового элемента минимум по умолчанию
   равен max-content, и без него `flex-shrink` ничего не меняет. */
.km-staff__cond,
.km-staff__you { flex: 0 1 auto; min-width: 0; font-size: 12px; color: var(--km-staff); }

/* Пометка весомее «почему видно вам», и различие это НЕ украшение.

   Первая редакция дала обоим 600 и развела точкой-разделителем через
   `::before`. На 375 полоса переносится ВСЕГДА — измерено на всех четырёх
   фикстурах стенда, — и точка оставалась висеть одна в начале строки,
   семью пикселями ни на чём. Разделитель, видимый только на широком, —
   это разделитель, которого нет там, где он нужнее.

   Весом различаются на любой ширине и без лишнего знака. */
.km-staff__cond { font-weight: 600; }
.km-staff__you { font-weight: 500; }

/* Подпись НЕ РАСТЯГИВАЕТСЯ на остаток строки. `flex: 1` здесь стоял, пока
   она была последней всегда: тянуться ей было некуда, и разницы не было
   видно. С 29 августа у закрытого занятия порядок другой — «Закрыто ·
   Откроется 5 сентября · Вам открыто как редактору», — и растянутая подпись
   отбрасывала бы фразу про редактора к правому краю, разрывая ряд пустотой
   там, где читается предложение. */
.km-staff__label { flex: 0 1 auto; min-width: 0; font-size: 12px; color: var(--km-text-muted); }
.km-staff__body { padding: 18px 20px; }

@media (max-width: 520px) {
  .km-staff__bar { gap: 6px; }
}

/* ПОДПИСЬ БЛОКА В ШАПКЕ КАРТОЧКИ РЕДАКТОРА — курсивом, рядом с названием.
   Тогда блоки различимы, не разворачиваясь.

   Название рядом с ней перестаёт растягиваться: место занимает подпись,
   а метка вида остаётся у правого края. Спрашивается это `:has()`, потому
   что у остальных блоков подписи нет и там название по-прежнему тянется. */
.km-ed__label {
  flex: 1;
  min-width: 110px;
  font-size: 12.5px;
  font-style: italic;
  color: var(--km-text-muted);
}
.km-ed__head:has( .km-ed__label ) .km-ed__title { flex: none; min-width: 0; }

/* УСЛОВИЕ И ЕГО ПОЛЕ — В ОДНОЙ РАМКЕ.
   Макет `design/conditional-block-v1.html`, 27 августа 2026.

   До этого условие, его поле и содержимое блока шли вперемешку, и глазом
   не было видно, где кончается настройка и начинается то, что увидит
   курсант. Рамка отвечает на это молча и сразу.

   Подложка светлее карточки, а не белая: так рамка читается как «здесь
   настройка», а белая область ниже — как «здесь содержимое». */
.km-cond {
  border: 1px solid var(--km-border);
  border-radius: 11px;
  padding: 13px 14px;
  background: var(--km-page);
}

/* СЛЕДСТВИЕ УСЛОВИЯ — тёплой строкой под рамкой.

   Не подсказка и не поле: это ответ на вопрос «и что из этого выйдет».
   Тёплая, как всё, что объясняет, а не предупреждает. */
.km-outcome {
  margin: 12px 0 0;
  background: var(--km-warm-bg);
  border: 1px solid var(--km-warm-border);
  color: var(--km-warm-text);
  border-radius: var(--km-radius-control);
  padding: 10px 13px;
  font-size: 12.5px;
  line-height: 1.55;
}

/* «БЛОК НЕ ПОКАЖЕТСЯ НИКОМУ» — ЖЁЛТЫМ, а не серой подписью.

   Своё имя, а не `km-sum`: тем именем в дизайн-системе названа сводка
   слияния аккаунтов — черта сверху и заголовок. Одно имя на два вида дало бы
   помесь, которую никто не задумывал: у проекта так уже было с `.km-hint`,
   и прожило это девять экранов.

   Цвет предупреждения, а не отказа: это не поломка, а недоделка автора,
   и красный здесь сказал бы «сломалось» там, где «не дописано». */
.km-outcome--warn {
  background: var(--km-warn-bg);
  border-color: var(--km-warn-border);
  color: var(--km-warn-text);
}

/* ОБЛАСТЬ СОДЕРЖИМОГО С ПОДПИСЬЮ «Что увидят подошедшие».

   Пунктир, а не сплошная: сплошная читалась бы как край карточки, и область
   стала бы похожа на ещё одно поле. Тот же довод, что у предпросмотра. */
.km-slot { margin-top: 14px; }
.km-slot__cap {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--km-text-muted);
  margin: 0 0 7px;
}
.km-slot__area {
  border: 1px dashed var(--km-border);
  border-radius: 11px;
  padding: 14px 15px;
  background: var(--km-surface);
}

/* Пусто — говорится словами. Пустая рамка читается как поломка: человек
   видит место, в котором ничего нет, и не знает, так и задумано или нет. */
.km-slot__area--empty { color: var(--km-text-muted); }

/* ТА ЖЕ ОБЛАСТЬ, НО ПОДПИСЬ СБОКУ — заглушки блоков программы в редакторе.
   Правка 2 сентября 2026.

   Роль та же, что у области выше: место, в котором **будет** содержимое,
   и подпись, какое именно. Поэтому модификатор, а не своя семья: третье имя
   рядом стало бы вторым способом сказать одно, и правка пунктира поехала бы
   в одно место из двух.

   Заглушки идут подряд, и подпись сверху удваивала бы высоту каждой:
   четыре блока превратились бы в восемь строк. Сбоку — четыре строки
   и один левый край у всех абзацев.

   ## Ширина столбца задана, и это главное здесь

   До правки подписью служил `<strong>` внутри `.km-note`, а та —
   флексовая строка. Ширины у столбца не было, он подстраивался под слово:
   «Что внутри» переносилось на две строки, «Полоса с ценой» — на одну,
   и текст каждой заглушки начинался со своего отступа.

   Число измерено в настоящем редакторе, а не выбрано: самое длинное имя
   («Варианты участия») занимает 133 пикселя капслоком, остальные 80–114.
   Первая редакция ставила 132 — на один пиксель меньше нужного, — и имя
   переносилось на две строки при верной в остальном раскладке. Ровно тот
   случай, когда комментарий обещает то, чего код не делает: там было
   написано «берут в одну строку». 144 оставляют запас на пятое имя.

   ## Зазор свой, потому что чужого нет

   Редактор блоков между динамическими блоками не ставит ничего, и три
   заглушки подряд слипались в стену. 12 — тот же зазор, что между
   карточками в дизайн-системе. */
.km-slot--aside {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin: 12px 0;
}
.km-slot--aside .km-slot__cap {
  flex: none;
  width: 144px;
  margin: 0;
  /* Подпись капслоком мельче текста, и по базовой линии она уезжает вверх.
     Два пикселя ставят её вровень с первой строкой абзаца. */
  padding-top: 2px;
}
/* `km-slot__body` — правый столбец, когда под областью есть ещё что-то:
   поля пояснений «Что внутри». Без него флексовая строка ставила поля
   третьим столбцом и сжимала текст области до слова в строке
   (17 сентября 2026).

   `flex: 1` у столбца — ГАРАНТИЯ, и слом её сегодня ничего не меняет:
   столбец растягивает длинный текст области, 684 px и без правила.
   Короче станет текст — без правила столбец ужмётся по нему, а поля
   ввода вслед за ним. */
.km-slot--aside .km-slot__area,
.km-slot--aside .km-slot__body {
  flex: 1;
  min-width: 0;
}

/* На узком столбца нет: 132 пикселя из 375 забирают треть строки, и абзац
   ломался бы по два слова. Подпись встаёт над областью — то же, что делает
   базовый `.km-slot`. */
@media (max-width: 640px) {
  .km-slot--aside { display: block; }
  .km-slot--aside .km-slot__cap { width: auto; padding-top: 0; margin: 0 0 7px; }
}

/* ПЕРЕКЛЮЧАТЕЛЬ ИСТОЧНИКА ФАЙЛА — одна полоса на три варианта.
   Макет `design/lesson-blocks-v2.html`.

   Имя `km-source`, а НЕ `km-seg`: рядом уже живёт `.km-segments` — чипы
   сегментов на экране зачислений, — и два имени, различающиеся хвостом,
   однажды спутают. Правило проекта спрашивает у имени не «занято ли»,
   а «с чем его спутают».

   Вариантов три, и они взаимоисключающие: это переключатель, а не набор
   кнопок. Отсюда `aria-pressed` у каждой и роль группы у полосы —
   без них экранный диктор прочитал бы три отдельные кнопки. */
.km-source {
  display: flex;
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-control);
  overflow: hidden;
  margin-bottom: 14px;
}
.km-source__pick {
  flex: 1;
  border: 0;
  border-right: 1px solid var(--km-border);
  background: var(--km-surface);
  font: inherit;
  font-size: 12.5px;
  line-height: 1.3;
  padding: 8px 6px;
  cursor: pointer;
  color: var(--km-text-secondary);
}
.km-source__pick:last-child { border-right: 0; }
.km-source__pick:hover { color: var(--km-text); }

/* ВЫБРАННЫЙ ОТЛИЧАЕТСЯ, а не просто помечен: признак существует тогда,
   когда он отличается от соседнего. Фон и вес — два признака, потому что
   один цвет плохо виден тем, кто его не различает. */
.km-source__pick[aria-pressed="true"] {
  background: var(--km-warm-bg);
  color: var(--km-warm-text);
  font-weight: 600;
}
.km-source__pick:focus-visible {
  outline: 2px solid var(--km-accent);
  outline-offset: -2px;
}

@media (max-width: 782px) {
  .km-source { flex-direction: column; }
  .km-source__pick { border-right: 0; border-bottom: 1px solid var(--km-border); }
  .km-source__pick:last-child { border-bottom: 0; }
}

/* Срок у ещё не открытого занятия — ОТДЕЛЬНОЙ СТРОКОЙ.
   Ссылка при этом остаётся живой (решение человека 26 августа 2026):
   человек и знает срок, и может сходить посмотреть, что его ждёт.
   Бледнее самой фразы намеренно — это приписка к ней, а не сообщение.

   СТРОКОЙ, А НЕ ХВОСТОМ ТОЙ ЖЕ ФРАЗЫ — правка 27 августа, и она следствие
   другой. Пока точку в конце ставили мы, срок шёл после неё и читался
   отдельно. Теперь фраза принадлежит человеку целиком, и точки в ней может
   не быть вовсе: на стенде вышло «…План работы на месяц кураторам Откроется
   16.03.2099» — два предложения в одно. Разделитель, зависящий от того,
   поставил ли человек точку, — не разделитель. */
.km-after__when { display: block; color: var(--km-text-muted); }

/* Звук в занятии.
   Плеер собран своей разметкой, а не системный: в макете кнопка, название,
   длительность и полоса позиции, и системный вид этого не даёт ни в одном
   браузере одинаково.

   Полоса — `input[type=range]`, и цвет ей задаёт `accent-color`: заливка
   до ползунка и сам ползунок красятся браузером сами. Своя заливка
   потребовала бы ширины из кода, то есть оформления из скрипта, —
   а тот же довод, что у `<progress>` в правиле 13: величина выражается
   разметкой, которая её понимает. Заодно бесплатно приходит перемотка
   с клавиатуры и чтение экранным диктором.

   Видео своих правил не имеет намеренно — его выводит плагин OmniVideo
   со своей вёрсткой. Свой блок видео был написан в 5.2 и убран вместе
   с закрытием занятия по досмотру: мера прохождения у нас сданные работы. */
.km-audio {
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-card);
  padding: 16px 18px;
}
.km-audio__head { display: flex; align-items: center; gap: 14px; }
.km-audio__play {
  flex: none;
  width: 44px;
  height: 44px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--km-accent);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.km-audio__sign { width: 19px; height: 19px; color: #FFFFFF; }
.km-audio__body { flex: 1; min-width: 0; }
.km-audio__name { display: block; font-size: 15px; line-height: 1.35; color: var(--km-text); }
.km-audio__meta { display: block; font-size: 12px; color: var(--km-text-muted); margin-top: 2px; }
.km-audio__line { margin-top: 14px; display: flex; align-items: center; gap: 12px; }
.km-audio__time { flex: none; font-size: 12px; color: var(--km-text-muted); font-variant-numeric: tabular-nums; }
/* Полоса позиции: заливка и ползунок лежат друг на друге.
   `<progress>` рисует, `<input type=range>` двигает — обоим величину даёт
   разметка, а не посчитанная ширина. Одного ползунка не хватает: браузер
   красит незаполненный остаток дорожки тёмным и хода к этому цвету не даёт. */
.km-audio__bar { position: relative; flex: 1; min-width: 0; height: 12px; display: flex; align-items: center; }
.km-audio__fill {
  position: absolute;
  left: 0;
  right: 0;
  width: 100%;
  height: 4px;
  border: none;
  border-radius: 2px;
  background: var(--km-track);
  -webkit-appearance: none;
  appearance: none;
}
.km-audio__fill::-webkit-progress-bar { background: var(--km-track); border-radius: 2px; }
.km-audio__fill::-webkit-progress-value { background: var(--km-accent); border-radius: 2px; }
.km-audio__fill::-moz-progress-bar { background: var(--km-accent); border-radius: 2px; }
.km-audio__track {
  position: relative;
  width: 100%;
  height: 12px;
  margin: 0;
  background: transparent;
  -webkit-appearance: none;
  appearance: none;
}
.km-audio__track::-webkit-slider-runnable-track { height: 12px; background: transparent; }
.km-audio__track::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 12px;
  height: 12px;
  border: none;
  border-radius: 50%;
  background: var(--km-accent);
}
.km-audio__track::-moz-range-track { height: 12px; background: transparent; }
.km-audio__track::-moz-range-thumb { width: 12px; height: 12px; border: none; border-radius: 50%; background: var(--km-accent); }

/* Сам звук не показывается: играет он, а видит человек разметку выше.
   Спрятанный элемент играет так же, как показанный. */
.km-audio__el { display: none; }

/* Иконка в кружке */
.km-icon-circle {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--km-peach);
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  color: var(--km-accent);
}
.km-icon-circle--lg { width: 42px; height: 42px; }
/* Знак задаётся здесь, а не остаётся при шестнадцати из разметки: кружок
   тут 34, и знак в шестнадцать сидел в нём точкой. Та же правка, что
   у строки узла, и то же решение. */
.km-icon-circle svg { width: 28px; height: 28px; }
.km-icon-circle--lg svg { width: 36px; height: 36px; }
.km-icon-circle--neutral { background: #F1F4F8; color: var(--km-text-muted); }
.km-icon-circle--accent { background: var(--km-accent); color: #fff; }
/* Открытый и нетронутый — пустой кружок с обводкой, как у строки узла
   (`km-node-state--open`). Серый здесь читался бы «закрыт»: на настоящем
   курсе таких модулей два из шести, и оба выглядели бы запертыми. */
.km-icon-circle--open { background: transparent; border: 1.3px solid #C9D3DE; color: var(--km-text-secondary); }
.km-icon-circle svg { display: block; }

/* Курсанты: стопка кружков слева, счёт справа — так в макете страницы курса.
   Заголовка у карточки нет, строка счёта его и заменяет. */
.km-peers { display: flex; align-items: center; gap: 12px; }
.km-peers > .km-avatars { flex: none; }

/* ССЫЛКИ ПРАВКИ НА ФРОНТЕ. Раздел 12.3.
 *
 * Видит их только администратор, и потому строка неяркая: она служебная
 * и не должна спорить с тем, ради чего человек пришёл. Ученик её не видит
 * вовсе — решение принято на сервере, а не спрятано классом.
 *
 * Разделитель между ссылками — точкой через `::after` у каждой, кроме
 * последней: без пустых `<span>` в разметке. Не `::before` у соседа:
 * точка внутри следующего пункта уезжала с ним при переносе, и на телефоне
 * вторая строка начиналась с точки (задача Алены 12.10.2026: «переносить
 * целыми пунктами — точка остаётся в конце строки, новая строка начинается
 * со слова»). Держит общая мерка стендов в `editLine()`. */
.km-editlinks {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  margin: 0;
  font-size: 13px;
  color: var(--km-text-muted);
}
.km-editlinks__label { color: var(--km-text-muted); }
.km-editlinks__item { color: var(--km-text-secondary); text-decoration: none; }
.km-editlinks__item:hover { color: var(--km-accent); }
.km-editlinks__item:not(:last-child)::after {
  content: '\00B7';
  margin-left: 10px;
  color: var(--km-text-muted);
}

/* ПЕРЕЧЕНЬ «КУРС ВКЛЮЧАЕТ» — ЗНАК ГОЛЫЙ, КАК В ДЕРЕВЕ.
 *
 * Правка 19 августа 2026 по находке человека: карточка отстала от нового
 * вида дерева на целое решение. Кружки под знаками сняли 19 августа
 * (`km-node-state`), а здесь остался `km-icon-circle` — персиковая заливка
 * 34 пикселя со знаком 28. Рядом с деревом, где знак 19 и голый, карточка
 * читалась как из другой системы.
 *
 * Заливка несла состояние, а в перечне состояния нет вовсе: строка
 * называет вид узлов, а не узел. Кружок отвечал на вопрос, которого
 * здесь не задают.
 *
 * Размер и ритм взяты у карточки дерева одним числом (`--km-glyph`)
 * и одним зазором: обе читаются одной системой, а не «похоже».
 *
 * `km-icon-circle` при этом жив и не тронут — он про знак В КРУЖКЕ,
 * и такой знак ещё понадобится. Просто здесь его не нужно. */
.km-kit { display: flex; flex-direction: column; gap: 10px; --km-node-glyph: var(--km-glyph); }
.km-kit__glyph {
  width: var(--km-node-glyph);
  height: var(--km-node-glyph);
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--km-accent);
}
.km-kit__glyph svg { display: block; width: var(--km-node-glyph); height: var(--km-node-glyph); }
/* Закрепления толщины здесь БОЛЬШЕ НЕТ, и это половина смены набора
   29 августа 2026. Разбор — у знака дерева ниже, в одном месте. */

/* Перечень КАРТОЧКАМИ — продающая страница.
 *
 * В сайдбаре участника колонка верна: там 320 пикселей ширины и вертикаль
 * единственная возможная. На продающей странице перечень идёт во всю
 * ширину.
 *
 * ЗДЕСЬ СТОЯЛ `--row`: одна белая плашка на всю ширину, внутри пары
 * «знак + число» в строку. Воздуха выходило больше, чем содержимого,
 * и правки просил человек. Макет `course-page-guest-v2.html` рисует
 * три отдельные карточки в ряд: знак в тёплом квадрате, число крупно,
 * под ним строка пояснения.
 *
 * Модификатор, а не второй компонент: строки те же, знак тот же, меняется
 * раскладка и подача. Прежний `--row` снят целиком — его звало ровно одно
 * место, и два способа сказать «перечень на продающей» разошлись бы молча.
 *
 * ЧИСЛА ИЗ МАКЕТА, и где они разошлись с системой — сказано вслух:
 *   сетка 3 × gap 16      — как в макете;
 *   карточка 22px 24px    — как в макете; рамка, радиус и тень токенами;
 *   квадрат знака 40×40   — как в макете; радиус 12 у макета свой,
 *                           между `--km-radius-control` (10)
 *                           и `--km-radius-card` (16) — взят макетный;
 *   число 22px            — как в макете; в шкале заголовков такого нет
 *                           (20 и 24), и заводить шестую ступень ради
 *                           одного места дороже, чем написать здесь;
 *   пояснение 14px        — у макета 14,5; половин пикселя шкала не знает,
 *                           взято 14 (`--km-text-secondary` того же кегля).
 */
.km-kit--cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.km-kit--cards .km-kit__item {
  align-items: flex-start;
  gap: 14px;
  padding: 22px 24px;
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-card);
  box-shadow: var(--km-shadow-card);
}

/* Знак в тёплом квадрате — только в карточках.
   В сайдбаре участника он голый, и накрой это правило базовый класс,
   переоделся бы и он. */
.km-kit--cards .km-kit__glyph {
  width: 40px;
  height: 40px;
  border-radius: 12px;
  background: var(--km-warm-bg);
}

.km-kit__item { display: flex; align-items: center; gap: 11px; }
.km-kit__text { font-size: 14px; line-height: 1.4; }

/* Число и пояснение под ним. Столбик, чтобы `margin` не складывался
   с зазором: расстояния задаёт `gap`, а не поля абзацев. */
.km-kit__lines { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.km-kit__value { font-family: var(--km-font-display); font-size: 22px; font-weight: 700; line-height: 1.2; }
.km-kit__note { font-size: 14px; line-height: 1.5; color: var(--km-text-secondary); }

/* На узком — в столбик: три карточки по 116 пикселей не читаются.
   Порог 900 тот же, что у `km-grid-3`: сетки рядом и ломаться обязаны
   вместе, иначе на планшете одна секция в ряд, другая в столбик. */
@media (max-width: 900px) {
  .km-kit--cards { grid-template-columns: 1fr; }
}

/* ВКЛАДКА «ПРОГРЕСС» — ПО ВИДУ СНИППЕТА WPCode 167709411317960 (задача Алены
   2 октября 2026; прежний вид 9.30 снят). Одна карточка, блоки в порядке
   сниппета и с его плотностью: полоса, три плитки, столбики с осями,
   «Выполненные задания», «Ещё не заполнено» по видам, «Достижения». Цвета —
   токены системы на месте цветов сниппета: плитки лиловая, «сделано»
   и тёплая; метки видов — своим цветом у девяти видов сниппета.
   Под курсором меняется только цвет: ничего не двигается. */
.km-ptab { display: flex; flex-direction: column; gap: 24px; }
/* Блок вкладки и список «Ещё не заполнено»: без `min-width: 0` длинное название формы распёрло бы столбец. */
.km-ptab__part,
.km-ptab__todo { min-width: 0; }
.km-ptab__stats { display: flex; flex-wrap: wrap; gap: 14px; }
.km-ptab__stat {
  flex: 1;
  min-width: 110px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 16px 20px;
  border-radius: 12px;
  background: var(--km-lilac-bg);
}
.km-ptab__number { font-size: 26px; font-weight: 700; line-height: 1; color: var(--km-brand-navy); }
.km-ptab__of { font-size: 14px; font-weight: 400; }
.km-ptab__caption { font-size: 12px; color: var(--km-text-secondary); }
.km-ptab__stat--forms { background: var(--km-done-bg); }
.km-ptab__stat--forms .km-ptab__number { color: var(--km-done); }
.km-ptab__stat--lessons { background: var(--km-warn-bg); }
.km-ptab__stat--lessons .km-ptab__number { color: var(--km-warn-text); }

/* Подпись блока — мелкими заглавными, как `.km-slabel` сниппета. */
.km-ptab__label {
  margin: 0 0 12px;
  font-size: 12px;
  font-weight: 600;
  color: var(--km-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.km-ptab__since { margin: -4px 0 8px; font-size: 13px; color: var(--km-text-secondary); }

/* Столбики — в рамке, как у сниппета; оси и сетка — светлые. Рисуются
   в пикселях своей ширины (`course.js`), растягивать их нельзя: исказились
   бы буквы подписей. */
.km-ptab__chart { padding: 18px 20px; border: 1px solid var(--km-border); border-radius: 12px; }
.km-chart { width: 100%; }
.km-chart__svg { display: block; max-width: 100%; height: auto; }
.km-chart__grid { stroke: var(--km-border-soft); stroke-width: 1; }
.km-chart__tick { font-size: 10px; fill: var(--km-text-muted); }
.km-chart__bar { fill: var(--km-peach); stroke: var(--km-accent); stroke-width: 1; }

/* Метка вида — пилюлей своего цвета, как у сниппета; без своего — лиловая. */
.km-ptab__tag {
  flex: none;
  padding: 2px 9px;
  border-radius: 20px;
  font-size: 11px;
  font-weight: 500;
  white-space: nowrap;
  color: var(--km-brand-navy);
  background: var(--km-lilac-line);
}
.km-ptab__tag--diary { color: #1A5276; background: #E8F4FD; }
.km-ptab__tag--homework { color: #1E8449; background: #E9F7EF; }
.km-ptab__tag--reflection { color: #6C3483; background: #F5EEF8; }
.km-ptab__tag--checklist { color: #9A7D0A; background: #FEF9E7; }
.km-ptab__tag--plan { color: #1A6644; background: #E8F8F0; }
.km-ptab__tag--trainer { color: #A04000; background: #FDF2E9; }
.km-ptab__tag--diagnostics { color: #1A3A6B; background: #EAF2FF; }
.km-ptab__tag--tracker { color: #0E6655; background: #E8F8F5; }
.km-ptab__tag--marathon { color: #922B21; background: #FDEDEC; }

/* «Выполненные задания» — строка вида, как заголовок группы сниппета:
   метка, имя вида, число, стрелка. Ссылка в «Мои работы»: цвет
   и подчёркивание гасятся двумя классами — у темы ссылки содержимого
   покрашены селектором сильнее одиночного класса. */
.km-ptab__kinds { display: flex; flex-direction: column; }
.km-ptab .km-ptab__kind-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 8px;
  border-radius: 8px;
  color: var(--km-text);
  text-decoration: none;
}
.km-ptab .km-ptab__kind-row + .km-ptab__kind-row { border-top: 1px solid var(--km-border-soft); }
.km-ptab a.km-ptab__kind-row:hover { background: var(--km-lilac-bg); color: var(--km-text); text-decoration: none; }
/* Страницы «Мои работы» нет — строка текстом: не нажимается и не подсвечивается. */
.km-ptab .km-ptab__kind-row--still { cursor: default; }
.km-ptab a.km-ptab__kind-row:hover .km-ptab__kind-name { color: var(--km-accent); }
.km-ptab__kind-name { font-size: 13px; font-weight: 600; }
.km-ptab__count { font-size: 12px; color: var(--km-text-muted); background: var(--km-border-soft); border-radius: 20px; padding: 1px 8px; }
.km-ptab__arrow { margin-left: auto; font-size: 16px; font-weight: 600; line-height: 1; color: var(--km-accent); }

/* «Ещё не заполнено» — подписью вида над строками, как у сниппета;
   строка — метка, название, «Заполнить» пилюлей. */
.km-ptab__kind {
  margin: 0;
  padding: 14px 0 6px;
  border-bottom: 1px solid var(--km-border-soft);
  font-size: 11px;
  font-weight: 600;
  color: var(--km-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.km-ptab__kind:first-child { padding-top: 0; }
.km-ptab__row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 0;
  border-bottom: 1px solid var(--km-border-soft);
}
.km-ptab__name { flex: 1; min-width: 0; font-size: 14px; color: var(--km-text); }
.km-ptab .km-ptab__fill {
  flex: none;
  padding: 4px 14px;
  border-radius: 20px;
  font-size: 12px;
  color: #fff;
  background: var(--km-accent);
  text-decoration: none;
  white-space: nowrap;
}
.km-ptab .km-ptab__fill:hover { color: #fff; background: var(--km-warm-text-strong); text-decoration: none; }
.km-ptab__note { margin: 10px 0 0; font-size: 12px; color: var(--km-text-muted); }

/* Достижения — плашки с картинкой кругом и звездой, как у сниппета. */
.km-ptab__awards { display: flex; flex-wrap: wrap; gap: 10px; }
.km-ptab__award {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  border: 1px solid var(--km-warm-border);
  border-radius: 10px;
  font-size: 14px;
  color: var(--km-warm-text-strong);
  background: var(--km-warm-bg);
}
.km-ptab__award img { width: 44px; height: 44px; border-radius: 50%; object-fit: cover; flex: none; }

/* Вкладка «Рейтинг» (spec «Вкладка «Рейтинг»», 1 октября 2026).

   Строка — место, фото, имя с раскладом, баллы. Как во вкладке сниппета v2,
   но на токенах системы. Первые три подсвечены тёплой подложкой; своя
   строка — зелёной рамкой «сделано». Под курсором ничего не двигается:
   меняется только цвет имени. */
.km-rating__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
}
.km-rating {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.km-rating__row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 10px 14px;
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-control);
}
.km-rating__row--top { background: var(--km-warm-bg); border-color: var(--km-warm-border); }
.km-rating__row--me { border-color: var(--km-done); box-shadow: inset 0 0 0 1px var(--km-done); }
.km-rating__place {
  flex: none;
  min-width: 32px;
  margin-top: 5px;
  text-align: center;
  line-height: 1;
  font-size: 18px;
  font-weight: 700;
  color: var(--km-accent);
}
.km-rating__row--top .km-rating__place { font-size: 24px; }

/*
 * Рейтинг по звёздам — вкладка «Рейтинг» курса со звёздами для всех («Звёзды курса» 1.28, 6.10; макеты
 * `design/reyting-vkladka-v1.dc.html`, `reyting-telefon-v1.dc.html`). Переключатель «Общий» / «Прорыв недели»
 * плашками на светлой подложке, выбор потока у команды справа; список — карточкой: места 1–3 кружками (золото,
 * серебро, бронза), дальше цифрой; своя строка — тёплой подложкой с «· вы»; вне десятки — «···» и своя строка
 * с «До 10-го места». Рейтинг по баллам (`km-rating`) не меняется. Кнопки переключателя — свои во всех состояниях:
 * тема красит `button` по имени элемента.
 */
.km-toprank__bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; }
.km-toprank__seg { display: inline-flex; gap: 4px; padding: 4px; border-radius: 12px; background: var(--km-track); }
.km-toprank button.km-toprank__tab,
.km-toprank button.km-toprank__tab:hover,
.km-toprank button.km-toprank__tab:focus,
.km-toprank button.km-toprank__tab:active {
  height: 40px;
  min-height: 0;
  margin: 0;
  padding: 0 18px;
  border: 0;
  border-radius: 9px;
  background: transparent;
  box-shadow: none;
  color: var(--km-text-secondary);
  font-family: var(--km-font);
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  cursor: pointer;
}
.km-toprank button.km-toprank__tab:hover { color: var(--km-text); }
.km-toprank button.km-toprank__tab.is-active,
.km-toprank button.km-toprank__tab.is-active:hover,
.km-toprank button.km-toprank__tab.is-active:focus,
.km-toprank button.km-toprank__tab.is-active:active { background: #fff; color: var(--km-text); box-shadow: 0 1px 4px rgba(63, 76, 92, 0.14); }
.km-toprank button.km-toprank__tab:focus-visible { outline: 2px solid var(--km-accent); outline-offset: 2px; }
.km-toprank__choice { display: inline-flex; align-items: center; gap: 10px; min-width: 0; max-width: 100%; font-size: 14px; color: var(--km-text-secondary); }
.km-toprank__choice[hidden] { display: none; }
.km-toprank .km-toprank__choice select.km-select { flex: 0 1 auto; width: auto; min-width: 0; max-width: 100%; height: 40px; }
.km-toprank__card { display: flex; flex-direction: column; gap: 6px; padding: 24px 24px 18px; border: 1px solid var(--km-border); border-radius: 16px; background: #fff; box-shadow: 0 2px 12px rgba(63, 76, 92, 0.06); }
.km-toprank__card[hidden] { display: none; }
h2.km-toprank__title { margin: 0; font-family: var(--km-font-display); font-size: 24px; font-weight: 700; line-height: 1.25; color: var(--km-text); text-transform: none; }
p.km-toprank__lead { margin: 0 0 12px; font-size: 14px; line-height: 1.6; color: var(--km-text-secondary); }
ol.km-toprank__list { display: flex; flex-direction: column; margin: 0; padding: 0; list-style: none; }
ol.km-toprank__list[hidden] { display: none; }
.km-toprank__row { display: flex; align-items: center; gap: 14px; margin: 0; padding: 10px 14px; border: 1px solid transparent; border-bottom-color: var(--km-border-soft); border-radius: 12px; }
.km-toprank__row--me { border-color: var(--km-warm-border); background: var(--km-warm-bg); }
.km-toprank__place { flex: none; width: 34px; font-family: var(--km-font-display); font-size: 18px; font-weight: 700; line-height: 1; text-align: center; color: var(--km-text-muted); }
.km-toprank__place--1,
.km-toprank__place--2,
.km-toprank__place--3 { display: flex; align-items: center; justify-content: center; height: 34px; border-radius: 50%; font-size: 17px; }
.km-toprank__place--1 { background: var(--km-medal-gold); color: var(--km-medal-gold-ink); }
.km-toprank__place--2 { background: var(--km-medal-silver); color: var(--km-text); }
.km-toprank__place--3 { background: var(--km-medal-bronze); color: var(--km-medal-bronze-ink); }
.km-toprank__row--alone .km-toprank__place { color: var(--km-warm-text-strong); }
a.km-toprank__face,
span.km-toprank__face { flex: none; display: block; width: 40px; height: 40px; border-radius: 50%; text-decoration: none; }
img.km-toprank__ava,
span.km-toprank__ava { display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; border-radius: 50%; object-fit: cover; font-size: 14px; font-weight: 700; line-height: 1; }
.km-toprank__ava--c1 { background: var(--km-ava-1); color: var(--km-ava-1-ink); }
.km-toprank__ava--c2 { background: var(--km-ava-2); color: var(--km-ava-2-ink); }
.km-toprank__ava--c3 { background: var(--km-ava-3); color: var(--km-ava-3-ink); }
.km-toprank__ava--c4 { background: var(--km-ava-4); color: var(--km-ava-4-ink); }
.km-toprank__ava--c5 { background: var(--km-ava-5); color: var(--km-ava-5-ink); }
.km-toprank__who { flex: 1; min-width: 0; overflow: hidden; font-size: 15px; font-weight: 600; line-height: 1.35; white-space: nowrap; text-overflow: ellipsis; color: var(--km-text); }
a.km-toprank__name,
a.km-toprank__name:visited,
a.km-toprank__name:focus,
span.km-toprank__name { color: var(--km-text); text-decoration: none; }
a.km-toprank__name:hover { color: var(--km-text); text-decoration: underline; text-underline-offset: 3px; }
.km-toprank__you { font-weight: 700; color: var(--km-warm-text-strong); }
.km-toprank__row--alone .km-toprank__who { display: flex; flex-wrap: wrap; column-gap: 0; row-gap: 1px; font-weight: 700; white-space: normal; }
.km-toprank__row--alone .km-toprank__you { color: var(--km-text); }
/* Буквы своей строки под «···» — персиковые, как на макете, а не по кругу цветов по месту. */
.km-toprank__row--alone span.km-toprank__ava { background: var(--km-peach); color: var(--km-warm-text-strong); }
.km-toprank__gap { flex-basis: 100%; font-size: 13px; font-weight: 400; color: var(--km-warm-text-strong); }
.km-toprank__value { flex: none; display: inline-flex; align-items: center; gap: 5px; font-family: var(--km-font-display); font-size: 20px; font-weight: 700; line-height: 1; color: var(--km-warm-text-strong); }
.km-toprank__star { flex: none; width: 18px; height: 18px; }
.km-toprank__dots { padding: 6px 0 4px; font-size: 18px; line-height: 1; letter-spacing: 4px; text-align: center; color: var(--km-rank-dots); }
.km-toprank__dots[hidden],
.km-toprank__mine[hidden],
p.km-toprank__zero[hidden],
p.km-toprank__empty[hidden] { display: none; }
.km-toprank__row--alone { padding: 12px 14px; }
p.km-toprank__zero,
p.km-toprank__empty { margin: 4px 0 0; font-size: 14px; line-height: 1.6; color: var(--km-text-secondary); }
p.km-toprank__foot { margin: 14px 0 0; padding-top: 14px; border-top: 1px solid var(--km-border-soft); font-size: 13px; line-height: 1.6; color: var(--km-text-secondary); }
a.km-toprank__link,
a.km-toprank__link:visited,
a.km-toprank__link:focus { color: var(--km-accent); font-weight: 600; text-decoration: none; }
a.km-toprank__link:hover { color: var(--km-accent); text-decoration: underline; text-underline-offset: 3px; }
@media (max-width: 640px) {
  .km-toprank__seg { display: flex; width: 100%; }
  /* Выбор потока у команды — под переключателем, подпись над списком, список во всю ширину: строка
     «Поток «Сентябрь 2026» · набор» в теме сайта шире места рядом с подписью (снимок боевого 15.10.2026). */
  .km-toprank__choice { flex-direction: column; align-items: stretch; gap: 6px; width: 100%; }
  .km-toprank .km-toprank__choice select.km-select { width: 100%; }
  .km-toprank button.km-toprank__tab,
  .km-toprank button.km-toprank__tab:hover,
  .km-toprank button.km-toprank__tab:focus,
  .km-toprank button.km-toprank__tab:active { flex: 1; height: 44px; padding: 0 10px; }
  .km-toprank__card { gap: 4px; padding: 18px 14px 14px; }
  h2.km-toprank__title { margin: 0 4px; font-size: 21px; }
  p.km-toprank__lead { margin: 0 4px 10px; font-size: 13px; line-height: 1.55; }
  .km-toprank__row { gap: 10px; padding: 8px 10px; }
  .km-toprank__row--alone { padding: 10px; }
  .km-toprank__place { width: 28px; font-size: 16px; }
  .km-toprank__place--1,
  .km-toprank__place--2,
  .km-toprank__place--3 { height: 28px; font-size: 15px; }
  .km-toprank__row--alone .km-toprank__place { font-size: 17px; }
  a.km-toprank__face,
  span.km-toprank__face,
  img.km-toprank__ava,
  span.km-toprank__ava { width: 32px; height: 32px; }
  span.km-toprank__ava { font-size: 12px; }
  .km-toprank__who { font-size: 14px; }
  .km-toprank__gap { font-size: 12px; }
  .km-toprank__value { gap: 4px; font-size: 18px; }
  .km-toprank__star { width: 16px; height: 16px; }
  .km-toprank__dots { padding: 4px 0; font-size: 16px; }
}
/* МЕСТО — ПО ВЕРХУ ИМЕНИ. Правило Алены 2 октября 2026: большая цифра рядом
   с текстом — по верхнему краю первой строки. Ряд стоял по центру, и «4»
   висело на 11 px ниже верха имени. Теперь ряд — по верху (`.km-rating__row`),
   фото и баллы — по центру, как были; место — строкой в свой кегль и сдвигом
   5 px (`.km-rating__place`):
   цифры разной высоты дают ±0,4 px. Медали первых трёх — не цифры и мерку
   не проходят, но стоят на той же линии (9,2 px — их высота знака). */
.km-rating__photo,
.km-rating__score { align-self: center; }
.km-rating__row--top .km-rating__place { margin-top: 9.2px; }
.km-rating__photo {
  flex: none;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--km-border-soft);
}
/* Своего фото нет — буквы имени на той же подложке (слово Алены 17.10.2026: запасного фото BuddyBoss нет). */
span.km-rating__photo {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  color: var(--km-text-secondary);
}
.km-rating__who { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.km-rating .km-rating__name {
  font-weight: 600;
  color: var(--km-text);
  text-decoration: none;
  overflow-wrap: anywhere;
}
.km-rating .km-rating__name:hover { color: var(--km-accent); text-decoration: none; }
.km-rating__parts { font-size: 13px; color: var(--km-text-secondary); overflow-wrap: anywhere; }
.km-rating__score { flex: none; font-size: 20px; font-weight: 700; color: var(--km-accent); white-space: nowrap; }
.km-rating__points { font-size: 12px; font-weight: 400; color: var(--km-text-muted); }
/* Выбор потока у команды: ширина по содержимому, на узком — во всю строку. */
.km-rating__choice { align-self: flex-start; max-width: 420px; }
.km-rating__me { margin: 0; font-size: 13px; font-weight: 600; color: var(--km-done); text-transform: uppercase; letter-spacing: 0.04em; }

@media (max-width: 480px) {
  .km-rating__choice { max-width: none; width: 100%; }
  .km-rating__row { padding: 10px; gap: 10px; }
  .km-rating__photo { width: 32px; height: 32px; }
  .km-rating__score { font-size: 17px; }
}

/* «Все мои работы по курсу →» под строками видов. Двумя классами —
   по той же причине, что строки выше: тема красит ссылки содержимого
   сильнее одиночного класса. Под курсором меняется только цвет. */
.km-card .km-filled__all {
  align-self: flex-start;
  font-size: 14px;
  color: var(--km-accent);
  text-decoration: none;
}
.km-card .km-filled__all:hover { color: var(--km-warm-text-strong); text-decoration: none; }
/* «Показать ещё N форм» под списком вкладки «Прогресс». Слово Алены
   17 сентября 2026: пять форм, дальше кнопка — приём «Моих работ». */
.km-forms-more { padding: 10px 0 4px; }

/* Календарь занятий и форм — сетка месяца. Задача 9.29.

   Отдельная от `.km-daygrid` семья намеренно: трекер практик это ПУСТОЕ
   МЕСТО под чужой блок, у него нет ни чисел, ни состояний, ни нажатия.
   Свести их в один класс значило бы, что первая же правка живого календаря
   поедет в мёртвую сетку — и наоборот.

   Насыщенность выражена ступенями `data-lms-level`, а не посчитанной
   прозрачностью: правило 13 запрещает оформление по месту, а ступеней
   ровно четыре и они здесь названы. Само число ступени считает браузер
   от самого плотного дня месяца — это данные, как `value` у `<progress>`. */
/* Блок целиком: сетка стоит ближе к своей шапке, чем карточки друг к другу.
   Класс не декоративный — без него `km-stack` разносит шапку, дни недели
   и сетку на общий отступ, и месяц читается как три разных блока. */
.km-month {
  --km-stack-gap: 10px;
}
.km-month__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
/* Месяц — СОСТОЯНИЕ блока, а не его имя, и потому набран не как подпись
   карточки: капслок с разрядкой у `.km-section-title` занят названием
   («ТРЕКЕР КУРСА»), и второй такой строкой месяц спорил бы с ним за роль
   заголовка. Здесь обычное начертание, крупнее подписи и тем же цветом,
   что основной текст. */
.km-month__title {
  margin: 0;
  text-align: center;
  flex: 1;
  font-size: 14px;
  font-weight: 600;
  color: var(--km-text);
}
.km-month__nav {
  font-family: inherit;
  font-size: 15px;
  line-height: 1;
  color: var(--km-text-secondary);
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-control);
  padding: 6px 10px;
  cursor: pointer;
  flex: none;
}
.km-month__nav:hover:not(:disabled) {
  color: var(--km-accent);
  border-color: var(--km-warm-border);
}
/* Выключенная стрелка не притворяется живой: вперёд листать некуда,
   будущей активности не бывает. Причина сказана подсказкой на самой
   кнопке — выключенное без причины читается как поломка. */
.km-month__nav:disabled {
  color: var(--km-text-muted);
  background: var(--km-page);
  cursor: default;
}
.km-month__dows,
.km-month__grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
}
.km-month__dows {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--km-text-muted);
  text-align: center;
}
.km-month__cell {
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  line-height: 1;
  border-radius: 8px;
  background: var(--km-page);
  border: 1px solid var(--km-border-soft);
  color: var(--km-text-muted);
}
/* Пустое место до первого числа месяца: клетки нет вовсе, а не пустая. */
.km-month__cell--void {
  background: none;
  border-color: transparent;
}
/* Четыре ступени насыщенности. Тёплая семья та же, что у всего живого
   в системе: белый — ничего, персиковый — много. */
.km-month__cell[data-lms-level="1"] {
  background: var(--km-warm-bg);
  border-color: var(--km-warm-bg);
  color: var(--km-warm-text);
}
.km-month__cell[data-lms-level="2"] {
  background: var(--km-peach);
  border-color: var(--km-peach);
  color: var(--km-warm-text-strong);
}
.km-month__cell[data-lms-level="3"] {
  background: var(--km-accent-light);
  border-color: var(--km-accent-light);
  color: var(--km-surface);
}
.km-month__cell[data-lms-level="4"] {
  background: var(--km-accent);
  border-color: var(--km-accent);
  color: var(--km-surface);
}
/* Сегодня — рамкой, а не заливкой: заливка спорила бы с насыщенностью
   и меняла бы её смысл на «сегодня плотный день». */
.km-month__cell--today {
  border-color: var(--km-accent);
  font-weight: 700;
}

/* Трекер практик — сетка по дням месяца.

   Клетки пустые и не нажимаются: механика приходит блоком Gravity Forms
   (5.6), здесь только место. Курсора-руки поэтому нет — он обещал бы
   нажатие, которого не будет.

   **НА СТРАНИЦЕ КУРСА ЭТОГО БЛОКА БОЛЬШЕ НЕТ** — решение человека
   25 августа 2026: там встал живой трекер курса (`.km-month`), а две
   сетки подряд были нашим дублем. Классы оставлены намеренно, и это
   не мёртвый код: их потребитель — макет `design/course-page-member.html`
   и трекер бесплатных курсов, к которому вернёмся. Убирать их вместе
   с блоком значило бы вычеркнуть одобренное макетом. */
.km-daygrid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 6px;
}
.km-daygrid__cell {
  aspect-ratio: 1;
  border-radius: 9px;
  background: var(--km-page);
  border: 1px solid var(--km-border);
}

/* Аватары стопкой.

   Один класс на два вида: `span` — кружок-знак, `img` — настоящее лицо
   курсанта (12.2). Второго класса нет намеренно: кружок у них один и тот же,
   а вся разница в том, есть внутри картинка или нет.

   `object-fit` обязателен: фотографии профиля бывают любых пропорций,
   и без него портрет 3:4 съезжает в овал. `background` при этом остаётся
   и работает подложкой, пока картинка грузится, — и остаётся кружком,
   если она не загрузится вовсе. */
.km-avatars { display: flex; }
.km-avatars__item {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 2px solid var(--km-surface);
  background: var(--km-warm-border);
  object-fit: cover;
}
.km-avatars__item + .km-avatars__item { margin-left: -11px; }

/* Дата кружком — эфиры */
.km-date-chip {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--km-peach);
  color: #A8592F;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  flex: none;
  line-height: 1;
}
.km-date-chip__day { font-size: 16px; font-weight: 700; }
.km-date-chip__month { font-size: 9px; letter-spacing: 0.04em; }

/* Дерево курса.
 *
 * Базовая строка — ЭТО ТОПИК: он самый частый (шестьдесят на боевом курсе
 * против двадцати занятий), и черта снизу разделяет топики внутри карточки.
 * Строка занятия перебивает её ниже — у неё свои поля и черты нет вовсе. */
/* ЗНАКИ И ПОДПИСИ — ПО ВЕРХУ ПЕРВОЙ СТРОКИ НАЗВАНИЯ, а не по центру строки. Слово Алены 14.10.2026 (звёзды курса
   1.22, раздел 6): у «1.1 Энергетическая система человека» в колонке занятия стрелка и «12 из 13» стояли посередине
   двух строк. Правило на всех строках, которые переносятся: колонка занятия, карта курса, блоки звёзд. Держит общая
   мерка стендов `stand.firstLines()` — она сама находит такие строки. */
.km-node {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: 10px 0;
  border-bottom: 1px solid var(--km-border-soft);
  /* Высота первой строки названия — по ней встают подписи справа и плашки (слово Алены 14.10.2026, 1.511.0). Числа —
     те же, что у кегля названия (`.km-node__title` 15 × 1,35, лист 14, колонка 14 и 13); разъедутся — покраснеет
     мерка стендов `firstLines` и мерка высоты строки трансляции на стенде карты. */
  --km-node-line: calc(15px * 1.35);
}
.km-node:last-child { border-bottom: none; }

/* СТРОКА ЗАНЯТИЯ — ШАПКА КАРТОЧКИ. Макет v3: поля 14 и 18, черты нет.
 *
 * Селектор двойной, и оба нужны: у занятия с топиками строка лежит
 * в `<summary>` складки, у занятия без топиков — прямо в карточке.
 * Написать один — и половина занятий останется с полями топика, причём
 * та половина, которая на боевом реже (два занятия из двадцати).
 *
 * Скругление снимается: подложку текущего обрезает сама карточка своим
 * `overflow: hidden`, а собственный радиус строки дал бы скруглённый
 * прямоугольник внутри скруглённого — тот самый вид «полосы с обрывами»,
 * от которого отказались. Специфичность здесь (0,2,0) против (0,1,0)
 * у `km-node--current`, так что порядок в файле роли не играет. */
.km-tree__card > .km-node,
.km-tree__fold-head > .km-node {
  padding: 14px 18px;
  gap: 12px;
  border-bottom: none;
  border-radius: 0;
}

/* ЛЕСТНИЦА УРОВНЕЙ. Правка вёрстки 1, решение человека 8 августа 2026.
 *
 * Модуль 20/700 → занятие 17/600 → лист 14/400 вторичным цветом. До правки
 * занятие и лист были одним кеглем и одним весом, и уровень выражал только
 * отступ: на 119 строках подряд иерархия не читалась вовсе.
 *
 * Уровень берётся из РАЗМЕТКИ, а не из класса-модификатора: лист третьего
 * уровня — тот, что лежит в `.km-tree__topics`, и другого способа туда
 * попасть нет. Заведи мы `km-node--topic`, у одного и того же факта стало бы
 * два написания — положение в дереве и класс, — и однажды они разошлись бы
 * молча.
 *
 * Третьего признака у листа нет намеренно (решение человека): справа
 * у него уже стоит тип словами, а фон развёл бы два узла одного уровня
 * так, будто они с разных. */
.km-node__title { flex: 1; min-width: 0; font-size: 15px; font-weight: 600; line-height: 1.35; }
.km-node--done .km-node__title { color: var(--km-text-secondary); }
.km-node--current .km-node__title { font-weight: 700; }
.km-node--locked .km-node__title { color: var(--km-text-muted); }
/* Причина закрытия — под названием, а не под знаком: 49 это поле карточки
   (18) плюс знак (19) плюс зазор строки (12). Числа сложены здесь потому,
   что все три уже объявлены выше и разъехались бы поодиночке.

   ДЕРЕВО КУРСАНТА ЭТИМ КЛАССОМ БОЛЬШЕ НЕ ПОЛЬЗУЕТСЯ — с 27 августа 2026
   причина стоит в самой строке (`km-node__why`). Здесь остались строки
   админки: корзина (`trash.js`) и предпросмотр в редакторе узла. */
.km-node__reason { font-size: 13px; line-height: 1.5; color: var(--km-text-muted); padding: 0 18px 12px 49px; }

/* ПРИЧИНА ЗАКРЫТИЯ — ПРАВЫЙ СТОЛБЕЦ СТРОКИ. Правка 27 августа 2026,
   макет `design/course-map-locked-v1.html`.

   Отдельным абзацем под строкой она растила карточку закрытого занятия
   вдвое против открытого — 108 пикселей против 50 на боевом Практикуме,
   — и под датой оставалось пустое место, читавшееся как «здесь что-то
   будет». Закрытое и открытое обязаны быть одной высоты: различают их
   цвет и замок, а не размер.

   Приглушённый цвет, а не тёплый: рядом в том же столбце стоят состояния
   (`km-node__state`), и они про то, что человеку **делать**. Причина про
   то, чего ждать, и спорить с ними за внимание ей незачем.

   Переносится по словам, а не `nowrap`: в отличие от «вы здесь» и «на
   6:24» причина бывает длинной — «Откроется, когда вы заполните «Отзыв
   о курсе»». Потолок ширины держит название читаемым: без него причина
   съедала бы строку до переноса по слову. */
.km-node__why {
  flex: none;
  max-width: 45%;
  font-size: 12px;
  line-height: 1.4;
  color: var(--km-text-muted);
  text-align: right;
}

/* Ссылка внутри причины остаётся ссылкой и в правом столбце. */
.km-node__why .km-link-out { color: inherit; }

/* ОДИН ДЕНЬ НА ВСЁ ЗАНЯТИЕ — СТРОКОЙ НАД ЧАСТЯМИ.
   Полоса цвета страницы внутри белой карточки: она про всё, что ниже,
   и потому лежит над ними, а не в одной из строк. */
.km-tree__when-all {
  margin: 2px 0 8px;
  padding: 7px 12px;
  border-radius: 9px;
  background: var(--km-page);
  font-size: 13px;
  line-height: 1.45;
  color: var(--km-text-muted);
}

/* И тогда строка самого занятия про день молчит, пока складка раскрыта:
   иначе один и тот же день стоял бы дважды, через восемь пикселей друг
   от друга. Свёрнутой складке он по-прежнему нужен — там его больше
   негде прочитать. */
.km-tree__fold--one-day[open] > .km-tree__fold-head .km-node__why { display: none; }

/* Третья ступень лестницы — лист внутри занятия: топик, практика, дневник,
   план, протокол. Правило одно на всех, потому что уровень у них общий:
   различает их знак в кружке и тип словами справа, а не кегль. */
.km-tree__topics .km-node__title { font-size: 14px; font-weight: 400; color: var(--km-text-secondary); }
.km-tree__topics .km-node { --km-node-line: calc(14px * 1.35); }

/* Размер знака — вторая ступень лестницы уровней: 19 у занятия, 16
   у топика, в колонке плеера 17 и 14. Число живёт переменной на дереве,
   а не в правиле знака: контейнер топиков объявляет своё, и лист получает
   его наследованием — объяви мы размер прямо у `.km-node-state`, лист
   унаследовал бы размер занятия.

   Парная переменная `--km-node-mark` снята вместе с `km-node__meta`:
   от неё считался отступ подписи, переносимой под название на узком
   экране, а подписи в правом столбце больше нет — там знаки и короткие
   слова, которые не переносятся. */
/* ЗНАК ГОЛЫЙ, БЕЗ КРУЖКА. Макет 19 августа 2026.
 *
 * Кружок снят: заливка и обводка несли состояние, а состояние переехало
 * вправо словом и галочкой. Оставленный, кружок отвечал бы на тот же
 * вопрос второй раз и слабее — персиковую заливку от прозрачной человек
 * не различал, о чём и был разбор.
 *
 * Размер знака 19 — из макета, и он же теперь размер всей метки: рамки
 * вокруг больше нет. Лестница уровней осталась на переменных, и третий
 * уровень по-прежнему мельче. */
.km-node-state {
  width: var(--km-node-glyph, 19px);
  height: var(--km-node-glyph, 19px);
  flex: none;
  /* Знак внутри кружка: цвет берётся отсюда через `currentColor`,
     и второго места, где решают цвет состояния, не заводится. */
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
}
.km-node-state svg { display: block; width: var(--km-node-glyph, 16px); height: var(--km-node-glyph, 16px); }

/* ЗАКРЕПЛЕНИЕ ТОЛЩИНЫ СНЯТО ВМЕСТЕ СО СМЕНОЙ НАБОРА, 29 августа 2026.
 *
 * Здесь стояло `vector-effect: non-scaling-stroke` на знаках дерева
 * и перечня, и стояло **правильно** — для прежнего набора. Те рисунки
 * жили в обрезанной рамке `3.5 3.5 13 13`, и без закрепления сжатая рамка
 * утолщала обводку вместе с рисунком: у галочки она уходила с полутора
 * пикселей на три, а у шапки модуля вылезала за кружок.
 *
 * Новый набор — Lucide и Tabler — рисован в рамке 24 со штрихом 2, и
 * закрепление здесь делает ровно ту беду, от которой защищало: 2 px
 * на любом размере. На 19 задумано 1,58, на 14 — 1,17; закреплённый
 * штрих был бы вдвое толще там, где знак мельче, то есть в колонке
 * плеера и у частей.
 *
 * Естественное деление даёт то, подо что рисовано: 1,33 px на шестнадцати.
 * Проверено измерением в браузере, а не расчётом на бумаге.
 *
 * Толщину и скругления задаёт сам `<svg>` (`window.lmsGlyph`), одним
 * написанием на весь набор: по фигурам их не пишут ни Lucide, ни Tabler,
 * и первый же добавленный знак приехал бы с чужой толщиной. */
/* Цвет знака — по состоянию, заливки нет ни у одного. */
/* Пройденный узел — зелёным «сделано», а не бледно-оранжевым.
 *
 * Решение Алены 13 сентября 2026: цвет один на весь проект, и карта здесь
 * вторая после страницы курса. Различать состояния цвет не перестаёт —
 * наоборот: «идёт» остался оранжевым, и теперь пройденное и текущее
 * отличаются не оттенком одного цвета, а разными. */
.km-node-state--done { color: var(--km-done); }
.km-node-state--locked { color: var(--km-text-muted); }
.km-node-state--current { color: var(--km-accent); }
/* Открытый и нетронутый — пустой кружок с обводкой. Цвет знака **обязан
   быть задан здесь**: у базового класса он белый (под заливку персиком
   и оранжевым), а тут подложки нет вовсе, и знак белым по светлому
   пропадал бы целиком. Найдено глазами после пункта 2: svg на месте,
   размер верный, а в кружке пусто. */
.km-node-state--open { color: var(--km-text-secondary); }

/* ПРАВЫЙ СТОЛБЕЦ. Порядок случаев решает `state()` в скрипте: место
   остановки, дата эфира, галочка, «вы здесь», пусто.

   Слова набраны ОДИНАКОВО — 12 пикселей тёплым, — и это макет v3.
   До него «на 6:24» было приглушённо-тёплым, «в среду, 19:00» серым,
   «вы здесь» полужирным тринадцатым: три вида у одного столбца, и разница
   между ними ничего не значила. Читается столбец как одно место, где
   написано, что с этой строкой сейчас. */
/* Плашки строки — поток и «по желанию» — одной группой (`course-map.js`).
   На широком группа для раскладки прозрачна: плашки стоят в строке, как
   стояли до неё. На узком она встаёт строкой под названием (ниже). */
.km-node__tags { display: contents; }

/* ПЛАШКА ПОТОКА И «ПО ЖЕЛАНИЮ» В СТРОКЕ ДЕРЕВА — НЕ ВЫШЕ СТРОКИ НАЗВАНИЯ. Слово Алены 14.10.2026: после 1.508.0
   («по первой строке») строку трансляции «распёрло» — плашка без своей высоты строки брала у темы 27 px и с полями
   выходила 37 px против 20 px названия; до 1.508.0 это прятало выравнивание по центру. Здесь: кегль 10 × 1,2 и поля
   3 px — 18 px, и серединой на середину первой строки названия. Строка трансляции в одну строку — той же высоты, что
   строка занятия (мерка стенда карты). */
.km-node .km-badge {
  line-height: 1.2;
  padding: 3px 8px;
  margin-top: calc( ( var( --km-node-line ) - 18px ) / 2 );
}

.km-node__state { flex: none; display: flex; align-items: center; }
.km-node__state--done { width: 18px; height: 18px; color: var(--km-done); }
.km-node__state--at,
.km-node__state--when,
.km-node__state--here,
.km-node__state--parts {
  font-size: 12px;
  /* Высота строки — ровно строка названия, а не унаследованная: у темы она 27 px, и подпись в 12 px вставала ниже
     названия и растила строку (подписи — по первой строке, слово Алены 14.10.2026). Буквы встают по середине той же
     строки, что название. */
  line-height: var(--km-node-line);
  color: var(--km-accent);
  white-space: nowrap;
}

/* ПРОШЕДШИЙ ЭФИР — ПРИГЛУШЁННЫМ, а не акцентом.
   Дефект найден человеком на боевом 10 сентября 2026.

   Оранжевый в правом столбце значит «это про сейчас»: место остановки,
   ближайший эфир, «вы здесь». Прошедшая дата не про сейчас — она про то,
   что уже было, и тем же цветом читалась как запланированная.

   Отличаться она обязана **от соседней строки того же столбца**, а не
   просто «быть серой»: рядом стоят оранжевые даты будущих эфиров,
   и на них признак и проверяется. */
.km-node__state--was { color: var(--km-text-muted); }

/* ТЕКУЩИЙ — ТЁПЛАЯ ПОДЛОЖКА ПО ШИРИНЕ КАРТОЧКИ.
 *
 * Раньше он различался только заливкой кружка, и человек его не находил:
 * ровно с этого начался разбор состояний. Подложка, оранжевый знак
 * и полужирное название — три признака вместо одного слабого.
 *
 * Скругление здесь про ТОПИК: он лежит внутри карточки с полями, и
 * подложка обязана быть прямоугольником со скруглением, а не полосой
 * от края до края. У строки занятия радиус снимается — её углы даёт
 * сама карточка. */
.km-node--current {
  background: var(--km-warm-bg);
  border-radius: 10px;
}
.km-node--current .km-node__title { font-weight: 700; }

/* Подложка топика выходит за колонку текста на 10 и ровно настолько же
   возвращает подбивкой: черты между топиками остаются на своих местах,
   а тёплый прямоугольник не липнет к буквам. Разъедься эти два числа —
   строка поедет вбок относительно соседей. */
.km-tree__topics .km-node--current {
  margin-left: -10px;
  margin-right: -10px;
  padding-left: 10px;
  padding-right: 10px;
}

/* У ПРОЙДЕННОГО НАЗВАНИЕ ПРИГЛУШЕНО: прочитанное уходит на второй план. */
.km-node--done .km-node__title { color: var(--km-text-muted); }

/* Админские таблицы */
/* Ширина в сто процентов — не косметика, а потолок.

   Без неё таблица берёт ширину по содержимому, и девять столбцов
   с неразрывными значениями вытолкнули страницу за край окна на семь
   пикселей. `overflow-x: auto` тут не спасает: он объявлен на самой
   `<table>`, а таблица не создаёт для него блока прокрутки. */
.km-table { background: var(--km-surface); border: 1px solid var(--km-border); border-radius: 14px; box-shadow: var(--km-shadow-card); overflow-x: auto; width: 100%; }

/* ОБЁРТКА ТАБЛИЦЫ — ТО, ЧТО ПРОКРУЧИВАЕТСЯ. 24 сентября 2026.

   `overflow-x: auto` строкой выше работает у `<div class="km-table">`
   (строки из `div`, экран сценариев) и не работает у `<table>`: таблица
   не сужается меньше своих столбцов и тянет страницу вбок. На окне 1024
   в настоящей админке, за меню WordPress, «Зачислениям» достаётся 788
   при наименьшей их ширине 1037, «Клиентам» — 876.

   Карточка — у обёртки: тень таблицы внутри прокрутки обрезалась бы по краю.
   `position: relative` — не оформление: без него подпись для диктора
   (`.km-sr`, она `absolute`) ищет место выше обёртки, прокрутке
   не подчиняется и тянет страницу до 1023 при окне 844 — замерено на стенде.
   Каждая `<table class="km-table">` стоит в такой обёртке — `TableScrollTest`. */
.km-table-scroll { position: relative; background: var(--km-surface); border: 1px solid var(--km-border); border-radius: 14px; box-shadow: var(--km-shadow-card); overflow-x: auto; max-width: 100%; }
.km-table-scroll > .km-table { background: none; border: none; border-radius: 0; box-shadow: none; }

/* Подписи столбцов — по левому краю, как и значения под ними.
   Браузер по умолчанию ставит `th` по центру, и подпись оказывается
   не над своим столбцом, а между двумя. Первые настоящие `<th>` в проекте
   появились в 5.6, до того таблицы собирались из `div`, и правила
   для них не было. Нашлось глазами на «Моих работах». */
/* ПОДПИСИ СТОЛБЦОВ — ТИХИЕ И ЗАГЛАВНЫМИ.

   До 21 августа 2026 здесь стояло `font-weight: 700` и больше ничего:
   подписи наследовали шестнадцать пикселей основного текста и выходили
   крупнее и темнее значений под ними. Читают в таблице значения,
   а подпись нужна один раз — понять, что это за столбец.

   Ровно этот вид уже был записан в системе для второй разновидности
   таблицы — `.km-table__row--head > *` строкой ниже, у той, что собрана
   из `div`. Одно и то же правило было написано дважды и разошлось:
   у одной таблицы подписи тихие, у другой громкие. Теперь они говорят
   одинаково. */
.km-table th {
  text-align: left;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--km-text-muted);
  padding: 12px 12px;
  white-space: nowrap;
  border-bottom: 1px solid var(--km-border);
}

/* Отступов у ячеек не было вовсе: браузер даёт единицу, и строки
   слипались, а разделяло их только то, что содержимое само по себе
   высокое. */
/* КЕГЛЬ ЯЧЕЙКИ ЗАДАН ЯВНО, И ЭТО ПРАВКА У СЕБЯ, А НЕ ГЛУШЕНИЕ ЧУЖОГО.

   Шестнадцать пикселей ячейкам давал наш собственный `body` выше: эта
   таблица стилей грузится и в админке, где у `body` тринадцать, — и
   перебивает их. То есть крупный кегль в списке не наследство WordPress,
   а наше умолчание, поставленное под абзац, который читают.

   Строка списка не абзац: её просматривают глазами по столбцу, и четырнадцать
   здесь — размер значения, а не текста. Померено на стенде: до правки
   «14 фев 2026», «8 августа», «Бесплатно», «самозапись» и прочерк потока
   шли шестнадцатым.

   Мельче остаётся то, что задумано мельче: почта под именем (12),
   рассрочка (12), подписи столбцов (11). */
.km-table td {
  padding: 12px 12px;
  font-size: 14px;
  border-bottom: 1px solid var(--km-border-soft);
  vertical-align: middle;
}

.km-table tbody tr:last-child td { border-bottom: none; }

/* Значение столбца не переносится по словам, если это одна величина.

   «Весна 2026» и «31 дек 2026» — по слову на строку в узкой колонке:
   таблица о девяти столбцах раздаёт им ширину поровну, и всё, что длиннее
   одного слова, встаёт лесенкой в четыре строки. Читаются они при этом
   как несколько значений подряд. */
.km-table td .km-nowrap,
.km-table__name,
.km-state,
.km-progress__num,
.km-progress__zero { white-space: nowrap; }
.km-table tbody tr:hover { background: var(--km-surface-alt); }

/* Имя и почта в строке списка.

   `.km-text` — шестнадцать пикселей с межстрочным 1.65, размер абзаца,
   который читают. Строка таблицы не абзац: имя в ней опознают взглядом,
   и полуторный межстрочный растит каждую строку из двухсот. */
.km-table__name { font-size: 14px; font-weight: 600; line-height: 1.3; }
/* Почта обрезается, а не растит столбец.

   Она длиннее имени и почти всегда длиннее всего остального в строке:
   таблица о девяти столбцах отдаёт ей ширину по содержимому, и вся
   страница уезжает за край окна. Померено: без потолка — на семь
   пикселей шире окна на стенде и заметно больше в админке, где слева
   стоит меню.

   Обрезать её можно, а имя нельзя: человека опознают по имени, почта
   же нужна для поиска — и ищут её не глазами по столбцу, а полем поиска
   наверху. Целиком она остаётся в подсказке. */
.km-table__mail {
  font-size: 12px;
  color: var(--km-text-muted);
  margin-top: 2px;
  display: block;
  max-width: 22ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Программа под курсантом (12.3, 18 сентября 2026).

   В ячейке курсанта, под почтой, а не своим столбцом: таблица не сжимается
   уже без него и с ним вылезала за край на 1280. Переносится, а не
   обрезается, как почта: названия курсов длинные и различаются концом
   («Места Вознесения. Самостоятельная работа»). Потолка по ширине нет
   намеренно: есть запас — название встаёт в строку, нет — переносится;
   потолок переносил бы и там, где место есть (слом 18 сентября 2026
   это показал). Тише имени: человека опознают по имени. */
.km-table__program {
  display: block;
  margin-top: 6px;
  font-size: 13px;
  line-height: 1.35;
  color: var(--km-text-secondary);
  white-space: normal;
}

/* Приглушённое значение: то, что повторяется в каждой строке и потому
   спорит за внимание с тем, ради чего в таблицу смотрят. Источник,
   прочерк вместо потока, дата у замороженного. */
.km-quiet { color: var(--km-text-muted); }

/* Подпись под значением — второй строкой и мельче. */
.km-sub { display: block; font-size: 12px; margin-top: 2px; }

/* Тревожное. Не «плохое»: красным здесь отмечено то, что требует
   действия в ближайшие дни, — а не то, что уже случилось. */
.km-alarm { color: var(--km-danger); }

.km-nowrap { white-space: nowrap; }

/* СОСТОЯНИЕ — ТОЧКА И СЛОВО.

   Слово рядом с точкой обязательно, и это не запас на всякий случай:
   цвет один не говорит ничего тому, кто его не различает, и ничего
   не говорит вообще, пока не выучишь, какой чему соответствует.

   Точка своя, а не буква и не эмодзи: она обязана быть видна при любом
   шрифте и не зависеть от того, что подставит система. Тот же довод,
   по которому в карточке эфира точка тоже своя. */
.km-state {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
  /* Наравне со строкой: состояние — такое же значение столбца, как дата
     рядом, и мельче остального оно читалось бы как подпись. */
  font-size: 14px;
}

.km-state__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex: none;
}

.km-state--ok { color: var(--km-text-secondary); }
.km-state--ok .km-state__dot { background: var(--km-ok); }

.km-state--warn { color: var(--km-warn); }
.km-state--warn .km-state__dot { background: var(--km-warn); }

.km-state--alarm { color: var(--km-danger); }
.km-state--alarm .km-state__dot { background: var(--km-danger); }

.km-state--off { color: var(--km-text-muted); }
.km-state--off .km-state__dot { background: var(--km-text-muted); }
.km-table__row { display: flex; align-items: center; gap: 14px; padding: 13px 18px; border-bottom: 1px solid var(--km-border-soft); min-width: 1040px; }
.km-table__row:last-child { border-bottom: none; }
.km-table__row:hover { background: var(--km-surface-alt); }
.km-table__row--head { background: var(--km-surface-alt); border-bottom: 1px solid var(--km-border); padding: 12px 18px; }
.km-table__row--selected { background: var(--km-warm-bg); }
.km-table__row--head > * {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--km-text-muted);
}
.km-table__person { flex: 1 1 260px; min-width: 220px; display: flex; align-items: center; gap: 11px; }

/* Ручка перетаскивания */
/* `.km-drag` снят 16 сентября 2026 вместе с ручкой перетаскивания, которой
   не было: класс рисовал хватку у элемента без единого обработчика. Порядок
   шагов переставляют стрелки (`.km-ico`). `.km-dragging` ниже живой — он
   у редактора дерева, где перетаскивание настоящее. */
.km-drop-line { height: 2px; border-radius: 1px; background: var(--km-accent); }
/* Бросок ВНУТРЬ строки — подсветкой самой строки, а не чертой рядом с ней.
   Черта отвечает на вопрос «между какими», подсветка — «в какую»; одним
   признаком три зоны сброса неразличимы, и человек узнаёт, куда попал,
   только после броска. Заведено пунктом 5 правок по узлам. */
.km-drop-into {
  background: var(--km-warm-bg);
  box-shadow: inset 0 0 0 2px var(--km-accent);
  border-radius: var(--km-radius-control);
}
.km-dragging {
  background: var(--km-surface);
  border: 1px solid var(--km-warm-border);
  border-radius: var(--km-radius-control);
  box-shadow: var(--km-shadow-lift);
}
/* Отказ при перетаскивании — у строки, куда бросили (слово Алены 21.10.2026), а не в полосе над деревом: та
   на длинном курсе за краем экрана. Сама плашка — `.km-note`; здесь только место в списке строк. */
.km-drop-note { margin: 4px 0 8px; }
/* Текст делит строку с кнопкой «Вложить как …», пока хватает места; не хватает — кнопка уходит вниз целиком. */
.km-drop-note__text { flex: 1 1 320px; min-width: 0; }

/* Липкая полоса — курс и цена */
.km-sticky-bar {
  position: sticky;
  top: 0;
  z-index: 20;
  background: rgba(246, 248, 251, 0.94);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--km-border);
  padding: 12px 28px;
  display: flex;
  align-items: center;
  gap: 20px;
}

/* ПОЛОСА С ЦЕНОЙ — ПРОДОЛЖЕНИЕ ОБЛОЖКИ, А НЕ СТРОКА НА ФОНЕ СТРАНИЦЫ.
   Решение Алены 4 сентября 2026.

   Модификатор, а не правка `km-sticky-bar`: тот же класс носят четыре
   административных экрана, где полоса — панель действий. Белая карточка
   со скруглением досталась бы им молча.

   Подложка, рамка и тень — карточки (`.km-card`), значения те же.
   `backdrop-filter` здесь снят: подложка непрозрачна, и размывать нечего.

   СТЫК. Зазор стопки снимается отрицательным полем ровно в ступень —
   считается из той же переменной, а не пишется числом. Скругление
   остаётся ОДНО НА ДВА БЛОКА: у обложки только верх, у полосы только низ.
   Скруглить обе стороны стыка значило бы нарисовать два блока рядом,
   а просят один.

   `:has()` — потому что решает СОСЕДСТВО, а не сам блок: обложка без
   полосы под собой скругляется как была. Не поддержи браузер `:has()`,
   обложка останется скруглённой снизу — шов будет виден, но ничего
   не сломается. */
.km-sticky-bar--price {
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-card);
  box-shadow: var(--km-shadow-card);
  backdrop-filter: none;

  /* ПОЛЯ, ПРОМЕЖУТОК И ВЫСОТА — ОТ КАРТОЧКИ УЧАСТНИКА. Решение человека
     8 сентября 2026: «полоса у гостя куцая по сравнению с полосой
     прогресса».

     Числа не подобраны на глаз, у каждого есть источник, и источник
     назван — иначе через этап их поправят «на глаз» обратно:

       24px  — поля `.km-card__pad`, ими обёрнута карточка участника;
       28px  — промежуток `.km-headline`, между прогрессом и кнопкой;
       149px — измеренная высота той карточки на ширине 1100.

     Высота здесь `min-height`, а не `height`: длинное название потока
     переносит строку, и жёсткая высота обрезала бы её.

     Последнее число живёт содержимым чужого блока: изменится состав
     карточки участника — оно устареет. Ловит это мерка стенда, которая
     сравнивает полосу с живой карточкой, а не с числом. */
  /* ПОЛЯ И ПРОМЕЖУТОК — ОТ КАРТОЧКИ УЧАСТНИКА, ВЫСОТА — ОТ СОДЕРЖИМОГО.
     Правка человека 8 сентября 2026, вторая по этой полосе.

     Здесь стояла `min-height: 149px` — высота карточки прогресса,
     снятая с неё числом. Человек посмотрел и сказал: высоты много,
     содержимое жмётся к краю. Так и есть: две строки мелким шрифтом
     в коробке на 149 читаются как пустая рамка с подписью.

     Число убрано, а не поправлено: высоту задаёт содержимое, и оно
     подросло — название крупнее, срок читаемый.

     Поля остались РОВНЫЕ и те же, что у карточки участника: 24 со всех
     сторон. Первая правка сделала их 22 на 28 — и мерка «поля те же,
     что у карточки» покраснела, справедливо. «Ровные» и «как у соседа»
     здесь одно и то же число, и разъезжаться им незачем. */
  padding: 24px;
  gap: 28px;
  align-items: center;
}

/* Название курса в полосе — заголовком, а не подписью.

   Общий `.km-sticky-bar__title` писан под липкую панель админки, где
   строка одна и мелкая. Здесь это главное слово на экране после самой
   обложки, и 15 пикселей для него мало.

   Перенос разрешён: в общем классе стоит `nowrap` с многоточием — там
   полоса узкая и обрезать верно, — а тут длинное название курса лучше
   перенести, чем оборвать. */
.km-sticky-bar--price .km-sticky-bar__title {
  font-family: var(--km-font-display);
  font-size: 19px;
  line-height: 1.3;
  white-space: normal;
  overflow: visible;
}

/* Строка про набор — читаемой, а не мелочью под названием. */
.km-sticky-bar--price .km-meta { font-size: 14px; color: var(--km-text-secondary); }

.km-sticky-bar--price .km-sticky-bar__main { gap: 6px; }

.km-hero + .km-sticky-bar--price {
  margin-top: calc(-1 * var(--km-gap-group));
  border-top: 0;
  border-top-left-radius: 0;
  border-top-right-radius: 0;
}

.km-hero:has( + .km-sticky-bar--price ) {
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}

/* НА ПРОДАЮЩЕЙ СТРАНИЦЕ ПОЛОСА — СТРОКОЙ ПОД ШАПКОЙ, А НЕ ЛИПКОЙ.
   Липкость она берёт от общего `.km-sticky-bar` (`sticky`, `top: 0`),
   а прилипает на этой странице строка переходов прототипа — тоже к верху
   окна. Две липкие у верха легли бы друг на друга, и полоса (z 20) закрыла
   бы строку (z 10). Прежний стенд описывал полосу так же: «обычная строка
   в потоке под шапкой» (1 октября 2026).
   `z-index: auto` — обязательно: с `relative` её прежний `z-index: 20`
   заводит свой слой выше закреплённой полосы телефона (15), и на боевом
   полоса с ценой, проходя низ экрана, закрывала «Выбрать участие». */
.km-page--guest > .km-sticky-bar--price { position: relative; top: auto; z-index: auto; }

/* Левая часть полосы на продающей странице (7.4): название курса и подпись
   про набор. Занимает всё свободное место, чтобы цена и кнопка прижались
   вправо, и сжимается до нуля — длинное название иначе выталкивает кнопку
   «Записаться» за край, то есть ровно то, ради чего полоса и висит. */
.km-sticky-bar__main {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  margin-right: auto;
}

.km-sticky-bar__title {
  font-weight: 700;
  font-size: 15px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ШАПКА ГОСТЯ ДЫШИТ. Решение человека 8 сентября 2026: «между заголовком,
   подзаголовком, именем и кнопкой тесно, всё слиплось в один ком».

   У участника в шапке четыре строки на 374 пикселях высоты — воздух
   остаётся сам собой. У гостя их шесть: добавились цена с кнопкой
   и счётчик курсантов, и тот же промежуток в 6 пикселей превратился
   в ком.

   Шаги взяты из системы, а не выдуманы: `--km-gap-label` — расстояние
   ВНУТРИ группы, `--km-gap-group` — МЕЖДУ группами. Метка вида,
   заголовок, подзаголовок и имя ведущей — одна группа: они называют
   курс. Кнопка и счётчик — другие, и потому отбиты шире.

   Вес селектора (0,4,0) не украшение: `.km-hero--brand.km-hero--over
   .km-hero__body` весит (0,3,0) и задаёт `gap: 6px` — правило полегче
   молча проиграло бы ему, и на экране не изменилось бы ничего.

   Только у гостя: у участника то же место дышит, и трогать его незачем. */
.km-page--guest .km-hero--brand.km-hero--over .km-hero__body,
.km-page--guest .km-hero--brand .km-hero__body {
  gap: var(--km-gap-label);
}

.km-page--guest .km-hero__body > .km-actions,
.km-page--guest .km-hero__body > .km-hero__learners {
  margin-top: calc( var(--km-gap-group) - var(--km-gap-label) );
}

/* ЦЕНА, ПОДПИСЬ ПОД НЕЙ И СЧЁТ КУРСАНТОВ — ЦВЕТОМ ПОДЗАГОЛОВКА ЭТОЙ ШАПКИ,
   БЕЗ ФОНА. Правка Алены 2 октября 2026: тёмные подложки 1.386.3 «выглядят
   грубо» — сняты. У «Энергетического апгрейда», «Самоценности» и «Практикума
   Принятия» белые цена и «+N курсантов» тонули в светлой обложке, потому что
   цвет у них был свой, белый, — а подзаголовок и автор рядом читались.

   Отсюда правило: цена («от», сумма, «× 3»), подпись под ней и счётчик
   набраны **тем же цветом, что подзаголовок и автор этой шапки**. Шапка
   у светлой обложки (`km-hero--ink`) — тёмно-синяя, у тёмной (`km-hero--lume`,
   с затемнением слева) — белая, как подзаголовок; на узком у обеих —
   тёмно-синяя (мобильный блок ниже). Кружки-аватарки не трогаются.

   Только у гостя: у участника в шапке нет ни цены, ни счётчика. Вес (0,5,0)
   сильнее общего `.km-hero--over .km-price` (0,2,0) и правил узкого
   экрана (0,3,0) — потому оба вида стоят шире 640, а узкий — своим правилом. */
@media (min-width: 641px) {
	.km-page--guest .km-hero--brand.km-hero--ink.km-hero--over .km-price,
	.km-page--guest .km-hero--brand.km-hero--ink.km-hero--over .km-price__from,
	.km-page--guest .km-hero--brand.km-hero--ink.km-hero--over .km-price__stages,
	.km-page--guest .km-hero--brand.km-hero--ink.km-hero--over .km-price__note,
	.km-page--guest .km-hero--brand.km-hero--ink.km-hero--over .km-hero__learners .km-meta { color: var(--km-brand-navy); }

	.km-page--guest .km-hero--brand.km-hero--lume.km-hero--over .km-price,
	.km-page--guest .km-hero--brand.km-hero--lume.km-hero--over .km-price__from,
	.km-page--guest .km-hero--brand.km-hero--lume.km-hero--over .km-price__stages,
	.km-page--guest .km-hero--brand.km-hero--lume.km-hero--over .km-price__note,
	.km-page--guest .km-hero--brand.km-hero--lume.km-hero--over .km-hero__learners .km-meta { color: rgba(255, 255, 255, 0.92); }
}

/* Карточка варианта участия (7.4).
   Кнопка прижата к низу: карточки в ряду разной высоты — у одной три строки
   про содержимое, у другой пять, — и без этого кнопки встают лесенкой. */
.km-plan .km-card__body { gap: 12px; height: 100%; }
.km-plan .km-btn { margin-top: auto; }

/* Сетки и ритм */
.km-grid-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(272px, 1fr)); gap: 20px; }

/* Ровно три колонки — секции «Для кого» и «Что изменится» гостевой страницы,
   макет `course-page-guest-v2.html`.

   Отдельно от `km-grid-cards`, и это не дубль: та набирает столько колонок,
   сколько влезет по 272 пикселя, — на широком экране получилось бы четыре
   дорожки под три карточки, и последняя треть строки пустовала бы. Здесь
   карточек всегда три, и они делят ширину поровну, как в макете.

   На узком — в столбик: три карточки по 116 пикселей не читаются. */
.km-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }

/* ОБЁРТКА ЯДРА УБИРАЕТСЯ ИЗ РАСКЛАДКИ, а не из разметки.

   Группе блоков ядро возвращает старый контейнер
   `wp-block-group__inner-container` — на теме без `theme.json`, а BuddyBoss
   именно такая. Контейнер становится единственным ребёнком сетки, и три
   карточки внутри него встают в один столбец: `display: grid` на месте,
   колонок три, а карточки все в первой.

   Отменить это атрибутом блока нельзя — пробовал `layout`, обёртка
   возвращается всё равно. `display: contents` убирает её из раскладки,
   и карточки становятся прямыми детьми сетки; разметка при этом остаётся
   ядровой, и ядро правит её как захочет.

   Найдено стендом измерением: в разметке всё выглядело верно. */
.km-grid-3 > .wp-block-group__inner-container { display: contents; }

@media (max-width: 900px) {
  .km-grid-3 { grid-template-columns: 1fr; }
}
/* Ритм стопки — переменной, а не числом: его читают вкладки, чтобы
   добрать свои 24 воздуха, откуда бы ритм ни шёл. Своего ритма у каждого
   макета свой: 24 у страницы курса, 26 у «Моих работ», 28 у витрины,
   40 у карты. Шестнадцать — умолчание, а не правда про все экраны. */
.km-stack { display: flex; flex-direction: column; gap: var(--km-stack-gap, var(--km-gap-group)); }

/* Страница курса разносит блоки на 24 — так в `design/course-page-member.html`.
   Крошки, обложка и карточка прогресса стояли на 16, и восьми пикселей
   не хватало ровно там, где два экрана кладут рядом. */
.km-page--course { --km-stack-gap: 24px; }
.km-section { display: flex; flex-direction: column; gap: 24px; }

/*
 * Ритм между соседними секциями.
 *
 * Внутри секции расстояния задаёт её собственный `gap`, а между секциями
 * его не задавал никто: в макетах они разнесены руками — инлайновым
 * `margin` у разделительной черты, — и в дизайн-систему это не переехало.
 * Оба административных экрана из-за этого стояли блоками вплотную:
 * кнопка «Новое предложение» упиралась в таблицу, а шапка — в чипы.
 *
 * Нашлось стендом предложений (3.6) измерением промежутков. Стенд
 * зачислений был при этом зелёным — он их не мерил, а глазами «вплотную»
 * читается как «так и задумано».
 */
.km-section + .km-section { margin-top: 28px; }

/*
 * Секция, у которой первый ребёнок — подпись блока.
 *
 * Общий ритм секции — 24, и это расстояние **между блоками** внутри неё.
 * Подпись блоком не является: она про то, что под ней. Оставленная
 * на общем ритме, она стоит ровно посередине между верхним и нижним
 * и читается как принадлежащая верхнему — на экране потоков «ПОТОКИ
 * ПРОГРАММЫ» так и прилипла к полю выбора над собой.
 *
 * Число то же, что у подписи на карточке, и берётся оно из одного места.
 */
.km-section--tight { gap: var(--km-gap-label); }

/*
 * Подпись под заголовком секции — мера чтения, и только она.
 *
 * Цвет и кегль сюда не переписываются: их даёт `km-text-secondary`, и класс
 * ставится рядом с ним. Второе написание того же разошлось бы с ним молча —
 * ровно так `.km-hint` прожил девять экранов в двух смыслах.
 *
 * Мера в `ch`, а не в пикселях: она про длину строки, а длина строки
 * считается знаками. На 1180 пикселях колонки подпись без меры даёт строку
 * знаков в сто тридцать — глаз теряет начало следующей.
 *
 * Заведено под «Для кого этот курс» (макет `course-page-guest-v2.html`,
 * где у секции есть `sec__sub`); готового вида под эту роль в системе
 * не было — проверено поимённо: `km-sub` это мелкая подпись в 12 px,
 * `km-hint` — подсказка под полем, `km-meta` — служебная строка.
 */
.km-section__sub { max-width: 62ch; }

/*
 * Тесная колонка: подпись и то, к чему она относится, стоят рядом,
 * а не через воздух секции. Заведено под заголовок карточки потока
 * и название её программы — 24 пикселя между ними читались бы как два
 * разных блока.
 */
.km-stack--tight { gap: var(--km-gap-label); }

.km-page { max-width: 1180px; margin: 0 auto; padding: 32px 28px 96px; }

/* У ЭКРАНОВ НА САЙТЕ БОКОВЫХ ПОЛЕЙ НЕТ — НИ НА КАКОЙ ШИРИНЕ. Решение Алены
   15 сентября 2026: «Убери боковые отступы совсем — во всех разрешениях…
   Я сама пропишу их там, где нужно», — у всех шорткодов. Замер на боевом
   у кабинета на 375: наши 28 + JetTabs 10 + элемент Elementor 15 − сетка
   темы 10 = 43 px с каждой стороны. Снимаются наши 28; поля JetTabs
   и Elementor — настройки страницы, их правит хозяйка.
   Модификатор, а не правка `.km-page`: общее правило делят шестнадцать
   экранов админки, где Elementor нет и поставить поля некому. */
.km-page--flush { padding-left: 0; padding-right: 0; }

/* СТРАНИЦА КУРСА СТАВИТ ПОЛЯ САМА: 20 px, на телефоне 16. Слово Алены
   1 октября 2026 (ответы по 1.385.0): страница курса — гостевая и участника —
   стоит не в Elementor, и поставить поля ей некому. Правило «у шорткодов
   на сайте полей нет» выше — про шорткоды внутри Elementor: кабинет, каталог,
   «Мои работы».
   Вес (0,2,0), а не одиночный класс: `.km-page--flush` и `.km-page` — по
   одному классу, и ничья решалась бы порядком таблицы. */
/* `:not(.no-gutter)` — сила (0,3,0), а не (0,2,0): страница прямым потомком сетки темы (закрытый эфир,
   `closed-event-page.php`) получает от BuddyBoss `.bb-grid>:not(.no-gutter){padding:0 10px}` той же
   силой (0,2,0), и ничью выигрывал он — поля 10 вместо 20, контейнер 1160 вместо 1140 у гостевой (замер
   на боевом 05.10.2026). Сила, а не порядок; начинается с `.km-`, чтобы попасть в `design-system-embed.css`.
   Держит `ThemeSiteOverrideTest`. */
.km-page.km-page--sides:not(.no-gutter) { padding-left: 20px; padding-right: 20px; }
@media (max-width: 760px) {
  .km-page.km-page--sides:not(.no-gutter) { padding-left: 16px; padding-right: 16px; }
}

/* ---------------------------------------------------------------------------
   Внутри темы (5.9)
   ---------------------------------------------------------------------------
   Тема даёт своим `p` и заголовкам вертикальные отступы — на стенде их не было,
   и наши подписи внутри темы разъезжались: «Программа курса» и счётчик рядом
   с ней вставали на разные уровни, а между секциями появлялся лишний воздух.

   Обнуляется **только своё**: перечислены наши классы, а не элементы. Обнули
   мы `p` внутри `.km-page` — и абзацы материала в занятии слиплись бы в один
   кусок, потому что содержимое приходит чужой разметкой и живёт по правилам
   темы законно.
   --------------------------------------------------------------------------- */
.km-h1, .km-h2, .km-h3,
/*
 * Расстояния задаёт `gap` контейнера, а не поля абзацев.
 *
 * Список был написан и **двое в него не попали** — `.km-text` и `.km-hint`.
 * Браузер даёт `<p>` поле в один кегль, оно складывается с `gap`, и карточки
 * сайдбара держали 32 против заявленных 16, а подсказка под кнопкой — 28.
 * Найдено общей проверкой стенда, а не глазами: разница в шестнадцать
 * пикселей на глаз выглядит просто «просторнее».
 *
 * Та же семья, что склонение по числу в 9.8: правило записано, а перевели
 * не всех.
 */
.km-section-title, .km-meta, .km-eyebrow,
.km-text, .km-text-secondary, .km-hint, .km-note,
.km-hero__title, .km-hero__lead, .km-empty__title, .km-empty__text,
.km-card__title, .km-course-card__title, .km-price,
.km-progress__meta, .km-progress__label {
	margin: 0;
}

/* Счётчик прижимается вправо: заголовок слева, число справа — так в макете. */
.km-row > .km-meta { margin-left: auto; }

/* Заглушка под изображение */
.km-placeholder {
  background: repeating-linear-gradient(135deg, #EDF1F6 0 9px, #E4EAF1 9px 18px);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--km-mono);
  font-size: 11px;
  color: var(--km-text-muted);
  width: 100%;
  height: 100%;
}

/* Правила, которые нельзя нарушать
   1. Один акцентный цвет на экран, одна главная кнопка в блоке.
   2. Оранжевый — только действие и статус, не декор.
   3. Никаких градиентов в интерфейсе, теней жёстче --km-shadow-card, обводок толще 1px.
   4. Закрытый контент показывается с причиной словами, не прячется.
   5. Прогресс — в занятиях («8 из 20»), процент только как дополнение.
   6. Пустые состояния — приглашение, а не извинение.
   7. Никакой геймификации: ни стриков, ни рейтингов активности.
   8. Время везде московское. */

/* ==========================================================================
   ДОБАВЛЕНО: поля, флаги, дерево на три уровня, аккордеон, меню кабинета,
   пустые состояния, пагинация, всплывающая панель.
   Только существующие переменные — новых цветов и радиусов нет.
   ========================================================================== */

/* --- Поля ввода --- */
.km-field { display: flex; flex-direction: column; gap: 7px; }
.km-label { font-size: 13px; font-weight: 600; color: var(--km-text-secondary); }
.km-hint { font-size: 12px; line-height: 1.5; color: var(--km-text-muted); }
.km-hint--error { color: var(--km-danger); }

/* `.km-write__area` здесь же, а не своим набором значений: поле письма
   выглядит как обычное многострочное, и второе написание тех же цветов
   разошлось бы с этим на первой правке. Скругление у него своё — оно
   ниже, там же, где объяснён стык с панелью. */
.km-input,
.km-textarea,
.km-select,
.km-write__area {
  font-family: inherit;
  font-size: 15px;
  line-height: 1.5;
  color: var(--km-text);
  background: var(--km-surface-alt);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-control);
  padding: 12px 14px;
  width: 100%;
  transition: border-color 0.16s, background 0.16s;
}
.km-input::placeholder,
.km-textarea::placeholder { color: var(--km-text-muted); }

/* СПИСОК РОСТОМ С ПОЛЕ ВВОДА. Найдено стендом правил 22 августа 2026.
 *
 * `line-height` у `select` движок игнорирует — проверено подстановкой:
 * значение меняется, высота нет. Оттого список выходил на три пикселя ниже
 * соседнего поля, а `.km-row` выравнивает по центру — и подписи двух полей
 * в одной строке вставали на разных уровнях.
 *
 * Общая мерка стендов ловит это с первого этапа («подписи в строке стоят
 * на одном уровне»), и на этом экране она проваливалась молча: отчёт
 * не печатался вовсе.
 *
 * Рост задаётся снизу тем же счётом, каким его набирает поле ввода:
 * строка (1.5em) плюс отступы (24px) плюс рамки (2px). Числом здесь стояло
 * бы 48.5px, и первая же правка кегля развела бы их снова. */
.km-select,
select.km-input { min-height: calc(1.5em + 26px); }

.km-input:hover,
.km-textarea:hover,
.km-select:hover { border-color: var(--km-warm-border); }

.km-input:focus,
.km-textarea:focus,
.km-select:focus {
  outline: none;
  background: var(--km-surface);
  border-color: var(--km-warm-border);
  box-shadow: 0 0 0 3px var(--km-warm-bg);
}

.km-textarea { min-height: 116px; resize: vertical; }

/* Числовое поле — уже, выравнивание по правому краю */
.km-input--number { width: 120px; text-align: right; font-variant-numeric: tabular-nums; }

/* Выпадающий список: своя стрелка вместо системной */
.km-select {
  appearance: none;
  padding-right: 40px;
  background-image: var(--km-select-arrow);
  background-repeat: no-repeat;
  background-position: right 14px center;
}


/* Поле с датой — иконка календаря слева задаётся обёрткой */
.km-input-group { position: relative; display: flex; align-items: center; }
.km-input-group__icon {
  position: absolute;
  left: 14px;
  display: flex;
  color: var(--km-text-muted);
  pointer-events: none;
  /*
   * РАЗМЕР ЗАДАЁТСЯ ЗДЕСЬ, А НЕ У КАЖДОГО ЗОВУЩЕГО. Найдено глазами
   * 23 августа 2026 на выборе программы.
   *
   * Класс не задавал размера вовсе, и держалось это на том, что первый
   * зовущий вешал его на `<span>`, а `<svg>` внутри размечал атрибутами
   * `width`/`height`. Повесь тот же класс прямо на `<svg>` — и он берёт
   * размер по умолчанию: 300×150. На экране это лупа во весь экран.
   *
   * Ни одна проверка этого не ловит: значок стоит `absolute`, за ширину
   * страницы не вылезает, класс в дизайн-системе есть. Видно только глазами.
   */
  width: 18px;
  height: 18px;
}

.km-input-group__icon svg {
  width: 100%;
  height: 100%;
  display: block;
}
.km-input-group .km-input { padding-left: 40px; }
.km-input-group:focus-within .km-input-group__icon { color: var(--km-accent); }
.km-input[type="date"] { font-variant-numeric: tabular-nums; }

/* ПОЛЕ ДАТЫ РОСТОМ С СОСЕДНИЕ. Найдено стендом карточки зачисления
 * 17 сентября 2026: Chrome рисует поле даты на два пикселя выше обычного
 * (51 против 49) — место под значок календаря. `.km-row` выравнивает поля
 * по низу, и подпись даты вставала выше соседних: общая мерка «подписи
 * в строке на одном уровне» проваливалась. Высота объявляется числом,
 * тем же, что у списка выше. */
.km-input[type="date"] { height: calc(1.5em + 26px); }

/* Состояния */
.km-input.is-error,
.km-textarea.is-error,
.km-select.is-error { border-color: var(--km-danger-border); background: #FDF0EC; }
.km-input.is-error:focus,
.km-textarea.is-error:focus { box-shadow: 0 0 0 3px var(--km-danger-bg); border-color: var(--km-danger-border); }

.km-input:disabled,
.km-textarea:disabled,
.km-select:disabled {
  background: var(--km-border-soft);
  border-color: var(--km-border);
  color: var(--km-text-muted);
  cursor: not-allowed;
}

/* СТРЕЛКА СПИСКА ОДНА В ЛЮБОМ СОСТОЯНИИ. Фокус, ошибка и выключенный список выше меняют фон сокращённой записью
   `background`, а она сбрасывает всё сразу: картинку, «не повторять» и место. До 1.522.7 фокус возвращал одну
   картинку — и стрелка ложилась узором по всему полю (снимок боевого 15.10.2026, «Рейтинг», «Самостоятельное
   прохождение»); у ошибки и выключенного стрелки не было вовсе. Здесь все три свойства вместе и после всех трёх
   состояний; наведение фона не трогает. Держит общая мерка стендов «стрелка одна» (`tests/stand-checks.js`). */
.km-select:focus,
.km-select.is-error,
.km-select:disabled {
  background-image: var(--km-select-arrow);
  background-repeat: no-repeat;
  background-position: right 14px center;
}

/* --- Чекбокс и переключатель --- */
.km-check {
  display: inline-flex;
  align-items: flex-start;
  gap: 10px;
  cursor: pointer;
  font-size: 15px;
  line-height: 1.5;
  user-select: none;
}
/* СТОЛБИК ФЛАЖКОВ — когда выбирают несколько из списка, а не одно из.
   Заведён 29 августа 2026 под выбор потоков в условном блоке: `km-check`
   сам по себе `inline-flex`, и без обёртки два флажка встают в строку,
   а третий переносится — читается как случайная сетка, а не как список.

   Зазор тот же, что между полями формы: строки здесь равноправны. */
.km-checks { display: flex; flex-direction: column; gap: 8px; }

.km-check input { position: absolute; opacity: 0; width: 0; height: 0; }
.km-check__box {
  width: 18px;
  height: 18px;
  flex: none;
  margin-top: 3px;
  border-radius: 5px;
  border: 1.5px solid #C9D3DE;
  background: var(--km-surface);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.16s, border-color 0.16s;
}
.km-check__box svg { opacity: 0; }
.km-check:hover .km-check__box { border-color: var(--km-warm-border); }
.km-check input:checked + .km-check__box { background: var(--km-accent); border-color: var(--km-accent); }
.km-check input:checked + .km-check__box svg { opacity: 1; }
.km-check input:focus-visible + .km-check__box { box-shadow: 0 0 0 3px var(--km-warm-bg); }
.km-check input:indeterminate + .km-check__box { background: var(--km-accent); border-color: var(--km-accent); }
.km-check input:indeterminate + .km-check__box svg { opacity: 1; }
.km-check input:disabled + .km-check__box { background: var(--km-border-soft); border-color: var(--km-border); }
.km-check input:disabled ~ .km-check__label { color: var(--km-text-muted); }

/* Компактный — для массового выбора в строке списка */
.km-check--row { gap: 0; }
.km-check--row .km-check__box { margin-top: 0; }

.km-check__label { display: flex; flex-direction: column; gap: 3px; }
.km-check__note { font-size: 12px; color: var(--km-text-muted); }

.km-switch { display: inline-flex; align-items: center; gap: 12px; cursor: pointer; font-size: 15px; user-select: none; }
.km-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.km-switch__track {
  width: 42px;
  height: 24px;
  flex: none;
  border-radius: 12px;
  background: var(--km-track);
  border: 1px solid var(--km-border);
  padding: 2px;
  display: flex;
  transition: background 0.16s, border-color 0.16s;
}
.km-switch__knob {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--km-surface);
  box-shadow: var(--km-shadow-card);
  transition: transform 0.16s;
}
.km-switch input:checked + .km-switch__track { background: var(--km-accent); border-color: var(--km-accent); }
.km-switch input:checked + .km-switch__track .km-switch__knob { transform: translateX(18px); }
.km-switch input:focus-visible + .km-switch__track { box-shadow: 0 0 0 3px var(--km-warm-bg); }
.km-switch input:disabled + .km-switch__track { background: var(--km-border-soft); }

/* --- Дерево: три уровня вложенности --- */

/* ЛЕСТНИЦА КРУЖКОВ — одна таблица на весь фронт. Правка вёрстки 1.
 *
 * Переменные объявлены на дереве, а не на строке узла: строка стоит внутри
 * контейнера топиков, и объяви их `.km-node`, собственное объявление
 * перебивало бы унаследованное — лист получил бы размер занятия.
 *
 * Кто читает эти числа, кроме самого кружка: отступ подписи на узком экране
 * (подпись переносится под название и встаёт по кружку). Поэтому число одно
 * и живёт здесь. */
/* Знак заполняет кружок, а не сидит в нём точкой — решение человека
   8 августа 2026, ориентир LearnDash. Разница между уровнями осталась
   на размере кружка и знака, но не ценой того, что лист нечитаем:
   у листа знак занимает даже большую долю кружка, чем у занятия.

   Половина дела здесь, вторая — в рамке рисунка (`lmsGlyph`): она была
   вдвое шире чернил, и одни числа тут ничего бы не дали. */
/* КАРТОЧКА НА КАЖДОЕ ЗАНЯТИЕ, серый фон страницы между карточками.
 *
 * Принятый вид от 19 августа 2026, `design/course-tree-v3.html`. Одна
 * карточка на всё дерево держалась ровно один выпуск (1.0.0–1.0.2) и была
 * забракована человеком: пятнадцать занятий и шестьдесят топиков внутри
 * одной рамки читаются сплошной стеной, а модуль внутри белого поля
 * не разделяет ничего.
 *
 * Поэтому поля у самого дерева больше нет: их несёт карточка занятия,
 * а название модуля стоит между карточками, на сером. */
.km-tree { display: flex; flex-direction: column; padding: 0; --km-node-glyph: var(--km-glyph); }
.km-tree__topics { --km-node-glyph: 16px; }
.km-tree--compact { --km-node-glyph: 17px; }
.km-tree--compact .km-tree__topics { --km-node-glyph: 14px; }

/* Карточка занятия. Ставит её `card()` в `course-map.js` — на один уровень,
   тот, что лежит прямо под модулем или прямо в корне. Топики карточек
   не получают ни при каком условии: на этом сломались три захода.

   `overflow: hidden` обязателен и не про красоту: тёплая подложка текущего
   занятия лежит на строке во всю ширину карточки, и без обрезки её прямые
   углы торчали бы из скруглённых углов рамки. */
.km-tree__card {
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-card);
  box-shadow: var(--km-shadow-card);
  overflow: hidden;
  margin-bottom: 10px;
}

/* СКЛАДКА ЗАНЯТИЯ. Решение человека 19 августа 2026: сворачивается
   занятие, модуль остаётся строкой-заголовком.

   Карточка при этом ОДНА и лежит на корне дерева — ни у занятия,
   ни у топика, ни у модуля своей нет. Три захода сломались на обратном. */
/* `display` У `<details>` НЕ ТРОГАЕМ.
 *
 * Стояло `display: flex`, и складка перестала прятать: топики держали
 * высоту 228 и раскрытыми, и свёрнутыми. Скрытие свёрнутого содержимого
 * браузер делает внутренним механизмом, и смена `display` на флекс его
 * ломает — разметка при этом верная, топики лежат в `<details>`, а не
 * в `<summary>`, и на глаз всё выглядит правильным.
 *
 * Поймано не селектором, а тем, что складку раскрыли и свернули
 * и посмотрели, что спряталось. */
.km-tree__fold { display: block; }

/* СВЁРНУТОЕ ПРЯЧЕТСЯ ЯВНО, а не механизмом браузера.
 *
 * У `.km-tree__topics` свой `display: flex` с седьмого этапа, и он
 * переживал скрытие свёрнутого `<details>`: топики держали высоту 228
 * и раскрытыми, и свёрнутыми. Разметка при этом верная — они лежат
 * в `<details>`, а не в `<summary>`, — и на глаз всё выглядело правильным.
 *
 * Снять флекс совсем нельзя: он держит колонку, и без него топики легли бы
 * строкой. Поэтому он возвращается раскрытому.
 *
 * Правило СУЖЕНО до складки (`.km-tree__fold >`), а не написано на класс
 * целиком: `km-tree__topics` носит контейнер третьего уровня везде, где
 * рисуется дерево, и безусловный `display: none` спрятал бы топики там,
 * где складки нет вовсе. Сегодня таких мест не нашлось, но правило,
 * верное только при сегодняшнем составе, — это ловушка на будущее. */
.km-tree__fold > .km-tree__topics { display: none; }
.km-tree__fold[open] > .km-tree__topics { display: flex; }
.km-tree__fold-head { display: block; cursor: pointer; list-style: none; }
.km-tree__fold-head::-webkit-details-marker { display: none; }

/* Синей рамки фокуса наружу не выходит: умолчание `<details>` обводило
   раскрытое занятие целиком. Клавиатуре признак остаётся — на самой строке. */
.km-tree__fold-head:focus { outline: none; }
.km-tree__fold-head:focus-visible .km-node { outline: 2px solid var(--km-accent); outline-offset: -2px; }

/* Шеврон смотрит ВПРАВО у свёрнутого и вниз у раскрытого — макет v3.
   Путь в скрипте один, поворот здесь: два пути под одно и то же разошлись
   бы молча, а «повёрнут» и «не повёрнут» видно глазом. */
.km-tree__chevron { color: var(--km-text-muted); transition: transform .15s; }
details[open] > .km-tree__fold-head .km-tree__chevron { transform: rotate(90deg); }

/* У занятия, где человек стоит, шеврон тёплый — иначе подложка есть,
   а знак слева остаётся серым и спорит с ней. */
.km-node--current .km-tree__chevron { color: var(--km-accent); }

/* ЛЕСТНИЦА РЕДАКТОРА ДЕРЕВА — АДМИНКА, а не фронт.
 *
 * `km-tree__module`, `km-tree__lesson`, `km-tree__topic` носят строки
 * редактора дерева (`tree-editor.js`), списка потоков (`cohorts.js`)
 * и корзины (`trash.js`). У ученика дерево собирается другими классами:
 * `km-tree__card`, `km-tree__heading`, `km-node`.
 *
 * Имя общее и занято НАМИ ЖЕ, и это стоило отдельной проверки: макет v3
 * называет карточку занятия `km-tree__lesson`, а строка под этим именем
 * здесь уже пятая версия — с полями, чертой снизу и отступом 52. Взять
 * имя из макета значило бы перекрасить редактор дерева молча. */
/* ЛЕСТНИЦА УРОВНЕЙ В РЕДАКТОРЕ ДЕРЕВА. Макет `design/tree-editor-v1.html`,
   21 августа 2026.

   Человек смотрел на боевом и назвал беду: **топик шире занятия**, и
   вложенность читалась наоборот. Отступ и кегль работают только вместе:
   один без другого не читается — отступ без кегля теряется на 375, кегль
   без отступа не говорит, кто чей.

   Числа взяты у макета, а не пересчитаны: 0 / 40 / 72 по отступу,
   15 / 14 / 13 по кеглю, и приглушение на третьем.

   Строка одна на все уровни (`km-treerow`), а не три разных: до этого дня
   у каждого уровня был свой класс со своим набором правил, и лестница
   разъезжалась при каждой правке одного из трёх. */
/* НАЖИМАЕМАЯ СТРОКА ВЫГЛЯДИТ НАЖИМАЕМОЙ. Найдено 16 сентября 2026.

   Вся строка открывает панель узла (`tree-editor.js`, обработчик на
   `row`), а курсор на ней стоял обычный: признак был, и он ничем
   не отличался — человек не видел, что строку можно нажать. Указатель
   был только у шеврона, то есть подсказывал про сворачивание,
   а не про открытие.

   Мерка на это в стенде есть, и она молчала: стенд обрывался раньше,
   на `history.replaceState()`, и всё, что стояло после, не проверялось
   вовсе. Разбор — в шапке сборщика. */
.km-treerow {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 9px 16px;
  border-bottom: 1px solid var(--km-border-soft);
  cursor: pointer;
}

.km-treerow:last-child { border-bottom: none; }
.km-treerow:hover { background: var(--km-bg); }
/* `--picked` СНЯТ, А НЕ ПЕРЕИМЕНОВАН. Найдено 16 сентября 2026.
   Его вешал скрипт зачислений на `<tr>` таблицы, у которой класса
   `km-row` нет вовсе: правило не срабатывало никогда, и выбранная строка
   не подсвечивалась с того дня, как подсветку завели. Верное имя лежало
   рядом и с тем же цветом — `.km-table__row--selected`. */

/* РУЧКА ПОЯВЛЯЕТСЯ ПО НАВЕДЕНИЮ. Висящая у каждой из 119 строк, она
   зашумляет экран сильнее, чем помогает: перетаскивают один узел из ста,
   а видят ручку у всех. */
.km-treerow__grip {
  width: 14px;
  height: 14px;
  flex: none;
  color: var(--km-text-muted);
  opacity: 0;
  cursor: grab;
}

.km-treerow:hover .km-treerow__grip { opacity: 1; }

/* «+» У МОДУЛЯ И ЗАНЯТИЯ — новый узел внутрь этой строки (ответ Алены 21.10.2026 на ревизию дерева, п. 1).
   Появляется по наведению, как ручка; с клавиатуры — по фокусу: невидимая кнопка в порядке табуляции
   была бы ловушкой. */
.km-treerow__add {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  flex: none;
  padding: 0;
  border: 1px solid var(--km-border);
  border-radius: 6px;
  background: var(--km-surface);
  color: var(--km-text-secondary);
  opacity: 0;
  cursor: pointer;
}

.km-treerow:hover .km-treerow__add,
.km-treerow__add:focus-visible { opacity: 1; }

.km-treerow__add:hover { color: var(--km-accent); border-color: var(--km-accent); }
.km-treerow__add:disabled { cursor: not-allowed; color: var(--km-text-faint); border-color: var(--km-border-soft); }
.km-treerow__add svg { width: 12px; height: 12px; }

.km-treerow__chev {
  width: 16px;
  height: 16px;
  flex: none;
  color: var(--km-text-muted);
  cursor: pointer;
  transition: transform 0.15s;
}

/* Свёрнутый — шеврон вбок. Поворотом, а не вторым знаком: два знака
   разошлись бы с состоянием, поворот от него неотделим. */
.km-treerow--folded .km-treerow__chev { transform: rotate( -90deg ); }

/* У листа шеврона нет, но место его занято: без этого имена узлов
   разъехались бы на 16 пикселей между листом и контейнером. */
.km-treerow__chev--empty { visibility: hidden; }

/* Тело строки — текст и правый столбец подписей рядом со знаками. Текст — имя, а под ним, если есть, нехватка:
   одним столбцом, чтобы знаки слева и подписи справа стояли по верху ПЕРВОЙ строки текста, как везде (ответ
   Алены 21.10.2026, п. 5). На узком экране подписи уходят под имя внутри тела, а не под флажок. */
.km-treerow__body {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 9px;
}

.km-treerow--explained .km-treerow__body { align-items: flex-start; }

.km-treerow__text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.km-treerow__name {
  flex: none;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Правый столбец — одним рядом и приглушённо: тип, правило, обязательность
   отвечают на вопросы, которые задают редко, и кричать им незачем. */
.km-treerow__meta {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: none;
}

.km-treerow--module { background: var(--km-surface-soft, #FAFBFD); }
.km-treerow--module .km-treerow__name { font-size: 15px; font-weight: 700; }

.km-treerow--lesson { padding-left: 40px; }
.km-treerow--lesson .km-treerow__name { font-size: 14px; font-weight: 600; }

.km-treerow--topic { padding-left: 72px; }
.km-treerow--topic .km-treerow__name { font-size: 13px; font-weight: 400; color: var(--km-text-secondary); }

/* НЕХВАТКА ЗАНИМАЕТ СВОЮ СТРОКУ ЦЕЛИКОМ.
   Найдено глазами на стенде 21 августа 2026: у эфира без даты и без ссылки
   два предупреждения в правом столбце вытолкнули имя в многоточие —
   «Эфир: сложн…». Имя важнее любой подписи рядом с ним.

   Нехватка стоит своей строкой ПОД ИМЕНЕМ, в столбце текста (`.km-treerow__text`),
   а не в правом столбце. С 21.10.2026 строка не переносится, а выравнивается
   по верху: знаки и подписи — по верху имени, первой строки текста (ответ
   Алены на ревизию дерева, п. 5). Прежде нехватка шла третьей строкой во всю
   ширину, флажок и ручка стояли по центру имени, и мерка «по верху первой
   строки» краснела на каждой такой строке. */
.km-treerow--explained { align-items: flex-start; }

/* Что внутри у свёрнутого — иначе непонятно, что сворачиваешь. */
.km-count-in { font-size: 12px; color: var(--km-text-muted); white-space: nowrap; }

.km-rule { font-size: 12px; color: var(--km-text-muted); white-space: nowrap; }
.km-opt { font-size: 12px; color: var(--km-text-muted); white-space: nowrap; }

.km-tag {
  font-size: 10px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--km-text-secondary);
  background: var(--km-bg);
  border: 1px solid var(--km-border);
  border-radius: 5px;
  padding: 2px 6px;
  white-space: nowrap;
}

.km-tag--cohort {
  background: var(--km-warm-bg);
  border-color: var(--km-warm-bg);
  color: var(--km-accent-dark);
}

/* Тариф узла (4.3). Тон тот же, что у потока: оба говорят «видят не все»;
   различает их слово «Тариф» в самой метке, а не цвет. */
.km-tag--tariff {
  background: var(--km-warm-bg);
  border-color: var(--km-warm-bg);
  color: var(--km-accent-dark);
}

/* Звёзды узла в строке дерева — «★ N» перед типом (звёзды курса 1.9, «В дереве
   курса»; прототип «Редактор дерева»). Ноль — серой, без заливки. */
.km-tag--star {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
  color: var(--km-warm-text-strong);
  background: var(--km-star-bg);
  border-color: var(--km-star-border);
  border-radius: 6px;
  padding: 3px 7px;
  font-variant-numeric: tabular-nums;
}

.km-tag--star-zero { color: var(--km-text-muted); background: var(--km-surface); border-color: var(--km-border-soft); font-weight: 600; }

/* Блок «Звёзды» в панели узла — тёплой плашкой, два поля рядом. */
.km-tree-stars {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 14px;
  border: 1px solid var(--km-warm-border);
  background: var(--km-warm-bg);
  border-radius: 10px;
}

.km-tree-stars__row { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; }

.km-tree-stars .km-hint { margin: 0; }

.km-tree-stars__fix { padding-top: 10px; }

/* На узком экране правый столбец уезжает под название: три подписи рядом
   с именем не помещаются, а имя важнее их всех. Имя остаётся в первой строке
   рядом со знаками, а знаки — по её верху, как везде (ответ Алены 21.10.2026 на
   ревизию дерева, п. 5): прежде имя уходило второй строкой, знаки стояли одни,
   и мерка «по верху первой строки» краснела на каждой строке при 375. */
@media ( max-width: 640px ) {
  .km-treerow { align-items: flex-start; }
  .km-treerow__body { flex-wrap: wrap; row-gap: 6px; align-items: flex-start; }
  .km-treerow__text { flex: 1 0 100%; }
  .km-treerow__name { white-space: normal; }
  /* Метки правого столбца тоже переносятся: одним рядом «правило · поток ·
     тариф · тип» выходили за экран — эфир потока на 456 px, узел тарифа
     на 471 при окне 375. Замерено стендом редактора дерева 15 сентября 2026. */
  .km-treerow__meta { flex: 1 1 100%; min-width: 0; flex-wrap: wrap; row-gap: 6px; }
  .km-treerow--lesson { padding-left: 24px; }
  .km-treerow--topic { padding-left: 44px; }
}

.km-tree__module {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--km-border-soft);
}
.km-tree__module-title { font-family: var(--km-font-display); font-size: 20px; font-weight: 700; line-height: 1.3; }

.km-tree__lesson {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 20px 13px 52px;
  border-bottom: 1px solid var(--km-border-soft);
}
/* Строка с объяснением под ней: причина занимает **свою** строку целиком.
   Во флексе она вставала колонкой между кнопками и сжимала название
   до четырёх строк по слову. Модификатор, а не правка самой строки:
   тот же класс носят строки редактора дерева, где переносить нечего.
   Найдено глазами на стенде корзины 8 августа 2026. */
.km-tree__lesson--explained { flex-wrap: wrap; row-gap: 6px; }
.km-tree__lesson--explained .km-node__reason { flex: 1 0 100%; margin-left: 0; }
.km-tree__lesson-title { flex: 1; font-size: 15px; }

/* Уровень 3 — топики ВНУТРИ карточки своего занятия, на белом.
 *
 * Отступ 28 без черты — правка вёрстки 2, решение человека 8 августа 2026,
 * подтверждённое макетом v3. Число складывается из поля карточки (18)
 * и самого отступа (28): 46 слева, 18 справа, чтобы правый столбец топика
 * стоял под правым столбцом занятия.
 *
 * Довод против черты не «в макете так». Уровень уже сказан лестницей кегля
 * — 15/600 против 14/400 вторичным цветом, — и вертикальная черта повторяет
 * его вторым способом. На шести модулях подряд повтор превращается
 * в решётку, а сдвиг в 61 пиксель на 375 съедает шестую часть экрана. */
.km-tree__topics {
  display: flex;
  flex-direction: column;
  padding: 0 18px 6px 46px;
}

/* НАПРАВЛЯЮЩЕЙ В КОЛОНКЕ БОЛЬШЕ НЕТ. Решение человека 19 августа 2026,
   и оно ОТМЕНЯЕТ правку вёрстки 2 в части плеера.

   Черта была оставлена там по доводу: колонка узкая, лестница кегля в ней
   своя и мельче, и различать уровни нечем, кроме черты. Довод перестал
   быть верным в тот же день: занятие лежит в карточке с подложкой,
   уровень виден и без черты, а черта с отступом съедают ширину —
   на 283 пикселя это видно.

   Отступ заодно уменьшен с 27 (15 поля плюс 12 подбивки) до 14:
   освободившееся место отдано названиям. Половина их ломалась на две
   строки — это и было главным, что колонка теряла. */
.km-tree--compact .km-tree__topics {
  margin: 2px 0 4px 14px;
  padding: 0;
  border-left: none;
}
.km-tree__topic {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 20px 9px 12px;
  border-radius: 8px;
}
.km-tree__topic-title { flex: 1; font-size: 14px; }

/* Редактируемое дерево: вся строка открывает панель узла, и это видно.

   Модификатор, а не правило для всех: у ученика на карте строка ведёт
   ссылкой, и признак нажимаемости ей даёт сама ссылка. Здесь нажимаема
   строка целиком — до 9.7 слушатель висел на одном имени, то есть
   на четверти ширины, и ничем не был помечен. */
.km-tree--editable .km-tree__module,
.km-tree--editable .km-tree__lesson,
.km-tree--editable .km-tree__topic,
.km-tree--editable .km-row { cursor: pointer; }

/* --- Аккордеон модуля: ТОЛЬКО ПРОДАЮЩАЯ СТРАНИЦА И АДМИНКА ---
 *
 * В дереве ученика аккордеона больше нет: модуль стал строкой-заголовком
 * 19 августа 2026, а карточка одиночных узлов снята вместе с ним — она
 * и была белой рамкой со снимка того же дня. Правило `.km-tree > ...
 * .km-accordion__item` ушло отсюда: в `.km-tree` этот класс не попадает
 * ни при каком условии.
 *
 * Живые потребители: `ProgramBlocks` (страница гостя, включая `--bare`)
 * и `templates/admin/enrollments.php`. */
.km-accordion { display: flex; flex-direction: column; gap: 12px; }
.km-accordion__item {
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-card);
  box-shadow: var(--km-shadow-card);
  overflow: hidden;
}
.km-accordion__item--current { border-color: var(--km-warm-border); }

/* ОДИН БЛОК С РАЗДЕЛИТЕЛЯМИ вместо пяти карточек с воздухом.
 *
 * Макет `course-page-guest-v2.html`: `km-prog` — одна поверхность, модули
 * внутри разделены чертой. Правки просил человек: карточки разъезжались
 * зазором 12, у каждой своя тень, и список читался как пять несвязанных
 * блоков вместо одной программы.
 *
 * Модификатор, а не правка базы: тем же `km-accordion` собрана карта курса
 * (`course-map.js`), и там карточки — верное решение.
 *
 * ЧИСЛА ИЗ МАКЕТА:
 *   поверхность, рамка, радиус, тень — как у карточки, токенами;
 *   `overflow: hidden` — чтобы углы резали шапку первого модуля;
 *   черта между модулями — `--km-border-soft`, как в макете;
 *   шапка 18px 24px — у базы 18px 22px, взято макетное;
 *   отступ списка слева 68 = 24 (поле) + 30 (номер) + 14 (зазор), то есть
 *     строки занятий встают ровно под название, а не под номер.
 *
 * Что НЕ взято из макета и почему — названо, а не подогнано:
 *   название 20px против 17,5 у макета — половин пикселя шкала не знает,
 *     а 20 уже стоит на этом экране и принято;
 *   строки занятий 12px/12 против 9/11 у макета — это `km-lineup`, общий
 *     компонент четырёх экранов; ради трёх пикселей его не разводят.
 */
.km-accordion--joined {
  gap: 0;
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-card);
  box-shadow: var(--km-shadow-card);
  overflow: hidden;
}
.km-accordion--joined .km-accordion__item {
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}
.km-accordion--joined .km-accordion__item + .km-accordion__item {
  border-top: 1px solid var(--km-border-soft);
}
.km-accordion--joined .km-accordion__head { padding: 18px 24px; }

/* Название тянется, счёт уходит вправо — как в макете. У базы оба стоят
   столбиком в `__body-head`; здесь они в одной строке. */
.km-accordion--joined .km-accordion__title { flex: 1; min-width: 0; }
.km-accordion--joined .km-accordion__count { flex: none; white-space: nowrap; }

/* Строки встают под название, а не под номер. */
.km-accordion--joined .km-accordion__body { padding: 2px 24px 18px 68px; }

/* У безымянной группы номера нет — отступать не подо что. */
.km-accordion--joined .km-accordion__body--bare { padding-left: 24px; }

/* Кнопка «Развернуть всё» — своей строкой над блоком, прижата вправо.
   В макете она между заголовком и программой, а не рядом с заголовком. */
.km-accordion__above { display: flex; justify-content: flex-end; }

@media (max-width: 640px) {
  /* Под номер отступать нечем: 68 съедает треть ширины. */
  .km-accordion--joined .km-accordion__body { padding-left: 24px; }

  /*
   * ШАПКА НЕ РАСПАДАЕТСЯ НА ЧЕТЫРЕ СТРОКИ.
   *
   * Общее правило узкой шапки ставит детей столбиком, и до 1.135.0 их было
   * трое: номер, колонка «название + счёт», галка. Разведя название и счёт
   * в одну строку ради широкого экрана, я сделал детей четырьмя — и на 375
   * шапка вытянулась на четыре строки, с галкой отдельно внизу.
   *
   * Регрессия моя, найдена глазами на стенде, мерок на неё не было: «ничего
   * не вылезает за ширину» здесь правда, а высота шапки никем не мерилась.
   *
   * Здесь строка возвращается: номер, название и галка в ряд, счёт — под
   * ними, с отступом под название (44 = 30 номера + 14 зазора).
   */
  .km-accordion--joined .km-accordion__head {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 14px;
  }
  .km-accordion--joined .km-accordion__title { flex: 1 1 auto; }
  /*
   * `order` ставит счёт ПОСЛЕДНИМ в раскладке, не трогая разметку:
   * иначе перенос по 100% ширины уводил на третью строку галку,
   * стоящую в разметке после счёта. Строк выходило три вместо двух.
   */
  .km-accordion--joined .km-accordion__count { order: 1; flex: 1 0 100%; padding-left: 44px; }
}
.km-accordion__head {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 18px 22px;
  cursor: pointer;
}
.km-accordion__item--current .km-accordion__head { background: var(--km-warm-bg); }
.km-accordion__title { font-family: var(--km-font-display); font-size: 20px; font-weight: 700; line-height: 1.3; }
.km-accordion__count { font-size: 13px; color: var(--km-text-muted); }

/* Шапка модуля продающей страницы — по `design/course-page-guest.html`.
 *
 * Отличается от шапки на карте курса тремя вещами, и все три из макета:
 * кружок с номером слева, счёт ВТОРОЙ СТРОКОЙ под названием, шеврон справа.
 *
 * Шеврон важнее прочего: без него карточка ничем не показывает, что она
 * раскрывается, — шесть одинаковых плашек, и нажимать их незачем. Он же
 * и есть единственный признак состояния, поэтому поворачивается. */
.km-accordion__num {
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--km-warm-bg);
  color: var(--km-warm-text-strong);
  font-size: 14px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}

.km-accordion__body-head { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }

.km-accordion__chevron {
  flex: none;
  color: var(--km-text-muted);
  transition: transform .15s;
}

details[open] > .km-accordion__head .km-accordion__chevron { transform: rotate(180deg); }

/* «Развернуть всё» — у правого края, как в макете. */
.km-section__action { margin-left: auto; }

/* Строка модуля: иконка слева, три подписи, действие справа.
 *
 * Счёт и состояние стоят **второй строкой**, а не в надстрочнике: решение
 * человека 7 августа 2026. Надстрочник называет номер модуля, и дописанное
 * туда состояние («Модуль первый · пройден») читалось на 375 с висящей
 * точкой посреди фразы. */
.km-accordion__state { font-size: 13px; color: var(--km-text-muted); }
.km-accordion__item--current .km-accordion__state { color: var(--km-warm-text); }
.km-accordion__chevron { flex: none; color: var(--km-text-muted); transition: transform 0.18s; }
.km-accordion__item[open] .km-accordion__chevron { transform: rotate(180deg); }
/* Шапка модуля на карте: две строки слева, «посмотреть» справа.
   Разметка с design/course-map-v2.html — надстрочник, заголовок, признак
   сворачивания. Заведено в 9.6, кусок 3. */
.km-accordion__lines { display: flex; flex-direction: column; gap: 4px; flex: 1; }
.km-accordion__toggle { flex: none; font-size: 13px; color: var(--km-accent); }
.km-accordion__body { border-top: 1px solid var(--km-border-soft); padding: 6px 22px 14px; }
/* Тело без шапки — карточка одиночных узлов верхнего уровня (пункт 6 правок).
   Черта сверху здесь отделяла бы содержимое от края карточки, а не от шапки,
   которой нет; поле сверху берётся такое же, как снизу. */
.km-accordion__body--bare { border-top: none; padding-top: 14px; }
.km-accordion__item--current .km-accordion__body { border-top-color: var(--km-warm-border); }

/* Список занятий внутри модуля на продающей странице (7.4).

   Своя строка, а не `.km-row`: та рассчитана на форму — выравнивание
   по нижнему краю и подпись, прижатая вправо через `margin-left: auto`.
   На узком экране название переносилось, а подпись типа уезжала на свою
   строку к правому краю — и вставала между двумя названиями, не относясь
   ни к одному. Черта между строками нужна по той же причине: без неё
   список читается как сплошной текст. */
.km-lineup { display: flex; flex-direction: column; }
.km-lineup__item {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 12px 0;
}
.km-lineup__item + .km-lineup__item { border-top: 1px solid var(--km-border-soft); }
.km-lineup__title { flex: 1; font-size: 15px; line-height: 1.5; }
.km-lineup__type { flex: none; font-size: 12px; color: var(--km-text-muted); }

/* Перечень СО ЗНАКОМ: строка «знак — название». Макет
   `course-page-guest-v2.html`, пункт 3 правок 2 сентября 2026.

   Своя семья, а не `km-lineup--center`, и это найдено стендом на 375.
   `--center` рассчитан на список эфиров и работ: там в строке дата,
   название, пометка и ссылка, и на узком экране он ставит название
   **первым** (`order: -1`, во всю ширину), а остальное под ним. Знак
   при этом уезжал под название — то есть строка читалась «название,
   а под ним непонятный значок».

   Здесь в строке двое, и переносить нечего: знак остаётся слева на любой
   ширине. Тот же класс ошибки, что `km-table__row` в списке потоков —
   имя подошло, устройство нет.

   Знак рода в строке перечня.

   Заменяет собой подпись типа справа: та стояла у каждой строки и на курсе
   из восемнадцати занятий повторяла одно слово восемнадцать раз, то есть
   не различала ничего. Знак различает ровно там, где родов больше одного.

   Своего размера у `svg` внутри нет намеренно — его задаёт скрипт набора
   (1.122.0), как и на карте курса. Ширина здесь на случай, когда знак ещё
   не пришёл: без неё строки прыгали бы при отрисовке. */
.km-lineup--glyph .km-lineup__item { align-items: center; }
.km-lineup__glyph {
  flex: none;
  display: flex;
  width: 17px;
  height: 17px;
  color: var(--km-accent);
}

/* Тот же перечень, но со столбцом даты и пометкой: прошедшие эфиры (кусок 7)
   и работы по курсу (кусок 8). Форма у них одна, и это не совпадение —
   в макете это одна и та же карточка с одной и той же чертой между строками.

   `--center` вместо базового `baseline`: в строке стоит бейдж, и по базовой
   линии он съезжает вниз относительно названия. Базовое выравнивание
   оставлено как было — на продающей странице в строке только текст, и там
   базовая линия читается лучше. */
.km-lineup--center .km-lineup__item { align-items: center; }
.km-lineup__date { flex: none; width: 108px; font-size: 13px; color: var(--km-text-muted); }
/* Того, чего ещё не было, — приглушённым: в макете будущий эфир написан
   тем же серым, что и его дата. Так строка читается как «сюда пока незачем»,
   а не как ещё одна запись, которую забыли открыть. */
.km-lineup__title--ahead { color: var(--km-text-muted); }
/* Момент отправки работы прижат вправо — так в макете: пометка состояния
   стоит рядом с названием, а дата у самого края. */
.km-lineup__date--right { width: 120px; text-align: right; }
.km-lineup__link { flex: none; font-size: 13px; font-weight: 600; }
.km-lineup__badge { flex: none; }

/* Пометка в строке перечня («Запись», «Ещё не было», «Идёт трансляция») — не выше строки названия: без своей высоты
   строки она брала у темы 27 px и с полями выходила 37 px, и строка с пометкой была выше строки без неё (вкладка
   «Трансляции»; найдено вместе с плашкой потока на карте курса, слово Алены 14.10.2026). Сила (0,2,0) — поверх полей
   вида бейджа. */
.km-lineup .km-lineup__badge { line-height: 1.2; padding-top: 3px; padding-bottom: 3px; }

/* Ближайший эфир: кружок даты слева, название и время посередине,
   действия справа. Своя строка, а не `.km-headline`: у той левая колонка
   объявлена полосой прогресса, и переиспользование сделало бы имя враньём —
   ровно то, чем `.km-input-group` однажды прикинулся подписью над полем. */
.km-upnext {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}
.km-upnext__body { flex: 1; min-width: 220px; display: flex; flex-direction: column; gap: 4px; }
/* «Идёт прямой эфир» над названием — по тексту, а не во всю колонку. */
.km-upnext__body > .km-badge { align-self: flex-start; }
.km-upnext > .km-actions { flex: none; }
/*
 * Идёт трансляция — над названием плашка, и первая строка карточки — её слова. Листок даты встаёт по верху букв первой
 * строки (общее правило листка, слово Алены 12.10.2026; мерка `numberTops` стендов): по середине он опускался на 10 px
 * ниже (1280, найдено 16.10.2026). Карточка без плашки — как была: там первая строка — название, и по середине сходится.
 * 8 px — от верха плашки до верха её прописных «ИДЁТ»: поле 5 px и выступ строки над прописными (замер на 1280).
 *
 * Сдвиг — только пока листок стоит рядом с текстом. На узкой карточке (на 375 и до ~400) текст переносится под листок,
 * и листок стоит над названием — это не случай правила, и лишние 8 px сверху были бы пустотой. Решает ширина самой
 * карточки, а не окна: 284 = листок 48 + промежуток 16 + меньшая ширина текста 220 (`.km-upnext__body`).
 */
.km-upnext.km-upnext--live { align-items: flex-start; container: km-upnext / inline-size; }

@container km-upnext (min-width: 284px) {
	.km-upnext.km-upnext--live > .km-date-chip { margin-top: 8px; }
}

/* Приглашение: текст слева, одно действие справа. Заведено под «Поделитесь
   своим опытом» на вкладке «Отзывы» (кусок 9).

   Своя строка, а не `.km-upnext`: у той слева кружок даты и объявлен он
   в имени. Переиспользование сделало бы имя враньём — та же ловушка,
   какой `.km-input-group` однажды прикинулся подписью над полем. */
.km-invite {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
}
.km-invite__body { flex: 1; min-width: 240px; display: flex; flex-direction: column; gap: 5px; }
.km-invite > .km-btn { flex: none; }

/* --- Левое меню кабинета --- */
/* Боковое меню жило здесь под кабинет. Потребителя нет с монтирования:
   левую колонку рисует тема (BuddyPanel), и своя была бы второй такой же.
   Классы убраны, а не оставлены «на будущее» — дизайн-система описывает
   то, что на экранах есть, а не то, что могло бы пригодиться. */

/* --- Пустые состояния: приглашение, а не извинение --- */
/*
 * `.km-empty` бывает и абзацем, и коробкой — и поля браузера у абзаца
 * приходится гасить здесь.
 *
 * Найдено общей меркой стенда на пустом экране файлов: `p.km-empty` нёс
 * свои 16px сверху и снизу, а ритм колонки задаёт контейнер. Правило
 * обнуления рядом (строка 3360) накрывает `__title` и `__text`, а сам
 * блок — нет: его писали коробкой, и абзацем он стал позже, в шести
 * шаблонах сразу.
 *
 * Видно это стало только там, где элемент **показан**: спрятанный
 * измеряется правдоподобно, и мерка его пропускает.
 */
.km-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin: 0;
  text-align: center;
  padding: 40px 28px;
  background: var(--km-surface-alt);
  border: 1px dashed #D9E1EA;
  border-radius: var(--km-radius-card);
}
.km-empty:hover { border-color: var(--km-warm-border); }
.km-empty__icon {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--km-peach);
  color: var(--km-accent);
  display: flex;
  align-items: center;
  justify-content: center;
}
.km-empty__title { font-size: 17px; font-weight: 700; }
.km-empty__text { font-size: 14px; line-height: 1.6; color: var(--km-text-secondary); max-width: 320px; }

/* --- Пагинация --- */
.km-pagination { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.km-pagination__info { font-size: 13px; color: var(--km-text-muted); flex: 1; }
/* Ряд листания переносится: «Назад 1 … 19 20 21 … 418 Дальше» — девять
   кнопок, 500 пикселей, и на 375 без переноса страница уезжала вбок.
   Нашлось стендом «Клиентов» — первого экрана, где этот ряд живой. */
.km-pagination__list { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.km-page-btn {
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  color: var(--km-text);
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-control);
  padding: 9px 14px;
  cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.km-page-btn:hover { border-color: var(--km-warm-border); color: var(--km-accent); }
.km-page-btn.is-active {
  background: var(--km-accent);
  border-color: var(--km-accent);
  color: #fff;
  font-weight: 700;
}
.km-page-btn[disabled] { color: #C9D3DE; background: var(--km-surface); border-color: var(--km-border); cursor: not-allowed; }
.km-page-gap { font-size: 13px; color: var(--km-text-muted); padding: 0 4px; }
.km-page-jump { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--km-text-secondary); }
.km-page-jump .km-input { width: 72px; padding: 8px 10px; font-size: 13px; text-align: center; }

/* --- Подсказка поиска: список найденного под полем ---

   Заведена для выбора материала в панели узла (9.7). До неё поле «Материал»
   принимало пятнадцатизначный номер записи и больше ничего: понять, что за
   материал выбран и где его взять, было нельзя ни при правке, ни при
   заведении узла.

   Строка списка — `button`, а не `div` с обработчиком: список выбирают
   и с клавиатуры, а кнопка умеет это сама. */
.km-suggest {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-control);
  background: var(--km-surface);
  box-shadow: var(--km-shadow-card);
  max-height: 260px;
  overflow-y: auto;
}
.km-suggest__item {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 10px 14px;
  border: none;
  border-bottom: 1px solid var(--km-border-soft);
  background: transparent;
  font-family: inherit;
  font-size: 15px;
  line-height: 1.4;
  color: var(--km-text);
  text-align: left;
  cursor: pointer;
}
.km-suggest__item:last-child { border-bottom: none; }
.km-suggest__item:hover,
.km-suggest__item:focus { background: var(--km-warm-bg); outline: none; }
.km-suggest__where { font-size: 12px; line-height: 1.4; color: var(--km-text-muted); }
.km-suggest__empty { padding: 12px 14px; font-size: 14px; color: var(--km-text-secondary); }

/* Занятое место материала — тем же тёплым, что и всё «обрати внимание».
   Не тревожным: материал в двух курсах это норма (правило 1), а не ошибка. */
.km-suggest__taken { color: var(--km-warm-text-strong); }

/* --- Всплывающая панель сбоку ---

   `fixed`, а не `absolute` и не поток. Бриф 1.6 говорит «открывается сбоку»,
   и до 9.7 это держалось на том, что панель стояла последним блоком страницы:
   на пяти узлах стенда она попадала в окно сама собой, а на боевых 188 —
   уезжала на десять тысяч пикселей вниз. Человек нажимал на узел, экран
   сереел затемнением, и больше не происходило ничего.

   Затемнение тоже `fixed`: `absolute` без положенного предка считается
   от начала документа, то есть накрывает первый экран, а не тот, на который
   человек смотрит.

   Числа z-index не выдуманы: в админке WordPress `#adminmenuwrap` стоит
   на 9990, `#wpadminbar` — на 99999. Панель обязана быть выше обоих, иначе
   её кнопка закрытия уходит под верхнюю полосу и закрыть панель нечем. */
.km-drawer-scrim {
  position: fixed;
  inset: 0;
  z-index: 100000;
  background: rgba(63, 76, 92, 0.28);
}
.km-drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 100001;
  display: flex;
  flex-direction: column;
  width: 480px;
  max-width: 100%;
  background: var(--km-surface);
  border-left: 1px solid var(--km-border);
  box-shadow: var(--km-shadow-lift);
}
.km-drawer__head {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 20px 24px;
  border-bottom: 1px solid var(--km-border);
}
.km-drawer__title { font-family: var(--km-font-display); font-size: 24px; font-weight: 700; line-height: 1.3; }
.km-drawer__close {
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: var(--km-radius-control);
  border: 1px solid var(--km-border);
  background: var(--km-surface);
  color: var(--km-text-secondary);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.km-drawer__close:hover { border-color: var(--km-warm-border); color: var(--km-accent); }
.km-drawer__body {
  flex: 1;
  overflow-y: auto;
  padding: 22px 24px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}
/* Группа полей внутри панели (блок «Эфир» и его поля без трансляции):
   тот же зазор, что у прямых детей `.km-drawer__body`. Без неё поля группы
   стояли вплотную — с 6.2, а заметно стало 28.09.2026, когда под полем
   «Трансляция» появилась строка поиска. */
.km-drawer__group {
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.km-drawer__foot {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 24px;
  border-top: 1px solid var(--km-border);
  background: var(--km-surface-alt);
}
.km-drawer__foot .km-drawer__spacer { flex: 1; }
/* Отказ при сохранении — над подвалом, вне прокрутки тела: виден, где бы ни стояла прокрутка панели. */
.km-drawer__alert { padding: 12px 24px; border-top: 1px solid var(--km-border); }

/* Строка контролов: кнопки и поля в ряд, с переносом на узком.
   Заведена для шапки экрана зачислений — в макете кнопки стоят строкой,
   а `.km-stack` ставит столбиком. */
.km-row {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-end;
	gap: 10px;
}

.km-row > .km-btn {
	flex: none;
}

/*
 * Строка полей, выровненная по верху.
 *
 * У обычной строки выравнивание по низу — так кнопка встаёт на одну линию
 * с полем. Но если под одним полем есть пояснение, по низу выравнивается
 * оно, и соседние поля разъезжаются по высоте: подписи «Продаётся с»
 * и «Продаётся до» оказываются на разных уровнях. Нашлось глазами
 * на стенде предложений (3.6).
 */
.km-row--top {
	align-items: flex-start;
}

/*
 * Строка, выровненная по середине: кнопка и оговорка рядом с ней.
 *
 * У обычной строки выравнивание по низу — так кнопка встаёт на одну линию
 * с полем. Рядом с кнопкой поля нет, а есть строка текста, и по низу она
 * прилипает к самому краю кнопки.
 */
.km-row--middle {
	align-items: center;
}

/*
 * Строка из флагов. У обычной строки поля выровнены по низу — так подпись
 * и поле стоят на одной линии. Флагам это не годится: у них подпись сбоку,
 * и по низу они разъезжаются, когда у одного пояснение в две строки.
 * Отступ больше обычного: между «Бесплатное» и «Один раз на человека»
 * должно быть видно, что это два разных вопроса.
 */
/*
 * Перечень: сводка перед необратимой операцией, состав чего-либо.
 * Маркер точкой, а не своей картинкой: список читают, а не разглядывают.
 */
.km-list {
	margin: 0;
	padding-left: 20px;
	display: flex;
	flex-direction: column;
	gap: 6px;
	font-size: 15px;
	line-height: 1.6;
	color: var(--km-text);
}

.km-list li {
	list-style: disc;
}

.km-row--flags {
	align-items: flex-start;
	gap: 10px 28px;
}

/* Поле внутри строки компактно.

   Само по себе `.km-field` — колонка, и поле в ней растягивается на всю
   ширину родителя: на странице в 1180 пикселей поиск и селекты уезжали
   от края до края. Фильтру столько не нужно, ему нужно ровно столько,
   сколько занимает значение. */
.km-row > .km-field {
	flex: 0 1 240px;
	min-width: 180px;
}

.km-row > .km-field--wide {
	flex: 1 1 320px;
	max-width: 460px;
}

/* ---------------------------------------------------------------------------
   Узкий экран
   ---------------------------------------------------------------------------

   Раздел 12.4 спецификации: экраны ученика проектируются от узкого,
   административные просто не должны разваливаться. Правило для таблиц —
   строка перестаёт быть таблицей и становится карточкой. Горизонтальная
   прокрутка таблицы шириной в тысячу пикселей не годится: на телефоне она
   выглядит сломанной, даже когда технически работает.

   Карточка собрана по мобильному макету `design/course-map-v2-mobile.html`:
   главное сверху крупным, остальное парами «подпись — значение», длинное
   обрезается многоточием, а не переносится в три строки.
   --------------------------------------------------------------------------- */

/* --- Плеер: две колонки только там, где колонке чтения хватает места ---
 *
 * Перелом свой, шире общего в 640, и это решение по числам, а не по вкусу.
 *
 * Колонка навигации 320 пикселей и не сжимается — в ней имена занятий.
 * Значит на 768 читальной колонке остаётся 400, на 1024 — 650. Планшет
 * попадал ровно в эту щель: две колонки формально были, а читать в них
 * было нечем.
 *
 * **Арифметика здесь была неверной, и это правлено вместе с шириной
 * колонки.** Стояло «1100 — то, ниже чего 780 не помещается», а 780 плюс
 * 320 навигации плюс 56 полей это 1156: на 1100 читальной достаётся 725,
 * и никогда не доставалось больше. Комментарий обещал вычисление, которого
 * код не делал, — ровно то, из-за чего через год уберут настоящую защиту,
 * приняв объяснение за неё.
 *
 * Что верно: 1100 — **решение**, проверенное глазами на 768, 1024 и 1440,
 * а не следствие ширины колонки. Потолок в 980 набирается от 1356 и выше;
 * между 1100 и 1356 читальная колонка уже двух колонок, но всё ещё шире
 * планшетной щели, ради которой перелом и заводился. Двигать его вслед
 * за 980 значило бы отобрать вторую колонку у ноутбуков 1280, чего никто
 * не просил.
 *
 * Ниже перелома плеер становится одной колонкой со створкой — тем же
 * видом, что на телефоне, и по той же причине: текст важнее оглавления,
 * а оглавление достаётся нажатием.
 *
 * Число названо здесь и продублировано в `lesson.js`: створку закрывает
 * скрипт, и второго места, где решают «узко ли», не заводится — оно
 * спрашивает медиазапрос, а не считает ширину само.
 */
@media (max-width: 1100px) {
	.km-player {
		grid-template-columns: minmax(0, 1fr);
		min-height: 0;
	}

	.km-player__side {
		position: static;
		height: auto;
		overflow-y: visible;
		border-right: none;
		border-bottom: 1px solid var(--km-border);
		padding: 16px 18px 18px;
	}

	.km-player__main { padding: 24px 24px 80px; }

	/* Створка появляется вместе с одной колонкой.
	 *
	 * Это **единственный** путь к оглавлению на телефоне, поэтому она
	 * собрана как control, а не как заголовок: рамка, знак слева, слово
	 * справа. Прежняя редакция была строкой в семнадцать пикселей с серым
	 * треугольником у края — на экране это читалось разделом, а не дверью.
	 *
	 * Маркер браузера убран: его треугольник рисуется по-разному в каждом
	 * и не попадает в дизайн-систему ни в одном. Свой знак нарисован
	 * разметкой и потому одинаков везде. */
	.km-player__toggle {
		display: flex;
		align-items: center;
		gap: 10px;
		cursor: pointer;
		list-style: none;
		background: var(--km-surface);
		border: 1px solid var(--km-border);
		border-radius: var(--km-radius-control);
		padding: 12px 16px;
	}

	.km-player__toggle::-webkit-details-marker { display: none; }

	.km-player__toggle-title {
		flex: 1;
		min-width: 0;
		font-family: var(--km-font-display);
		font-size: 17px;
		font-weight: 700;
	}

	/* Слово следует за состоянием — его ставит `lesson.js`. Акцентом,
	   как «Открыть» у шапки модуля: одно и то же действие на одном экране
	   не должно выглядеть двумя разными. */
	.km-player__toggle-state {
		flex: none;
		font-size: 13px;
		font-weight: 600;
		color: var(--km-accent);
	}

	.km-player__toggle-chevron {
		flex: none;
		display: block;
		color: var(--km-accent);
		transition: transform 0.18s;
	}

	.km-player__side[open] .km-player__toggle-chevron { transform: rotate(180deg); }

	/* Створка называется так же, как заголовок карты, и на узком они
	   встают друг под другом: «Программа курса» дважды подряд. На широком
	   створки нет, и заголовок нужен — поэтому прячется он, а не она. */
	.km-player__side .km-section-title { display: none; }
}

@media (max-width: 640px) {
	.km-player__main { padding: 20px 18px 72px; }
}

@media (max-width: 640px) {
  /* Шапка модуля складывается: «посмотреть» уходит под подписи.
     На 375 оно стояло справа в одну строку с названием и отнимало
     ширину — «1. Планетарные Места Вознесения» переносилось на две
     строки, а надстрочник разрывался посреди фразы, оставляя висящую
     точку: «МОДУЛЬ ПЕРВЫЙ ·» и «ПРОЙДЕН» на разных строках.

     Ни одна мерка этого не поймала: «ничего не вылезает за ширину» и
     «подписи стоят на одном уровне» здесь правда, а читаемость они
     не мерят. Найдено глазами на настоящем курсе, 7 августа 2026. */
  .km-accordion__head { flex-direction: column; align-items: flex-start; gap: 8px; }
  .km-accordion__lines { width: 100%; }

	/*
	 * Полоса действий переносится по строкам.
	 *
	 * Кнопок в ней столько, сколько действий у экрана, и на узком они
	 * не помещаются в строку никогда: пять уезжают за край экрана вдвое.
	 * Прокрутка, как у чипов, тут не годится — уехавшее действие человек
	 * просто не найдёт, а «Отчислить» находить надо. Дефект жил с 2.8
	 * и не ловился стендом, потому что полоса спрятана, пока никто
	 * не выбран: измерять было нечего.
	 */
	.km-sticky-bar {
		flex-wrap: wrap;
		gap: 10px;
		padding: 12px 16px;
	}

	/* Строка узла на узком экране переносится, а не вылезает за край.
	   Название, метки потока и необязательности, подпись состояния — на широком
	   это одна строка, на телефоне в неё не помещается ничего. Нашлось стендом
	   карты курса: «Открыто» уезжало за правый край и тянуло страницу вбок.
	   Заголовок занимает строку целиком, метки и подпись встают под ним. */
	.km-node {
		flex-wrap: wrap;
		row-gap: 4px;
	}

	/* Кружок и название остаются в одной строке: разнесённые по разным,
	   они читаются как два разных узла. Переносится то, что можно отложить, —
	   подпись состояния и метки. */
	.km-node__title {
		flex: 1 1 auto;
		min-width: 0;
	}

	/* И причина закрытия — строкой целиком, под названием. Она длиннее
	   всего, что переносится рядом: «Откроется, когда вы заполните «Отзыв
	   о курсе»» не делит 375 пикселей с названием ни при каком выравнивании.

	   Встаёт она ПОД НАЗВАНИЕМ, а не под знаком: отступ складывается
	   из знака — он свой на каждом уровне, потому переменной — и зазора
	   строки занятия. */
	.km-node__why {
		flex: 1 0 100%;
		max-width: none;
		text-align: left;
		padding-left: calc( var( --km-node-glyph ) + 12px );
		order: 2;
	}

	/* ПЛАШКИ ПОТОКА И «ПО ЖЕЛАНИЮ» — СТРОКОЙ ПОД НАЗВАНИЕМ. Правка Алены
	   1 октября 2026: «Сентябрь 2026» в строке эфира наезжал на длинное
	   название. Ссылка с названием растёт от нуля (`flex: 1`), строка
	   потому не переносилась, и название сжималось в столбец шириной
	   в слово рядом с плашкой.

	   Отступ и порядок — как у причины закрытия строкой выше: под
	   названием, а не под знаком. Состояние справа («вы здесь», дата
	   эфира) остаётся в строке названия: `order` уводит вниз только
	   плашки и причину. */
	.km-node__tags {
		display: flex;
		flex: 1 0 100%;
		flex-wrap: wrap;
		align-items: center;
		gap: 6px;
		order: 1;
		padding-left: calc( var( --km-node-glyph ) + 12px );
	}

	/* И зазор между строками у занятия свой, мельче бокового.
	   `gap: 12px` у строки занятия ставит оба сразу, а двенадцать пикселей
	   между названием и причиной под ним — это ровно то раздувание,
	   от которого правка. Между колонками они по-прежнему нужны. */
	.km-tree__card > .km-node,
	.km-tree__fold-head > .km-node { row-gap: 4px; }

	/*
	 * СТРЕЛКА, НАЗВАНИЕ И ОТМЕТКА ЗАНЯТИЯ С ЧАСТЯМИ — В ОДНОЙ СТРОКЕ. Найдено 14.10.2026 снимком боевого: на 375
	 * у «1.1 Энергетическая система человека» стрелка стояла отдельной строкой над названием, галочка — под ним.
	 * Ссылка в шапке складки шириной по названию (`flex: 0 1 auto` выше — чтобы пустое место строки раскрывало
	 * складку), а строка на узком переносится: длинное название целиком не помещалось рядом со стрелкой и уезжало
	 * вниз вместе со всем после него.
	 *
	 * Здесь ссылка занимает остаток строки и переносит название внутри себя, а нажатия по пустому месту по-прежнему
	 * достаются складке: сама ссылка их не ловит, ловит только название. Название — шириной по тексту.
	 */
	.km-tree__fold-head > .km-node .km-node__link { flex: 1 1 0; pointer-events: none; }
	.km-tree__fold-head > .km-node .km-node__link > * { pointer-events: auto; }
	.km-tree__fold-head > .km-node .km-node__title { flex: 0 1 auto; }

	/*
	 * То же самое у строк редактора дерева, и нашлось это только в 6.2 —
	 * первым стендом этого экрана. Стендов у него не было вовсе: написан
	 * он в первом этапе, когда их не заводили, а потом писали к новым
	 * экранам. Строка узла несёт название, тип, поток, правило открытия,
	 * обязательность и нехватку словами — на телефоне это не помещается
	 * никогда, и до 6.2 просто уезжало за край.
	 *
	 * Заголовок занимает строку целиком, метки встают под ним: то же
	 * решение, что у карты курса выше.
	 */
	.km-tree__module,
	.km-tree__lesson,
	.km-tree__topic {
		flex-wrap: wrap;
		row-gap: 6px;
	}

	/*
	 * Название остаётся в одной строке с ручкой перетаскивания: разнесённые
	 * по разным, они читаются как две строки списка, а ручка — как пустая
	 * строка ни о чём. Переносится то, что можно отложить, — метки, подпись
	 * правила и нехватка словами.
	 */
	.km-tree__module-title,
	.km-tree__lesson-title,
	.km-tree__topic-title {
		flex: 1 1 auto;
		min-width: 0;
	}

	.km-tree__lesson { padding-left: 32px; }

	/*
	 * Строка перечня с датой на узком: название сверху, всё остальное под ним.
	 *
	 * Дата, название, пометка и ссылка в одну строку на 375 не помещаются
	 * никогда: столбец даты в 108 пикселей съедает треть экрана.
	 *
	 * Порядок меняется, и это решение, а не следствие переноса. `flex-wrap`
	 * переносит **раньше**, чем сжимает, — и без `order` строка складывалась
	 * по-разному от длины названия: короткое оставалось рядом с датой,
	 * длинное уезжало на свою строку, а пометка на третью. Три строки у одной
	 * записи и две у соседней читаются как разные списки.
	 *
	 * Теперь у всех одинаково: название целой строкой, под ним дата,
	 * пометка и ссылка. Порядок чтения экранным диктором остаётся прежним —
	 * он идёт по разметке, а не по `order`.
	 */
	.km-lineup--center .km-lineup__item {
		flex-wrap: wrap;
		row-gap: 6px;
	}

	.km-lineup--center .km-lineup__title {
		order: -1;
		flex: 1 1 100%;
	}

	.km-lineup__date { width: auto; }
	.km-lineup__date--right { width: auto; text-align: left; }

	/*
	 * Действия карточки эфира уходят под текст, а не сжимаются.
	 *
	 * `flex: none` держит их шириной содержимого, и на 375 «Страница эфира»
	 * с «В календарь» не помещаются рядом никогда: вторая уезжала за край
	 * экрана на десять пикселей. Общая мерка ширины про это молчала —
	 * она снималась на вкладке «Курс», а вылезало на «Трансляциях».
	 */
	.km-upnext > .km-actions {
		flex: 1 1 100%;
	}

	/*
	 * Плеер на узком — одна колонка, навигация сверху и свёрнутая.
	 *
	 * Липкую колонку в 320 пикселей на телефон не поставить, а развёрнутое
	 * дерево из сорока строк над занятием означает, что до текста человек
	 * доберётся прокруткой в полтора экрана. Раздел 12.4: плеер на телефоне —
	 * основной способ пользоваться системой, а не запасной.
	 */
	/* Полоса действий занятия переносится: три кнопки в строку не встают. */
	.km-lesson-nav > .km-btn,
	.km-lesson-nav__middle { flex: 1 1 100%; }

	.km-lesson-nav__middle { justify-content: stretch; }

	/* Карточка «Дальше» встаёт столбиком: название и длительность
	   в одну строку не помещаются и обрезались бы до половины. */

	/*
	 * Кабинет и страница курса на узком — одна колонка.
	 *
	 * Сайдбар курса уходит вниз: там счётчики и трекер, они второстепенны
	 * по замыслу. Кабинет одноколоночный на любой ширине — левое меню
	 * рисует тема.
	 */
	.km-course {
		grid-template-columns: minmax(0, 1fr);
		gap: 24px;
	}

	/* Одна колонка — липнуть нечему: сайдбар встаёт под содержимым,
	   и прилипший он закрыл бы собой конец дерева. */
	.km-course__side { position: static; top: auto; }

	.km-hero__title { font-size: 24px; }
	.km-hero__body { padding: 16px 18px 18px; }

	/* Наложение на 375: сорок два пикселя заголовка съедают экран целиком,
	   а 280 пикселей высоты при коротком названии дают полосу пустой
	   картинки под текстом. Высоту держит содержимое. */
	.km-hero--over .km-hero__title { font-size: 26px; }
	.km-hero--over .km-hero__body { min-height: 0; padding: 20px 18px 22px; gap: 10px; }

	/* Фирменная шапка на узком. Свои правила нужны потому, что селектор
	   `.km-hero--brand.km-hero--over` весом (0,2,0) перебивает соседние
	   правила этого же медиазапроса, — и 58px уехали бы на 375. */
	.km-hero--brand.km-hero--over .km-hero__title { font-size: 34px; }
	/* НА УЗКОМ У ТЕЛА СВОЯ ВЫСОТА, И ОНА НЕ НОЛЬ.
	   Настольные 374 сюда протекали по весу — (0,3,0) против (0,2,0)
	   у общего `min-height: 0` — и оставляли под именем ведущей полосу
	   пустого места. А ноль вместо них вернул прыжок: разметка едет
	   пустой, и шапка подрастала в тот миг, когда приходил ответ.
	   200 — измеренная высота заполненного тела на 375. */
	.km-hero--brand.km-hero--over .km-hero__body { padding: 18px 18px 20px; gap: 4px; min-height: 200px; }
	.km-hero--brand .km-hero__eyebrow { font-size: 11px; letter-spacing: 0.1em; }
	.km-hero--brand.km-hero--over .km-hero__lead { font-size: 14px; max-width: none; }
	/* НА УЗКОМ ШАПКА НЕ НАКЛАДЫВАЕТСЯ, А СТАНОВИТСЯ ДВУМЯ ЭТАЖАМИ.
	   Найдено глазами на стенде: надзаголовок, две строки заголовка,
	   двухстрочная подпись и имя ведущей не помещаются в 211 пикселей
	   картинки, тело оказывается выше её — и текст вываливается ниже
	   снимка на фон страницы. Сама разметка при этом права, и ни одна
	   мерка на ширину этого не видит: за край ничего не уезжает. */
	/* НА УЗКОМ ОБЛОЖКА ПОКАЗЫВАЕТСЯ ЦЕЛИКОМ, БЕЗ ОБРЕЗКИ ВОВСЕ.
	   Стояло `aspect-ratio: 16 / 9`, и это резало по бокам: обложка
	   «Пробуждения чакр» — 3:1, в коробку 1.78:1 она влезает только
	   потерей 110 пикселей слева и справа. Справа у неё лотос, то есть
	   весь сюжет. Найдено меркой обрезки, заведённой в тот же день.

	   Пропорция снята, высоту задаёт сама картинка: здесь она стоит
	   отдельным этажом, и обрезать её незачем — места под ней столько,
	   сколько нужно. */
	.km-hero--brand.km-hero--over .km-hero__cover {
		position: static;
		aspect-ratio: auto;
		height: auto;
	}

	.km-hero--brand.km-hero--over .km-hero__cover img { height: auto; }

	.km-hero--brand.km-hero--over .km-hero__body {
		background: var(--km-surface);
		border: 1px solid var(--km-border);
		border-top: none;
		border-radius: 0 0 var(--km-radius-card) var(--km-radius-card);
	}

	/* НА УЗКОМ ОБА ВИДА ВЫГЛЯДЯТ ОДИНАКОВО, И ЭТО НЕ УПРОЩЕНИЕ.
	   Тело съехало на белую карточку, значит белый текст на нём не виден
	   вовсе — светлый вид пропадал целиком. Затемнение там тоже ни к чему:
	   затемнять нечего, картинка выше. Цвет берётся тёмный у обоих. */
	.km-hero--brand.km-hero--lume.km-hero--over::after { content: none; }
	.km-hero--brand.km-hero--lume .km-hero__eyebrow { color: var(--km-brand-navy); }
	.km-hero--brand.km-hero--lume.km-hero--over .km-hero__title { color: var(--km-brand-navy); }
	.km-hero--brand.km-hero--lume .km-hero__title-rest { color: var(--km-brand-teal); }
	.km-hero--brand.km-hero--lume.km-hero--over .km-hero__lead { color: var(--km-brand-navy); }
	.km-hero--brand.km-hero--lume .km-hero__author { color: var(--km-brand-navy); }

	/* ЦЕНА И СЧЁТ КУРСАНТОВ — ПО ТОЙ ЖЕ ПРИЧИНЕ И В ТУ ЖЕ СТОРОНУ.
	   Правка 8 сентября 2026, найдена глазами на 375.

	   Правила выше вернули тёмный цвет заголовку, подписи и имени
	   ведущей — а цена и счёт курсантов остались белыми с
	   `.km-hero--over` и пропали на белой карточке целиком. Мерка
	   «цена и кнопка в шапке» при этом зелена: элемент на месте,
	   он просто невидим. Записанный класс — признак существует
	   не тогда, когда поставлен, а когда отличается от подложки.

	   Цвета не выдуманы: это те самые, что стоят у `.km-price`,
	   `.km-price__from`, `.km-price__stages` и `.km-meta` по умолчанию.
	   Кегль не трогаем — он про размер, а не про видимость. */
	.km-hero--brand.km-hero--over .km-price { color: var(--km-text); }
	.km-hero--brand.km-hero--over .km-price__from { color: var(--km-text-muted); }
	.km-hero--brand.km-hero--over .km-price__stages { color: var(--km-text-secondary); }
	.km-hero--brand.km-hero--over .km-meta { color: var(--km-text-muted); }
	/* Подпись под ценой («или в два платежа») — по той же причине. Она
	   появилась 19 сентября, позже этого правила, и в список не попала:
	   белая на белой карточке, на боевом 375 её не было видно вовсе
	   (снимки «Энергетического апгрейда» и «Практикума Принятия»
	   1 октября 2026). Цвет — тот же, что у `.km-price__note` по умолчанию. */
	.km-hero--brand.km-hero--over .km-price__note { color: var(--km-text-muted); }

	/* У ГОСТЯ — ЦВЕТОМ ПОДЗАГОЛОВКА, как и шире 640 (правка Алены 2 октября
	   2026): на узком подзаголовок и автор у обоих видов тёмно-синие, и цена,
	   подпись под ней и счётчик — им в тон, а не серым. Вес (0,4,0) сильнее
	   правил строками выше (0,3,0). */
	.km-page--guest .km-hero--brand.km-hero--over .km-price,
	.km-page--guest .km-hero--brand.km-hero--over .km-price__from,
	.km-page--guest .km-hero--brand.km-hero--over .km-price__stages,
	.km-page--guest .km-hero--brand.km-hero--over .km-price__note,
	.km-page--guest .km-hero--brand.km-hero--over .km-hero__learners .km-meta { color: var(--km-brand-navy); }

	/* Кнопки полосы прогресса переносятся, а не уезжают за край:
	   «Продолжить обучение» и «Карта курса» в 375 рядом не помещаются. */
	.km-headline > .km-actions { flex: 1 1 100%; flex-wrap: wrap; }
	.km-headline > .km-actions > .km-btn { flex: 1 1 auto; justify-content: center; }

	/* Затемнение глубже и ровнее, чем на широком.
	 *
	 * Градиент задан долями высоты шапки: на широком текст занимает её
	 * верхнюю треть и лежит на тёмном, а на узком заголовок переносится
	 * на две строки и текст занимает её почти целиком — подзаголовок
	 * доезжает туда, где прозрачность уже 0.1. На светлой части обложки
	 * он там пропадает, и найдено это глазами, а не меркой: «текст белый»
	 * и «текст поверх обложки» обе остаются правдой.
	 *
	 * Мобильной шапки макет не рисует вовсе, поэтому это решение, а не
	 * воспроизведение: читаемость важнее верности долей. */
	.km-hero--over::after {
		background: linear-gradient(
			to bottom,
			rgba(63, 52, 46, 0.72) 0%,
			rgba(63, 52, 46, 0.5) 100%
		);
	}

	/* Вкладки уезжают прокруткой: пять штук в 375 не помещаются никогда. */
	.km-tabs {
		flex-wrap: nowrap;
		overflow-x: auto;
		gap: 18px;
		-webkit-overflow-scrolling: touch;
		scrollbar-width: none;
	}

	.km-tabs::-webkit-scrollbar { display: none; }
	.km-tabs > * { flex: none; }

	/* Чипы уезжают прокруткой, а не переносятся столбиком. */
	.km-chips {
		flex-wrap: nowrap;
		overflow-x: auto;
		-webkit-overflow-scrolling: touch;
		scrollbar-width: none;
		padding-bottom: 2px;
	}

	.km-chips::-webkit-scrollbar {
		display: none;
	}

	.km-chips > * {
		flex: none;
	}

	/* На узком компактность ни к чему: поле занимает строку целиком. */
	.km-row > .km-field,
	.km-row > .km-field--wide {
		flex: 1 1 100%;
		max-width: none;
	}

	/* Таблица становится списком карточек.
	 *
	 * `display: block` у самой таблицы обязателен. Ниже блочными становятся
	 * строки и ячейки, а сам элемент оставался таблицей — и продолжал
	 * подбирать ширину по содержимому, а не по контейнеру. Пока подписи
	 * столбцов были короткими, это не проявлялось; на воронке отчётов
	 * («Отвал перед узлом» рядом со значением) карточка вылезла за край
	 * экрана и потянула страницу вбок — ровно то, что отвергает раздел 12.4.
	 * Дефект жил с 2.8 на каждом экране и ждал строки подлиннее. */
	.km-table,
	.km-table-scroll {
		display: block;
		overflow-x: visible;
		background: none;
		border: none;
		box-shadow: none;
		border-radius: 0;
	}

	.km-table thead {
		display: none;
	}

	.km-table tbody,
	.km-table tr,
	.km-table td {
		display: block;
		width: auto;
	}

	.km-table tr {
		position: relative;
		margin-bottom: 10px;
		padding: 14px 16px;
		background: var(--km-surface);
		border: 1px solid var(--km-border);
		border-radius: 14px;
		box-shadow: var(--km-shadow-card);
	}

	.km-table td {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: 12px;
		padding: 3px 0;
		border: none;
	}

	/* Подпись столбца переезжает в строку карточки. */
	.km-table td[data-label]::before {
		content: attr(data-label);
		flex: none;
		font-size: 12px;
		color: var(--km-text-secondary);
	}

	/* Первая ячейка — выбор, вторая — имя: они держат верх карточки. */
	.km-table td:first-child {
		position: absolute;
		top: 14px;
		right: 16px;
		padding: 0;
	}

	.km-table td:nth-child(2) {
		display: block;
		padding-right: 28px;
		padding-bottom: 8px;
	}

	.km-table td:nth-child(2) .km-text {
		font-size: 15px;
		font-weight: 700;
	}

	/*
	 * Таблица, у которой первая ячейка — название, а не выбор.
	 *
	 * Правила выше написаны под список зачислений: там первой идёт клетка
	 * с флажком, и на узком экране она уезжает в правый верхний угол
	 * карточки, а вторая — имя — держит её верх. Там, где первой стоит
	 * название, то же правило кладёт его поверх следующей строки: в карточке
	 * «Тип» и «Предложение» оказываются друг на друге. Нашлось глазами
	 * на стенде предложений (3.6) — измерения этого не видели, потому
	 * что мерили ширину и наличие, а не пересечение ячеек.
	 */
	.km-table--title-first td:first-child {
		position: static;
		display: block;
		padding: 0 0 8px;
	}

	.km-table--title-first td:first-child::before {
		content: none;
	}

	.km-table--title-first td:nth-child(2) {
		display: flex;
		padding-right: 0;
	}

		/*
	 * Столбец строк внутри ячейки прижимается к правому краю — туда же,
	 * куда `space-between` уводит одиночное значение. Иначе строка
	 * с рассрочкой висела бы слева, а цена справа.
	 *
	 * СУЖЕНО ДО ТАБЛИЦЫ 17 сентября 2026. Без `.km-table` правило доставало
	 * до карточки зачисления: строки её лент переставали растягиваться,
	 * прижимались вправо, и длинная уезжала за ЛЕВЫЙ край карточки и экрана
	 * (лента «Прогресс» — с 9 px при карточке с 28, фраза журнала — за край
	 * экрана). Тот же класс с двумя смыслами, что абзацем ниже.
	 */
	.km-table .km-lines { align-items: flex-end; }

	/* Значение справа не переносится в три строки, а обрезается. */
	.km-table td > span,
	.km-table td > div {
		min-width: 0;
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}

	.km-table td:nth-child(2) > div {
		white-space: normal;
	}
}

/* ─── Карточка предложения ──────────────────────────────────────────────────
 *
 * Макет `design/offers-screen-v1.html`, принят 20 августа 2026. Заменила
 * строку таблицы на экране предложений.
 *
 * Номер стоит первым и набран моноширинным: им заполняется поле `offer_id`
 * у товара в магазине, и человек его **переписывает глазами**. Моноширинный
 * здесь не украшение — в пропорциональном шрифте единица и семёрка в номере
 * из пятнадцати цифр различаются хуже.
 *
 * Снятое с продажи приглушено целиком, а не помечено значком: видно,
 * но не спорит с действующим.
 */
.km-offer {
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-card);
  padding: 14px 18px;
  margin-bottom: 10px;
}

.km-offer--off {
  opacity: 0.72;
}

.km-offer__head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}

.km-offer__num {
  flex: none;
  font-family: var(--km-mono);
  font-size: 12px;
  color: var(--km-accent);
  background: var(--km-warm-bg);
  padding: 2px 7px;
  border-radius: 5px;
}

.km-offer--off .km-offer__num {
  color: var(--km-text-muted);
  background: var(--km-page);
}

/*
 * Название — кнопка: по нему открывается правка. Кнопкой, а не ссылкой,
 * потому что никуда не ведёт, и не всей карточкой, потому что внутри
 * карточки есть вторая кнопка — «Скопировать», — а кнопка в кнопке
 * разметкой не бывает.
 *
 * Одна строка с усечением: на боевом три предложения названы «Продвинутый
 * курс "Практикум по Местам Вознесения". Февраль 2026 · Новый поток»
 * и длиннее всей остальной строки. Полное показывается подсказкой.
 */
.km-offer__name {
  flex: 1;
  min-width: 200px;
  border: 0;
  background: none;
  padding: 0;
  text-align: left;
  cursor: pointer;
  /* И кнопкой, и ссылкой: на экране предложений название открывает панель
     правки на месте (никуда не ведёт — значит кнопка), а на карточке потока
     ведёт на соседний экран (значит ссылка). Подчёркивание и цвет ссылки
     снимаются здесь, чтобы обе выглядели одинаково: человек читает список
     предложений, а не два разных списка. */
  text-decoration: none;
  font-family: inherit;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.35;
  color: inherit;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.km-offer__name:hover {
  color: var(--km-accent);
}

.km-offer--off .km-offer__name {
  color: var(--km-text-secondary);
}

/*
 * `--link` СНЯТ 20 АВГУСТА 2026, И ЭТО НЕ ОТКАТ, А ЗАМЕНА.
 *
 * Он красил название в оранжевое там, где оно ведёт на другой экран, —
 * чтобы было видно, что по нему нажимают. Признак верный, но **второй**:
 * ту же работу делает явная кнопка «Править», заведённая на экране
 * предложений в тот день, когда человек написал «ничего не кликается».
 *
 * Двумя разными признаками одного и того же карточки одного семейства
 * стали выглядеть по-разному — а сводили их к одному стилю ровно затем,
 * чтобы человек не узнавал одну и ту же вещь заново на каждом экране.
 * Победил признак, который старше и уже принят.
 */

.km-offer__state {
  flex: none;
  font-size: 12px;
  color: var(--km-ok);
}

.km-offer--off .km-offer__state {
  color: var(--km-text-muted);
}

/*
 * Чья это карточка: программа предложения и программа потока.
 *
 * Стоит между шапкой и условиями и **приглушена сильнее условий**: это
 * не свойство предложения, а место, где оно живёт. Написана одним
 * правилом на оба экрана по той же причине, по какой у них общая карточка
 * `km-offer`, — второе такое же правило разъехалось бы на первой правке.
 *
 * `--off` не приглушает её отдельно: она и так самая тихая строка
 * карточки, и приглушать тише некуда.
 */
.km-offer__program {
  /*
   * Своих полей нет: в колонке промежуток даёт `gap` родителя, и поле
   * тега прибавлялось бы к нему. Это общая проверка стендов — она
   * и поймала здесь `12px` снизу, которые браузер даёт абзацу.
   */
  margin: 0;
  font-size: 12px;
  color: var(--km-text-muted);
  line-height: 1.4;
}

/*
 * А в карточке списка колонки нет: `.km-offer` — обычный блок, и строки
 * в нём разнесены полями, как `__terms` и `__facts` рядом.
 */
.km-offer .km-offer__program {
  margin-top: 6px;
}

.km-offer__terms {
  margin-top: 8px;
  font-size: 13px;
  color: var(--km-text-secondary);
  line-height: 1.6;
}

/*
 * Третья строка карточки: несколько коротких фактов через разделитель.
 *
 * У предложения это товар магазина и его номер, у потока — группа, куратор
 * и число предложений. Форма одна и та же, и написана она **одним правилом
 * на оба имени**: два одинаковых правила разъехались бы на первой правке,
 * а слом одного из них уцелел бы — второе делает то же самое.
 *
 * Имена при этом разные, потому что содержимое разное: `__shop` у потока
 * означал бы товар, которого у него нет.
 */
.km-offer__shop,
.km-offer__facts {
  margin-top: 8px;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.km-offer__shop-name,
.km-offer__fact {
  font-size: 12px;
  color: var(--km-text-secondary);
}

/*
 * Ненастроенное — приглушённым, но **написанным**: «группы нет» человек
 * прочтёт и поймёт, а пустое место читается как «экран недорисован».
 * Правило проекта про место, за которым нет данных: либо молчит, либо
 * названо словами.
 */
.km-offer__fact--none {
  color: var(--km-text-muted);
}

.km-offer__shop-id {
  font-size: 11px;
  font-family: var(--km-mono);
  color: var(--km-text-muted);
}

.km-offer__glyph {
  flex: none;
  width: 15px;
  height: 15px;
  color: var(--km-text-muted);
}

.km-copy {
  border: 1px solid var(--km-border);
  background: transparent;
  color: var(--km-text-secondary);
  font-family: inherit;
  font-size: 11px;
  padding: 3px 9px;
  border-radius: var(--km-radius-badge);
  cursor: pointer;
}

.km-copy:hover {
  background: var(--km-page);
}

/* Полоса выбора, липнущая к НИЗУ окна. Задача 1.18.0, редактор дерева.

   Наверху у редактора уже висит своя полоса с «Сохранить», и обе с `top: 0`
   легли бы одна на другую. Увидеть такое можно только на собранной странице:
   по отдельности обе правы.

   `top: auto` здесь обязателен, а не аккуратность: базовый класс задаёт
   `top: 0`, и без сброса браузер прилепит полосу к верху, а `bottom`
   проигнорирует. */
.km-sticky-bar--bottom {
  top: auto;
  bottom: 0;
  border-bottom: none;
  border-top: 1px solid var(--km-border);
  flex-wrap: wrap;
  row-gap: 10px;
}

/* Подпись и поле, стоящие В СТРОКУ, а не столбиком.

   `km-label` рассчитан на поле под собой, в колонке `km-field`; в полосе
   он оказывается рядом с полем, и вертикальные отступы колонки здесь лишние. */
.km-label--inline { flex: none; }
.km-select--inline { width: auto; min-width: 190px; }

/* Флажок выбора в строке дерева.

   Не даёт строке утащить себя перетаскиванием: у `km-tree--editable` вся
   строка `draggable`, и захват за флажок начинал бы перенос вместо отметки. */
.km-tree__pick {
  flex: none;
  display: flex;
  align-items: center;
  margin-right: 2px;
}

/* ── Карточка эфира ─────────────────────────────────────────────────────────

   Макет `design/live-page-v2.html`, решения человека 20 августа 2026.

   Три состояния, и различает их **вид, а не только текст**: у прошедшего
   рамка гаснет до обычной, у идущего кикер краснеет и получает точку.
   Признак существует ровно настолько, насколько отличается от соседнего
   случая, — поэтому у стенда мерки на отличие, а не на наличие класса. */
.km-live {
  background: var(--km-surface);
  border: 1px solid var(--km-warm-border);
  border-radius: var(--km-radius-card);
  padding: 20px 22px;
}

/* Прошедший эфир — приглушённая карточка: смотреть в ней больше нечего,
   и тёплая рамка обещала бы обратное. */
.km-live--past { border-color: var(--km-border); }

.km-live__kicker {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--km-text-muted);
}

.km-live__kicker--now { color: var(--km-live); font-weight: 700; }

/* Точка — своя, а не буква и не эмодзи: она обязана быть видна на любом
   шрифте и не читаться экранным диктором как слово. */
.km-live__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--km-live);
  flex: none;
}

/* ДАТА — ГЛАВНОЕ НА КАРТОЧКЕ. Решение человека: день недели, число, время,
   крупно. До эфира человеку нужна не кнопка, которой ещё нет, а когда. */
.km-live__when {
  margin-top: 10px;
  font-size: 22px;
  font-weight: 700;
  line-height: 1.25;
}

.km-live__when small {
  display: block;
  font-size: 14px;
  font-weight: 400;
  color: var(--km-text-secondary);
  margin-top: 4px;
}

.km-live__row { margin-top: 16px; display: flex; gap: 10px; flex-wrap: wrap; }

.km-live__cal {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--km-border);
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.km-live__cal-label { font-size: 13px; color: var(--km-text-secondary); }
.km-live__sep { color: var(--km-text-muted); font-size: 13px; }

.km-cal-link {
  font-size: 13px;
  color: var(--km-accent);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}

.km-cal-link:hover { border-bottom-color: var(--km-accent); }

.km-live__hint {
  margin-top: 12px;
  font-size: 13px;
  color: var(--km-text-muted);
  line-height: 1.5;
}

/* Значок площадки внутри кнопки трансляции. */
.km-btn__glyph { width: 17px; height: 17px; flex: none; }

/* ── Обсуждение: чат эфира и комментарии занятия ────────────────────────────

   Один вид на оба случая — меняется только заголовок и место на странице.
   Разный вид означал бы, что это две разные вещи, а это одна: комментарии
   к записи материала. */
/* Блок обсуждения — КАРТОЧКА, как в макете (`design/live-page-v2.html`),
   и с собственным отступом сверху.

   Оба правила поставлены после того, как экран посмотрели глазами
   на боевом, и оба про свою беду.

   **Карточка.** Первая редакция полагалась на `km-section`: он даёт воздух
   внутри и не даёт ни фона, ни рамки. Разговор оказывался на голом фоне
   страницы рядом с материалом, который стоит карточкой, — и читался как
   довесок, а не как часть занятия.

   **Отступ сверху свой, а не от соседства.** `.km-section + .km-section`
   даёт ритм соседям, а между кнопками и разговором стоит СПРЯТАННАЯ
   подсказка «отметьте, что прошли». `display: none` селектору соседства
   не виден, элемент в разметке есть — и правило молча не срабатывает.
   Ровно та беда, что уже ловилась на экране потоков; здесь она вылезла
   зазором в 16 пикселей вместо 28. */
/*
 * МЕСТО ДЛЯ ЧУЖОЙ РАЗМЕТКИ. Приёмка человека 21 августа 2026, обобщено
 * 7 сентября.
 *
 * Работа у класса ровно одна — вернуть чужой разметке ОБЫЧНЫЙ ПОТОК.
 * Колонка чтения занятия флексовая (`.km-content`), и чужой блок в ней
 * ведёт себя не так, как на любой обычной странице.
 *
 * ## Двое, и оба измерены
 *
 * **Разговор wpDiscuz.** Тема ставит своему `.comments-area` поля
 * `50px auto`: в потоке `auto` равны нулю и блок занимает всю ширину,
 * во флексе — съедают свободное место и сжимают блок по содержимому.
 * Замерено рядом с эталоном: запись блога — 410 при нулевых полях
 * по бокам, занятие без этого класса — 286 при полях 64.
 *
 * **Шаблон Elementor** внутри материала. Он приходит своим контейнером
 * `.elementor` и своим оформлением, а `wrapProse()` заворачивал его
 * в белую карточку с рамкой и скруглениями — поверх чужой плашки.
 * Измерено на боевом: девять мест с кнопками практик, на каждом ровно
 * один такой узел.
 *
 * ## Почему ОДИН класс, а не два
 *
 * Тело у них было бы побайтно одинаковым, а правило, написанное дважды,
 * прячет само себя: слом одного написания уцелеет на другом. Здесь
 * не «разговор» и не «Elementor» — здесь **чужая разметка в нашей
 * колонке**, и повод у обоих один.
 *
 * Прежнее имя `km-talk-host` называло одного из двух потребителей
 * и потому мешало увидеть второго.
 *
 * Своего воздуха здесь не заводится: сверху и снизу его даёт сама чужая
 * разметка. Класс, у которого одна строка, — это не мелочь, а место,
 * где записано, почему она нужна.
 */
.km-plain-host {
  display: block;
  min-width: 0;
}

.km-talk {
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-card);
  box-shadow: var(--km-shadow-card);
  padding: 20px 22px;
  gap: 14px;

  /* Воздух с ОБЕИХ сторон, а не только сверху.

     Блок стоит то над кнопками, то под ними — решает состояние эфира, —
     и отступ, поставленный с одной стороны, работает ровно в половине
     случаев. Найдено стендом: на боевом эфир прошёл, разговор стоит внизу,
     и упирающийся в кнопки «Чат эфира» там не увидеть никак. */
  margin: 28px 0;
}

.km-talk__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.km-talk__item {
  border-top: 1px solid var(--km-border);
  padding-top: 14px;
}

.km-talk__item:first-child { border-top: none; padding-top: 0; }

/* Ветка ответов. Раздел 17.8: перенос из LearnDash везёт `comment_parent`,
   и показ обязан его показывать — иначе ответ встанет самостоятельной
   репликой, потеряв, кому отвечал.

   Отступ слева и линия делают вложенность видимой БЕЗ подписи «в ответ
   такому-то»: признак существует не тогда, когда поставлен, а тогда,
   когда отличается от соседнего случая. Верхнее сообщение линии не имеет,
   ответ имеет — этим они и различаются.

   Глубина любая: правило работает на каждом следующем уровне само,
   потому что задано вложенностью, а не номером уровня. */
.km-talk__list--replies {
  margin-top: 14px;
  padding-left: 16px;
  border-left: 2px solid var(--km-border);
  gap: 12px;
}

.km-talk__list--replies .km-talk__item {
  border-top: none;
  padding-top: 0;
}

.km-talk__head {
  margin: 0 0 4px;
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}

.km-talk__author { font-size: 14px; font-weight: 600; }
.km-talk__when { font-size: 12px; color: var(--km-text-muted); }

.km-talk__body { font-size: 14px; line-height: 1.6; color: var(--km-text-secondary); }
.km-talk__body p { margin: 0 0 8px; }
.km-talk__body p:last-child { margin-bottom: 0; }

.km-talk__form { margin-top: 16px; }

/* ── Шапка и фильтры административного экрана ────────────────────────────────

   Два яруса вместо четырёх. Решение человека 21 августа 2026 по экрану
   зачислений: поиск, сегменты, программы, статус с источником и «Ещё фильтры»
   занимали экран целиком, и до первой строки данных надо было прокрутить.

   Классы общие, а не «для зачислений»: то же устройство — заголовок, поиск,
   действия, под ними ряд условий — просится на любой список в админке,
   и второй такой набор через экран пришлось бы держать в согласии с этим. */

.km-toolbar {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;

  /* Воздух между ярусами задаётся здесь, а не соседством `.km-section`.

     Ярусы вышли из секций ради сжатия шапки — и вместе с секциями ушёл
     ритм: ряд условий встал вплотную к ряду полей, а ряд сегментов
     к нему. Ни одна общая мерка этого не поймала: «секции разнесены
     по вертикали» спрашивает про `.km-section`, а ярусов среди них
     больше нет. Найдено глазами на боевом, 21 августа 2026. */
  margin-bottom: 16px;
}

/* Заголовок в строке с полем — меньше обычного H1.

   36 пикселей рядом с полем поиска высотой 46 читаются не как заголовок
   экрана, а как помеха: строка распадается на «большое слово» и «всё
   остальное». Правится здесь, а не по месту: правило 13. */
.km-toolbar .km-h1 { font-size: 24px; line-height: 1.2; }

/* Поиск тянется, кнопки — нет: растягивать надо то, куда вводят текст. */
.km-toolbar__search {
  flex: 1 1 240px;
  min-width: 200px;
  max-width: 380px;
}

.km-filters {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}

/* «Ещё фильтры» стоит последним в том же ярусе и раскрывается на всю его
   ширину. Три поля рядом с четырьмя списками не поместились бы ни на одном
   экране, а свой ярус ради свёрнутой строки — ровно то, что задача велит
   убрать.

   Разворот делается сменой `flex-basis` у самого `details`: когда оно
   открыто, элемент занимает строку целиком и поля встают под списками. */
.km-filters__more { flex: none; }
.km-filters__more[open] { flex: 1 0 100%; }

.km-filters__more-head {
  cursor: pointer;
  list-style: none;
  font-size: 13px;
  font-weight: 600;
  color: var(--km-text-secondary);
  padding: 8px 4px;
  white-space: nowrap;
}

.km-filters__more-head::-webkit-details-marker { display: none; }
.km-filters__more-head::after { content: ' ▾'; }
.km-filters__more[open] .km-filters__more-head::after { content: ' ▴'; }
.km-filters__more-head:hover { color: var(--km-accent); }

.km-filters__more-body { padding-top: 12px; }

/* ПЛОТНОСТЬ ШАПКИ — ПО МАКЕТУ, И ЭТО ЕЁ СМЫСЛ.

   Общие `.km-input` и `.km-select` заведены под **формы**: поле, в которое
   вводят и подолгу смотрят, обязано быть крупным. Шапка списка — не форма,
   а строка условий: её читают краем глаза и по ней не печатают.

   Разница вышла в четверть экрана. Померено рядом с макетом, 1180:
   поиск 49 против 37, список 49 против 35, кнопка 41 против 35, вся шапка
   151 против 126. Именно она и читается как «ненаглядность»: до первой
   строки данных остаётся ровно столько же прокрутки, сколько было
   до сжатия ярусов.

   Правится **в шапке**, а не в самих `.km-input` и `.km-select`: те же
   классы носят формы редактора узла, потока, предложения — там крупный
   размер верен. На узком возвращается обратно: 35 пикселей — это меньше
   пальца, и список условий там открывают именно пальцем. */
.km-toolbar .km-input,
/* Ряд чипов внутри ряда фильтров обязан переноситься сам.

   Флексовый элемент по умолчанию не сжимается уже своего содержимого
   (`min-width: auto`), и вложенный `.km-chips` вытягивался в одну строку
   в 941 пиксель при экране в 375: переносить внутри себя ему было
   нечего — места ему обещали сколько угодно.

   Ловится это только измерением на узком: на широком экране разметка
   ведёт себя правильно, и оба вида выглядят верными. Поймала общая мерка
   «ничего не вылезает за ширину экрана» 23 августа 2026. */
.km-filters .km-chips {
  flex: 1 1 auto;
  min-width: 0;
}

/* Число в панели — своей шириной, а не на всё свободное место.

   Поле «Дней» у «Продлить» в карточке зачисления (1 октября 2026: окно
   `prompt` заменено полем) общее правило панели растягивало до 300 px —
   три цифры в поле шириной с поиск. Селектор сильнее общего (0,3,0 против
   0,2,0): исход держится силой, а не порядком правил. */
.km-toolbar .km-input.km-input--number {
  flex: none;
  width: 96px;
}

/* Подпись и поле в строку — подпись по середине поля.

   Панель карточки выравнивает по верху (`flex-start`: слева двухстрочное
   имя), и голая подпись «Дней» в 17 px вставала выше середины поля
   в 48 px. Своя пара с центровкой не зависит от того, как выравнивает
   ряд, в котором стоит. */
.km-inline-field {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: none;
}

.km-filters .km-select {
  font-size: 14px;
  padding: 8px 12px;
}

/* Список не растягивается под длинное название.

   `.km-select--inline` шириной `auto` берёт ширину самого длинного пункта,
   а название программы на боевом — «Практикум по Местам Вознесения 2026 ·
   263». Четыре таких списка не поместятся в строку ни на одном экране,
   и ярус, ради которого всё и сжималось, развалится на два. */
.km-filters .km-select { max-width: 260px; }

.km-toolbar__search .km-input { padding-left: 36px; }
.km-toolbar__search .km-input-group__icon { left: 12px; }

.km-toolbar .km-btn { padding: 9px 15px; }

/* Сегменты: подпись и чипы одной строкой.

   Подпись стоит снаружи контейнера чипов — скрипт перерисовывает его
   на каждый ответ и начинает с очистки. */
/* Сегменты: подпись и чипы **одной строкой**, с переносом.

   Подпись стоит снаружи контейнера чипов — скрипт перерисовывает его
   на каждый ответ и начинает с очистки. Но выглядеть это обязано одной
   строкой, а не подписью над рядом кнопок: отдельная строка — это ярус,
   а ярусы здесь и сжимали.

   Поэтому контейнер чипов объявлен `display: contents`: его дети встают
   в этот же ряд, и подпись оказывается перед первым чипом. Роль ему
   при этом нужна — без неё элемент с `display: contents` вместе
   со своим `aria-label` уходит из дерева доступности. */
.km-segments {
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}

.km-segments .km-chips { display: contents; }

.km-segments__label {
  font-size: 12px;
  color: var(--km-text-muted);
  flex: none;
  margin-right: 3px;
}

/* Чип сегмента — обычными буквами и мельче фильтров.

   Общий `.km-chip` набран капсом с разрядкой: он заведён под навигацию,
   где чипов три-четыре и они главные на экране. Сегментов шесть, они
   стоят под рядом фильтров и обязаны читаться тише его, а не громче.
   Правится модификатором, а не самим `.km-chip`: тот же класс носят
   чипы на шести других экранах.

   Отступы у выбранного те же, что у невыбранного: общий `.km-chip`
   прибавляет пиксель на каждую сторону, и ряд из шести чипов дёргался
   при каждом нажатии. */
.km-chip--segment {
  font-size: 12px;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  padding: 5px 11px;
  border-radius: 20px;
}

.km-chip--segment.is-active { padding: 5px 11px; }

/* Число — главное на чипе, и потому темнее и плотнее названия.

   Общий `.km-chip__count` приглушён до шести десятых: в навигации число
   справочное. Здесь наоборот — ради него чип и читают: «нажимаешь,
   чтобы выяснить, что сегмент пуст» и было тем, что правится. */
.km-chip--segment .km-chip__count {
  opacity: 1;
  font-weight: 600;
  color: var(--km-text);
  margin-left: 6px;
}

@media (max-width: 640px) {
  /* На узком заголовок занимает строку целиком, поиск — следующую:
     иначе поле сжимается до пары букв и в него не видно, что набрано. */
  .km-toolbar .km-h1 { flex: 1 0 100%; font-size: 22px; }
  .km-toolbar__search { flex: 1 0 100%; max-width: none; }

  /* Два действия делят строку пополам, а не встают лесенкой каждое своей
     ширины: на 375 «Зачислить вручную» и «Выгрузить CSV» занимали две
     строки разной длины, и шапка читалась как обрывок списка. */
  .km-toolbar .km-btn { flex: 1 1 0; }

  /* Списки условий встают друг под друга во всю ширину. Прокрутка, как
     у чипов, здесь не годится: уехавший список человек не откроет,
     а чип он хотя бы дотянет пальцем. */
  /* Столбиком — и **без переноса**.

     Перенос у колонки складывает элементы в несколько колонок, а ширину
     строки задаёт самый широкий из них: ряд чипов с прокруткой хочет
     тысячу с лишним пикселей и растягивал под себя весь экран. Колонка
     без переноса даёт каждому элементу ровно ширину контейнера, и полоса
     чипов уезжает прокруткой внутри себя, как и задумано.

     Найдено измерением на 375 у журнала действий 23 августа 2026:
     на широком экране обе редакции выглядят одинаково верными. */
  .km-filters { flex-direction: column; align-items: stretch; flex-wrap: nowrap; }
  .km-filters .km-select { width: 100%; }
  .km-filters__more-head { padding-left: 0; }

  /* Плотность шапки возвращается к обычной: 35 пикселей меньше пальца,
     а список условий на телефоне открывают именно им. Сжатие было
     про экономию высоты на широком, где всё в одну строку. */
  .km-toolbar .km-input,
  .km-filters .km-select {
    font-size: 15px;
    padding: 12px 14px;
  }

  /* Место под иконку возвращается отдельно.

     Сокращённая запись `padding` выше стирает и левое поле, а оно тут
     не косметика: иконка поиска лежит поверх, и без места буква «И»
     оказывается прямо под лупой. Найдено глазами на 375 — ни одна мерка
     наложения текста на иконку не спрашивает. */
  .km-toolbar__search .km-input { padding-left: 40px; }
  .km-toolbar__search .km-input-group__icon { left: 14px; }

  /* Потолок ширины снимается: на узком список занимает строку целиком,
     а 260 пикселей оставляли справа пустое место шире пальца. */
  .km-filters .km-select { max-width: none; }

  .km-toolbar .km-btn { padding: 12px 18px; }
}

/* Несколько строк в одной ячейке — столбцом.

   На узком экране ячейка становится строкой карточки (`display: flex`,
   подпись слева, значение справа), и положенные в неё блоки подряд
   становятся флексовыми элементами: «49 000 ₽» и «Рассрочка: 3 из 3»
   вставали рядом и читались одной фразой. Проверка на текст этого
   не видит — в `textContent` переноса нет ни при каком оформлении.
   Найдено измерением на стенде зачислений, 375, 21 августа 2026.

   Столбец, а не `display: block`: у блока нет промежутка между строками,
   а сжимать его до нуля здесь нечем — строки разной высоты. */
.km-lines {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

/* Обрезается каждая строка по отдельности, а не столбец целиком:
   правило `.km-table td > div` теперь попадает на обёртку, и без этого
   многоточие ставилось бы вместо всех строк разом.

   СУЖЕНО ДО ТАБЛИЦЫ, и это не осторожность. Без `.km-table` впереди
   правило доставало до карточки зачисления, где тем же `.km-lines`
   собраны списки работ, правил и истории: неразрывными становились
   целые фразы, и карточка вылезала за край экрана на 375 почти
   на сотню пикселей. Один класс успел завести два смысла — в ячейке
   таблицы строки короткие и обрезаются, в карточке они переносятся. */
.km-table .km-lines > * {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}

/* Строка ячейки, которую обрезать нельзя: фраза с датами. Пометка неоплаты
   рассрочки (7.14, 17 сентября 2026) — «Этап 2: платёж ждали 1 авг, не пришёл…»;
   многоточие съело бы ровно то, ради чего она заведена, — день и срок.

   Переносится внутри ячейки, а не раздвигает столбец: без предела ширины
   фраза в одну строку растянула «Оплату» до 641 px, и таблица вылезла
   за экран на 1280 (замер на стенде). */
.km-table .km-lines > .km-lines__long {
  overflow: visible;
  text-overflow: clip;
  white-space: normal;
  max-width: min(280px, 100%);
  line-height: 1.4;
}

/* ── Карточка зачисления ────────────────────────────────────────────────────

   Всё об одном человеке на одном экране. Решение человека 22 августа 2026.
   Разметка и порядок блоков — по `design/enrollment-card-v1.html`. */

.km-toolbar--card { align-items: flex-start; }

.km-toolbar__who { flex: 1 1 240px; min-width: 240px; }

.km-back {
  font-size: 13px;
  color: var(--km-text-secondary);
  text-decoration: none;
  display: inline-block;
  margin-bottom: 4px;
}

.km-back:hover { color: var(--km-accent); }

.km-toolbar--card .km-h1 { margin-bottom: 3px; }

/* Карточка с полями. `.km-card` в системе есть, но она под обложки курсов
   и потому без внутреннего отступа: у неё содержимое — картинка во всю
   ширину. Здесь отступ нужен, и он модификатором, а не правкой базы. */
.km-card--pad { padding: 16px 18px; margin-bottom: 12px; }

/* Часть карточки под чертой: действие, которое относится к блоку выше.
   Первая такая — «Засчитать этап» в блоке доступа карточки зачисления
   (7.14): форма читается вместе со строкой «Рассрочка» и потому стоит
   в той же карточке, а не отдельной. */
.km-card__part {
  margin: 16px 0 0;
  padding-top: 14px;
  border-top: 1px solid var(--km-border-soft);
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* Промежутки внутри части держит `gap`; свой отступ у заголовка
   сложился бы с ним. */
.km-card__part > .km-card__t { margin: 0; }

.km-card__t {
  font-size: 11px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--km-text-muted);
  font-weight: 600;
  margin: 0 0 12px;
}

/* Пары «подпись — значение» сеткой, а не таблицей: подписи разной длины,
   и колонка под самую длинную оставила бы половину карточки пустой. */
.km-facts {
  display: grid;
  grid-template-columns: repeat( auto-fit, minmax( 200px, 1fr ) );
  gap: 12px 22px;
}

/* Пара целиком: она ячейка сетки, и своего оформления ей не нужно —
   но имя у неё быть обязано. Класс, поставленный в разметке и не заведённый
   в системе, не сверяется ни с чем, и первый же опечатанный уехал бы
   на экран незамеченным. */
.km-fact { min-width: 0; }

.km-fact__k { font-size: 12px; color: var(--km-text-muted); }
.km-fact__v { margin-top: 2px; line-height: 1.4; font-size: 14px; }

/* Две колонки для прогресса и работ: их читают вместе, отвечая на вопрос
   «идёт ли человек». На узком встают друг под друга — рядом им нужно
   по трети экрана, а его нет. */
.km-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

/* Колонке разрешено сжиматься.

   У элемента сетки минимальная ширина по умолчанию `auto`, то есть
   по содержимому: одна неразрывная строка внутри — и колонка перестаёт
   помещаться в свою дорожку, а страница уезжает за край экрана. Внутри
   всё и так умеет обрезаться, мешало только это. */
.km-cols > * { min-width: 0; }

/* Строка ленты: название тянется, метка и дата не жмутся. */
.km-line {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 0;
  border-bottom: 1px solid var(--km-border-soft);
}

.km-line:last-child { border-bottom: none; }

.km-line__n {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 14px;
}

.km-line__d { font-size: 12px; color: var(--km-text-muted); white-space: nowrap; }

/* Строка-фраза: переносится, а не обрезается. Запись журнала действий —
   законченное предложение, и многоточие на его середине отнимает смысл.
   Кто и когда — рядом на широком, под фразой на узком. */
.km-line--long { flex-wrap: wrap; align-items: baseline; }
.km-line--long .km-line__n { white-space: normal; flex: 1 1 260px; line-height: 1.45; }

/* Метка вида: мельче чипа и не нажимается — она подпись, а не кнопка. */
.km-tag-sm {
  font-size: 10px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--km-text-secondary);
  background: var(--km-bg);
  border: 1px solid var(--km-border);
  padding: 2px 7px;
  border-radius: 5px;
  white-space: nowrap;
}

/* ПУСТО — ЭТО ОТВЕТ, А НЕ ПРОПУСК.

   Пустой блок человек читает как поломку: он не отличит «работ нет»
   от «работы не загрузились». Поэтому у каждого списка карточки есть
   слова на случай, когда в нём ничего, и выглядят они как текст,
   а не как строка данных. */
.km-empty-line {
  font-size: 13px;
  line-height: 1.5;
  color: var(--km-text-muted);
  /* Отступ полем, а не отступом: внутри колонки расстояния задаёт `gap`,
     и своё поле у ребёнка спорит с ним. Общая мерка стенда это ловит. */
  margin: 0;
  /* Отступ с обеих сторон, как у строки ленты (`.km-line`, 9px). Был только
     сверху, и на пустой карточке плашка под списком прилипала к «Ничего
     не пройдено.» — увидено Аленой 17 сентября 2026. Строки ленты давали
     зазор своим отступом, и на заполненной карточке этого не было видно. */
  padding: 8px 0;
}

/* Ссылка на чужую установку. Подчёркнута намеренно: она уводит с сайта,
   и выглядеть как обычное значение поля ей нельзя. */
.km-link-out { color: var(--km-accent-dark, #C85A28); text-decoration: underline; }
.km-link-out:hover { color: var(--km-accent); }

/* Восемьдесят девять тегов сеткой — это стена, и открывается она
   по требованию. Свёрнутое `details` отдаёт полные размеры невидимого,
   и стенд обязан открывать его перед измерением (5.5). */
.km-tags { grid-column: 1 / -1; margin-top: 4px; }

.km-tags__head {
  cursor: pointer;
  list-style: none;
  font-size: 12px;
  font-weight: 600;
  color: var(--km-text-secondary);
}

.km-tags__head::-webkit-details-marker { display: none; }
.km-tags__head::after { content: ' ▾'; }
.km-tags[open] .km-tags__head::after { content: ' ▴'; }
.km-tags__head:hover { color: var(--km-accent); }

.km-tags__cloud { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }

/* ── Примечания магазина на карточке зачисления ──────────────────────────────

   Решение Алены 21 сентября 2026, спецификация 12.3. Запись — свободный
   текст в несколько строк с подписью: когда, кто, к какому заказу.

   Свой компонент, а не модификатор ленты: `.km-line` — строка в одну
   строчку с обрезкой, а запись обрезать нельзя, в ней весь смысл («заказы
   на 3100 и 6200 отдельно»). Один класс с двумя правилами переноса — ровно
   та беда, что уже была с `.km-lines` в ячейке и в карточке. */
.km-shopnotes { display: flex; flex-direction: column; min-width: 0; }

.km-shopnote {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 10px 0;
  border-bottom: 1px solid var(--km-border-soft);
  min-width: 0;
}

.km-shopnote:last-child { border-bottom: none; }

/* Когда, кто, какой заказ — мелко и в строку; на узком переносится. */
.km-shopnote__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 10px;
  font-size: 12px;
  color: var(--km-text-muted);
}

/* Текст как написан: переводы строк — свои у человека. Неразрывное слово
   (адрес платежа ЮKassa, почта) переносится где угодно: иначе оно задаёт
   ширину карточке, и страница уезжает за край на 375 — так уже было
   со строкой правила 22 августа 2026. */
.km-shopnote__text {
  margin: 0;
  font-size: 14px;
  line-height: 1.5;
  color: var(--km-text);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* След действия («Статус заказа изменён массовой правкой») — приглушённо,
   но на месте: отличает его только текст, разборщик ошибается, а
   спрятанная ручная запись — ошибка, которую не увидит никто. */
.km-shopnote--trace .km-shopnote__text { font-size: 13px; color: var(--km-text-muted); }

/* Служебные — свёрнуты строкой с числом. */
.km-shopnotes__more { margin-top: 6px; }

.km-shopnotes__head {
  cursor: pointer;
  list-style: none;
  padding: 6px 0;
  font-size: 12px;
  font-weight: 600;
  color: var(--km-text-secondary);
}

.km-shopnotes__head::-webkit-details-marker { display: none; }
.km-shopnotes__head::after { content: ' ▾'; }
.km-shopnotes__more[open] .km-shopnotes__head::after { content: ' ▴'; }
.km-shopnotes__head:hover { color: var(--km-accent); }

/* Кнопка формы — по своей ширине: часть карточки стоит столбцом
   и растянула бы её во всю строку. */
.km-shopnotes__send { align-self: flex-start; }

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

@media (max-width: 640px) {
  /* Действия карточки делят строку: их три, и лесенкой они занимают
     треть экрана ни за чем. */
  .km-toolbar--card .km-btn { flex: 1 1 0; }
  .km-toolbar__who { flex: 1 0 100%; }

  /* Поля в один столбец: две колонки по 160 пикселей режут значения
     вроде «26 фев 2026 — 26 фев 2027» пополам. */
  .km-facts { grid-template-columns: 1fr; }
}

/* Подпись только для тех, кто читает не глазами.

   `display: none` для этого не годится — оно прячет и от экранного диктора,
   то есть ровно от тех, ради кого подпись и написана. */
.km-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect( 0 0 0 0 );
  white-space: nowrap;
  border: 0;
}

/* Столбец действий у строки списка: узкий, прижат вправо. */
.km-cell-act { width: 44px; text-align: right; }

/* ДЕЙСТВИЕ ПОЯВЛЯЕТСЯ ПО НАВЕДЕНИЮ.

   Висящее у каждой из двадцати пяти строк, оно зашумляет экран сильнее,
   чем помогает: открывают карточку одного человека из списка, а видят
   значок у всех. Тот же довод, что у ручки перетаскивания в дереве.

   При этом оно **остаётся видимым для клавиатуры**: спрятанное до наведения
   и не показанное при фокусе, оно недостижимо для того, кто ведёт не мышью. */
.km-act,
.km-act:focus {
  display: inline-flex;
  opacity: 0;
  color: var(--km-text-muted);
  padding: 4px;
  border-radius: 6px;
}

tbody tr:hover .km-act,
.km-act:focus-visible { opacity: 1; }

/* Очертание дописано сюда же, а не отдельным правилом: у `.km-act` признак
   фокуса уже был (проявление), и второе определение того же селектора
   развело бы один признак по двум местам. Задача 9.27. */
.km-act:focus-visible { outline: 2px solid var(--km-accent); outline-offset: 2px; }

.km-act:hover { background: var(--km-border-soft); color: var(--km-text); }
.km-act svg { width: 18px; height: 18px; display: block; }

@media (max-width: 640px) {
  /* На узком наведения нет вовсе, и прятать нечего: карточка становится
     недостижимой. Значок стоит рядом с флажком, в правом верхнем углу. */
  .km-act { opacity: 1; }
  .km-table td.km-cell-act { justify-content: flex-end; }
  .km-table td.km-cell-act::before { content: none; }
}

/* ─── Карточка доставки ─────────────────────────────────────────────────────
 *
 * Макет `design/webhooks-v1.html`, принят 22 августа 2026. Заменила строку
 * таблицы на экране журнала вебхуков.
 *
 * Причина растягивала строку на треть страницы и сталкивала подписи
 * столбцов — а причина здесь главное: с ней в журнал и приходят. В карточке
 * она стоит своим блоком, и рядом с ней стоит действие, а не в другом
 * конце экрана.
 *
 * Выполненное приглушено целиком — тем же приёмом и по тому же доводу,
 * что снятое с продажи предложение: видно, но не спорит с тем, что просит
 * внимания.
 *
 * Состояние берёт ОБЩИЙ `.km-state` с точкой, а не заводит свой: точка
 * и четыре её цвета — это про любое состояние на любом экране, и второй
 * набор разошёлся бы с первым на первой же правке палитры.
 */
.km-hook {
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-card);
  padding: 14px 18px;
  margin-bottom: 10px;
}

.km-hook--done {
  opacity: 0.75;
}

.km-hook__head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}

/* Имя события — моноширинным и первым: по нему отличают оплату от возврата
   с одного взгляда, и оно приходит из чужой системы дословно. */
.km-hook__event {
  flex: none;
  font-family: var(--km-mono);
  font-size: 12px;
  color: var(--km-text);
  background: var(--km-page);
  border: 1px solid var(--km-border);
  padding: 2px 8px;
  border-radius: 5px;
}

.km-hook__who {
  flex: 1;
  min-width: 180px;
  font-size: 14px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.km-hook__meta {
  margin-top: 7px;
  font-size: 13px;
  color: var(--km-text-secondary);
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
}

/* Номер заказа — моноширинным по тому же доводу, что номер предложения:
   его переписывают глазами, и в пропорциональном шрифте единица и семёрка
   в номере из пятнадцати цифр различаются хуже. */
.km-hook__id {
  font-family: var(--km-mono);
  font-size: 12px;
  color: var(--km-text-muted);
}

.km-hook__sep { color: var(--km-text-muted); }

.km-hook__why {
  margin-top: 11px;
  background: var(--km-page);
  border-radius: 10px;
  padding: 11px 14px;
  font-size: 13px;
  color: var(--km-text);
  line-height: 1.55;
}

.km-hook__why b { font-weight: 600; }

/* Кто и когда разобрал — под причиной, тише неё: причина — про систему,
   эта строка — про человека (10.1, правка 22 сентября 2026). Заметки несут
   номера заказов одним словом — переносятся где угодно. */
.km-hook__settled {
  margin: 8px 0 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--km-text-secondary);
  overflow-wrap: anywhere;
}

.km-hook__act {
  margin-top: 10px;
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
}

/* Тело доставки внутри карточки: показывается по требованию, здесь же,
   а не в панели внизу экрана. Моноширинным — это JSON. */
.km-hook__payload {
  margin-top: 10px;
  font-family: var(--km-mono);
  font-size: 12px;
  line-height: 1.5;
  background: var(--km-page);
  border: 1px solid var(--km-border);
  border-radius: 10px;
  padding: 11px 14px;
  max-height: 320px;
  overflow: auto;
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--km-text);
}

/* Поле «что решили» — внутри карточки и только когда его открыли: на каждой
   карточке подряд оно спрашивало бы то, чего у человека ещё нет. */
.km-hook__note {
  margin-top: 10px;
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
}

.km-hook__note .km-input { flex: 1; min-width: 220px; }

@media (max-width: 640px) {
  /* На узком строки карточки встают друг под друга: почта длинная,
     и рядом с именем события ей места нет. */
  .km-hook__who { min-width: 100%; white-space: normal; }
  .km-hook__act > .km-btn { flex: 1; }
}

/* ─── Экран правил ──────────────────────────────────────────────────────────
 *
 * Макет `design/rules-v1.html`, принят 22 августа 2026. Решение человека
 * про прежний экран: «бесполезный и страшный».
 *
 * Бесполезный — потому что у правила было видно одно название: ни включено
 * ли, ни когда срабатывает, ни писало ли хоть раз. Страшный — потому что
 * два выключателя стояли одинаково, а делают разное.
 */

/* Два выключателя, и вид у них разный.
 *
 * Отключённый — тёплой карточкой, работающий — обычной. Одинаковые, они
 * читаются как один выключатель, который однажды нажмут не тот; а разница
 * между «остановить правила» и «закрыть отправку» — это разница между
 * «система молчит» и «система считает, но молчит наружу». */
.km-switches {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

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

.km-sw {
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: 14px;
  padding: 14px 16px;
}

.km-sw--off {
  background: var(--km-warm-bg);
  border-color: var(--km-warm-border);
}

.km-sw__top {
  display: flex;
  align-items: center;
  gap: 9px;
}

.km-sw__name { flex: 1; font-weight: 600; }

.km-sw__why {
  margin-top: 7px;
  font-size: 13px;
  color: var(--km-text-secondary);
  line-height: 1.5;
}

.km-sw__act { margin-top: 11px; }

/* Правило строкой в общей карточке.
 *
 * Строки лежат внутри одной рамки, а не карточками поодиночке: сценариев
 * четырнадцать, и четырнадцать карточек подряд читаются как четырнадцать
 * разных вещей. Здесь же одна вещь — список. */
.km-rules {
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-card);
  overflow: hidden;
}

.km-rule {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--km-border-soft);
}

.km-rule:last-child { border-bottom: none; }
.km-rule:hover { background: var(--km-page); }

/* Выключенное приглушено целиком — тем же приёмом, что снятое с продажи
   предложение и выполненная доставка: видно, но не спорит с действующим. */
.km-rule--off { opacity: 0.6; }

.km-rule__body { flex: 1; min-width: 0; }
.km-rule__name { font-weight: 600; line-height: 1.3; }

.km-rule__when {
  font-size: 12px;
  color: var(--km-text-muted);
  margin-top: 3px;
}

.km-rule__num {
  flex: none;
  text-align: right;
  font-size: 13px;
  color: var(--km-text-secondary);
  min-width: 190px;
}

/* Главное число экрана: уходило ли что-нибудь людям.
   Зелёным — только когда уходило: на боевом это одно правило
   из четырнадцати, и отличаться оно должно с одного взгляда. */
.km-rule__sent { color: var(--km-ok); font-weight: 600; }
.km-rule__sent--none { color: var(--km-text-muted); font-weight: 400; }

.km-rule__small {
  display: block;
  font-size: 12px;
  color: var(--km-text-muted);
  margin-top: 2px;
  /* ДЛИННОЕ СЛОВО ЛОМАЕТСЯ. Найдено глазами на боевых данных, 375.
   *
   * В строке особого случая стоит текст отказа движка, а в нём — имя тега
   * CRM: `program:mesta-voznesenija:completed`, тридцать пять знаков без
   * единого пробела. Неразрывное слово задаёт минимальную ширину флексовой
   * ячейке, ячейка — строке, строка — странице: на 375 браузер отъезжал
   * до 510 и показывал экран уменьшенным.
   *
   * На фикстуре этого не видно: длинные имена тегов бывают только
   * у настоящих отказов. Ровно то, о чём правило «фикстуры стенда несут
   * самое длинное из правдоподобного». */
  overflow-wrap: anywhere;
}

/* Кнопки по наведению и справа.
 *
 * Стояли сразу за названием и плясали по горизонтали: названия у правил
 * разной длины, и глазу не за что зацепиться. Место в строке они занимают
 * всегда — иначе строка дёргалась бы под курсором. */
.km-rule__acts {
  flex: none;
  display: flex;
  gap: 6px;
  opacity: 0;
}

.km-rule:hover .km-rule__acts,
.km-rule:focus-within .km-rule__acts { opacity: 1; }

@media (max-width: 760px) {
  /* На узком наведения нет вовсе, и прятать нечего: кнопки становятся
     недостижимыми. Строка при этом встаёт столбиком. */
  .km-rule { flex-wrap: wrap; }
  .km-rule__acts { opacity: 1; }
  /* Ячейка чисел занимает строку целиком И УМЕЕТ СЖИМАТЬСЯ.
   *
   * `flex: none` на широком верен — колонка не должна плясать от длины
   * названия, — а на узком он же не давал ей стать уже своего содержимого:
   * `flex-basis: auto` плюс `flex-shrink: 0` дают ширину по самому длинному
   * слову, и `overflow-wrap` внутри тут бессилен. Имя тега CRM из текста
   * отказа растягивало строку до 488 px при экране в 375, и браузер
   * показывал страницу уменьшенной. */
  .km-rule__num { flex: 1 1 100%; min-width: 0; text-align: left; }
}

/* «Показать ещё» вместо номеров страниц: 463 кнопки — не навигация. */
.km-more { margin-top: 12px; text-align: center; }

/* ── Отчёты: три числа, обрывы, свёрнутая воронка ─────────────────────────
 *
 * Вид по макету `design/reports-v1.html`, решение человека 22 августа 2026:
 * прежний экран был «самой бестолковой страницей» — сто двадцать строк
 * одинакового веса. Здесь вес разный: крупное число ответа, крупное число
 * потери, а полная воронка убрана под раскрытие.
 */

.km-nums { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; }
.km-num {
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-card);
  padding: 16px 18px;
}
.km-num__value { font-size: 28px; font-weight: 700; line-height: 1.1; }
.km-num__key { font-size: 13px; color: var(--km-text-secondary); margin-top: 5px; line-height: 1.4; }
.km-num__sub { font-size: 12px; color: var(--km-text-muted); margin-top: 6px; }

/* Карточка без своих отступов: строки сами держат поля. */
.km-card--flush { overflow: hidden; }

.km-loss { display: flex; align-items: center; gap: 14px; padding: 13px 18px; border-bottom: 1px solid var(--km-border-soft); }
.km-loss:last-child { border-bottom: none; }
.km-loss__count {
  flex: none;
  width: 54px;
  text-align: right;
  font-size: 20px;
  font-weight: 700;
  color: var(--km-danger);
  font-variant-numeric: tabular-nums;
}
.km-loss__body { flex: 1; min-width: 0; }
.km-loss__title { font-weight: 600; line-height: 1.35; overflow-wrap: anywhere; }
.km-loss__where { font-size: 12px; color: var(--km-text-muted); margin-top: 3px; overflow-wrap: anywhere; }

/* «Показать людей» — по наведению, как кнопки правила: пять кнопок,
   висящих постоянно, спорят по весу с числом потери. */
.km-loss__act { flex: none; opacity: 0; transition: opacity .12s ease; }
.km-loss:hover .km-loss__act,
.km-loss:focus-within .km-loss__act { opacity: 1; }

.km-folds { display: flex; flex-direction: column; gap: 10px; }
.km-fold {
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-card);
  overflow: hidden;
}
.km-fold > summary {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 13px 18px;
  cursor: pointer;
  font-weight: 600;
  list-style: none;
}
.km-fold > summary::-webkit-details-marker { display: none; }
.km-fold > summary::before {
  content: '';
  flex: none;
  width: 7px;
  height: 7px;
  border-right: 1.5px solid var(--km-text-muted);
  border-bottom: 1.5px solid var(--km-text-muted);
  transform: rotate(-45deg);
  transition: transform .15s ease;
}
.km-fold[open] > summary::before { transform: rotate(45deg); }
.km-fold__meta { font-size: 13px; color: var(--km-text-muted); font-weight: 400; margin-left: auto; }

.km-node-row { display: flex; align-items: center; gap: 12px; padding: 9px 18px; border-top: 1px solid var(--km-border-soft); }
.km-node-row__title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.km-node-row__bar { flex: none; width: 120px; }
.km-node-row__value {
  flex: none;
  /* «171 из 263 · 65%» — знаменатель у каждой строки свой, и в двух
     строках он читается хуже, чем в одной. */
  width: 148px;
  text-align: right;
  font-size: 13px;
  color: var(--km-text-secondary);
  font-variant-numeric: tabular-nums;
}
/* Число потери — узкой колонкой; «не с чем сравнить» у первого в цепочке
   не переносится по слогам, а занимает столько, сколько нужно. */
.km-node-row__drop {
  flex: none;
  min-width: 52px;
  text-align: right;
  white-space: nowrap;
  font-size: 13px;
  color: var(--km-text-muted);
  font-variant-numeric: tabular-nums;
}
.km-node-row__drop--bad { color: var(--km-danger); font-weight: 600; }

/* На узком полоса и колонки уезжают: остаются название и числа строкой. */
@media (max-width: 767px) {
  .km-loss { gap: 10px; padding: 12px 14px; flex-wrap: wrap; }
  .km-loss__count { width: 44px; font-size: 18px; }
  /* На узком наведения нет: спрятанная кнопка была бы недостижимой. */
  .km-loss__act { opacity: 1; flex: 1 1 100%; margin-left: 54px; }

  .km-node-row { flex-wrap: wrap; gap: 4px 10px; padding: 10px 14px; }
  .km-node-row__title { flex: 1 1 100%; white-space: normal; overflow: visible; text-overflow: clip; }
  .km-node-row__bar { display: none; }
  .km-node-row__value { width: auto; text-align: left; }
  .km-node-row__drop { width: auto; margin-left: auto; }
}

/* ── Состав бонусов ──────────────────────────────────────────────
 *
 * Задача 9.25. Взято из макета `design/bonuses-v1.html` без правок:
 * он написан классами `km-`, и переписывать их по месту значило бы
 * заводить второе оформление того же.
 *
 * `km-picks` — список программ с галками, `km-pick--on` поднимается
 * наверх, `km-pick--locked` показывает курсовые бонусы у предложения:
 * их отсюда не меняют.
 */
.km-box {
	background:var(--km-surface);
	border:1px solid var(--km-border);
	border-radius:var(--km-radius-card);
	overflow:hidden;
}

.km-box__head {
	padding:13px 18px;
	border-bottom:1px solid var(--km-border);
	font-size:14px;
	font-weight:600;
}

.km-box__body {
	padding:16px 18px 18px;
}

.km-picks {
	border:1px solid var(--km-border);
	border-radius:10px;
	overflow:hidden;
}

.km-picks__scroll {
	max-height:296px;
	overflow-y:auto;
}

.km-pick {
	display:flex;
	align-items:flex-start;
	gap:11px;
	padding:9px 13px;
	border-bottom:1px solid var(--km-border);
	cursor:pointer;
	background:var(--km-surface);
}

.km-pick:last-child {
	border-bottom:none;
}

.km-pick:hover {
	background:var(--km-bg);
}

.km-pick input {
	margin:2px 0 0;
	width:15px;
	height:15px;
	flex:none;
	accent-color:var(--km-accent);
}

.km-pick input:focus-visible {
	outline:2px solid var(--km-accent);
	outline-offset:2px;
}

.km-pick__main {
	flex:1;
	min-width:0;
}

.km-pick__name {
	font-size:13.5px;
	line-height:1.4;
}

.km-pick__meta {
	font-size:11.5px;
	color:var(--km-text-muted);
	margin-top:2px;
}

.km-pick__side {
	flex:none;
	font-size:11.5px;
	color:var(--km-text-muted);
	padding-top:1px;
	text-align:right;
	max-width:170px;
}

.km-pick--on {
	background:var(--km-warm-bg);
}

.km-pick--on:hover {
	background:#FBE9DD;
}

.km-pick--on .km-pick__name {
	font-weight:600;
}

.km-pick--locked {
	cursor:default;
	background:var(--km-bg);
}

.km-pick--locked:hover {
	background:var(--km-bg);
}

.km-pick--locked .km-pick__name {
	color:var(--km-text-secondary);
}

.km-pick--locked input {
	accent-color:var(--km-text-muted);
}

.km-picks__split {
	padding:6px 13px;
	background:var(--km-bg);
	font-size:11px;
	letter-spacing:.04em;
	text-transform:uppercase;
	color:var(--km-text-muted);
	border-bottom:1px solid var(--km-border);
}

.km-tag--from-course {
	background:var(--km-warm-bg);
	color:var(--km-warm-text);
}

.km-offer__bonus {
	margin-top:9px;
	padding-top:9px;
	border-top:1px solid var(--km-border);
	font-size:13px;
	line-height:1.6;
	display:flex;
	gap:10px;
	align-items:baseline;
	flex-wrap:wrap;
}

.km-offer__bonus-label {
	color:var(--km-text-secondary);
	flex:none;
}

.km-offer__bonus-list {
	flex:1;
	min-width:180px;
}

.km-offer__bonus-list--empty {
	color:var(--km-text-muted);
}.km-link,
.km-link:focus{
	border:0;
	background:none;
	padding:0;
	font:inherit;
	font-size:12.5px;
	color:var(--km-accent);
	cursor:pointer;
	text-decoration:underline;
	text-underline-offset:2px;
	flex:none;
}

.km-link:focus-visible {
	outline:2px solid var(--km-accent);
	outline-offset:2px;
	border-radius:3px;
}

.km-open {
	margin-top:12px;
	padding-top:14px;
	border-top:1px dashed var(--km-border);
}

/*
 * Блок «Что показывать на странице курса». Задача 9.26,
 * макет `design/course-settings-v1.html`.
 *
 * Строка настройки — это название, объяснение и то, чем настройку задают:
 * галка, поле с эхом или строка состояния у того, чем человек не управляет.
 *
 * Из макета вычтено то, что дизайн-система уже рисует: подписи идут
 * `km-hint`, галка — `km-check` с `km-check__box`, коробка — `km-box`.
 * Своё у макета осталось только то, чего в системе не было: сама строка,
 * эхо и строка состояния.
 *
 * **`km-set__row`, а не `km-field`**, и это не придирка к имени: `km-field`
 * в системе — колонка (`flex-direction: column`), а здесь нужна строка.
 * Взятое по созвучию, оно поставило бы эхо под поле на всех экранах, где
 * его потом употребят, — и каждый из них выглядел бы правильным по
 * отдельности.
 */
.km-set {
	padding:15px 18px;
	border-bottom:1px solid var(--km-border);
}

.km-set:last-child {
	border-bottom:none;
}

.km-set__top {
	display:flex;
	align-items:baseline;
	gap:10px;
}

.km-set__name {
	flex:1;
	font-size:13.5px;
	font-weight:600;
}

.km-set__row {
	margin-top:9px;
	display:flex;
	align-items:center;
	gap:10px;
	flex-wrap:wrap;
}

/*
 * `width:auto` обязателен: у `.km-input` в системе стоит `width:100%`,
 * и без снятия поле занимает строку целиком, а эхо уезжает под него.
 * На узком это правильно и делается переносом (`flex-wrap`), на широком —
 * нет: эхо для того и рядом, чтобы читаться вместе с тем, что набрано.
 */
.km-set__row .km-input {
	width:auto;
	min-width:210px;
	flex:1;
	font-size:13px;
	padding:6px 10px;
}

.km-set__row--num .km-input {
	width:auto;
	min-width:150px;
	max-width:220px;
	flex:none;
	font-family:var(--km-mono);
}

/*
 * Эхо. `flex:none` намеренно: оно съезжает на свою строку целиком, а не
 * рвётся посередине — в нём бывают названия форм без пробелов.
 */
.km-echo {
	font-size:12px;
	line-height:1.5;
	flex:none;
}

.km-echo--ok {
	color:var(--km-ok);
}

.km-echo--warn {
	color:var(--km-warn);
}

.km-echo--muted {
	color:var(--km-text-muted);
}

.km-found {
	margin-top:8px;
	font-size:12px;
	color:var(--km-text-secondary);
	line-height:1.7;
}

.km-found__list {
	margin:3px 0 0;
	padding:0;
	list-style:none;
}

/*
 * Названия форм приходят машинными: слаги, скобки, номера. Длинное слово
 * без пробелов задаёт минимальную ширину строке, строка — блоку, блок —
 * экрану; на 375 это уводит страницу за край целиком. Ломаем по буквам.
 */
.km-found__list li {
	color:var(--km-text-muted);
	overflow-wrap:anywhere;
}

.km-found__more {
	color:var(--km-text-muted);
}

/*
 * Строка состояния — там, где решает не человек. Показывает и что решено,
 * и почему: выключенное без причины читается как поломка ровно так же,
 * как пустота.
 */
.km-auto {
	font-size:12px;
	color:var(--km-text-muted);
	background:var(--km-page);
	border-radius:7px;
	padding:7px 11px;
	margin-top:8px;
	line-height:1.55;
}

.km-auto b {
	color:var(--km-text-secondary);
	font-weight:600;
}

.km-auto--on b {
	color:var(--km-ok);
}

/*
 * Кусок машинного текста внутри строки: образец названия формы, ключ, слаг.
 *
 * Заведён в 9.26 — до него моноширинный шрифт ставился шестью частными
 * классами (`km-hook__id`, `km-placeholder` и другими), и общего не было
 * ни одного. Ставится на `<code>`, у которого браузер и так меняет шрифт:
 * класс задаёт кегль и цвет, чтобы образец не выпирал из подписи.
 */
.km-mono {
	font-family:var(--km-mono);
	font-size:.92em;
	color:var(--km-text-secondary);
}

/*
 * Обёртка чужой разметки отзывов. Задача 9.28.
 *
 * Оформления здесь нет ни строчки и быть не должно: внутри — вывод
 * представления GravityView, его вид задаёт человек в чужом экране,
 * и красить его отсюда значило бы завести второе место, где живёт
 * этот вид.
 *
 * Своя у обёртки одна работа — НЕ ДАТЬ ЧУЖОМУ УТАЩИТЬ СТРАНИЦУ ВБОК.
 * Представление рисует список с таблицами и длинными ссылками, ширину
 * которых мы не выбираем; без своей прокрутки первая же широкая строка
 * тянет за собой всю страницу. Этот дефект в проекте уже был дважды —
 * у административных таблиц и у карточки воронки, — и оба раза его
 * находил не тест, а глаз на узком экране.
 */
.km-reviews {
	overflow-x: auto;
	max-width: 100%;
}

/* ─────────────────────────────────────────────────────────────────────────
   ФАЙЛЫ КУРСА. Задача 10.1, макет `design/course-files-concept-v1.html`.

   ИМЯ У СТРОКИ СВОЁ, И ЭТО НЕ ПРИДИРКА. Макет называл строку файла
   `km-row`, а `.km-row` в этой таблице определён ДВАЖДЫ и в двух разных
   смыслах: строка дерева (`padding`, `border-bottom`, `align-items:center`)
   и строка контролов шапки (`flex-wrap`, `align-items:flex-end`). Они
   не спорят, а СКЛАДЫВАЮТСЯ — третий смысл сделал бы помесь ещё гуще.

   `.km-file` тоже занят: это строка файла в блоке вложения на странице
   занятия, со своим `__glyph`/`__body`/`__action`. Переименовывается
   меньшинство, а у нового имени употреблений ноль — поэтому своё имя
   берёт новый, а не старый.
   ───────────────────────────────────────────────────────────────────── */

:root {
	/* Цвет значка по виду файла. Три — те, что на боевом: 279 pdf, 177 mp3,
	   28 jpg плюс 11 png. Остальным общий серый: выдумывать цвет виду,
	   которого почти нет, — значит заводить словарь, за которым не следят. */
	--km-kind-doc: #C0392B;
	--km-kind-audio: #6B4FA8;
	--km-kind-image: #2E7D5B;
	--km-kind-other: #7C8A9B;
}

.km-lib__head {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 12px;
	margin-bottom: 14px;
}

.km-lib__search { flex: 1 1 220px; }

/* Сводка прижимается вправо, к кнопке: она справка, а не заголовок. */
.km-lib__head > .km-meta { margin-left: auto; }

.km-lib__form { padding: 16px 18px; margin-bottom: 14px; }

.km-lib { padding: 4px 18px; }

.km-lib__row {
	display: flex;
	align-items: center;
	gap: 12px;
	padding: 11px 0;
	border-bottom: 1px solid var(--km-border);
}

.km-lib__row:last-child { border-bottom: none; }

.km-lib__kind {
	flex: none;
	width: 34px;
	height: 34px;
	border-radius: 9px;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 9.5px;
	font-weight: 700;
	color: #FFFFFF;
	background: var(--km-kind-other);
}

.km-lib__kind--doc { background: var(--km-kind-doc); }
.km-lib__kind--audio { background: var(--km-kind-audio); }
.km-lib__kind--image { background: var(--km-kind-image); }

.km-lib__main { flex: 1; min-width: 0; }

.km-lib__name {
	display: block;
	font-size: 14px;
	line-height: 1.4;
	color: var(--km-text);
}

.km-lib__meta {
	display: block;
	font-size: 11.5px;
	color: var(--km-text-muted);
	margin-top: 2px;
}

/*
 * «ГДЕ СТОИТ» — СПРАВА И СЛОВАМИ.
 *
 * Ширина ограничена, чтобы длинная фраза не отжимала название: строк сотня,
 * и глаз идёт по левому краю.
 */
.km-lib__where {
	flex: none;
	max-width: 230px;
	text-align: right;
	font-size: 12px;
	color: var(--km-text-secondary);
}

/*
 * «Нигде не стоит» — тёплым, а не серым: это состояние, на которое смотрят,
 * а не подпись, которую пропускают. Приглушённое, оно потерялось бы ровно
 * там, где заведено, — в списке из сотни строк.
 */
.km-lib__where--none { color: var(--km-warm-text-strong); }

.km-lib__act {
	flex: none;
	display: flex;
	gap: 10px;
}

/*
 * Адрес — моноширинным. Ссылка на Диск это набор знаков без слов, и в ней
 * ищут глазами опечатку: пропорциональный шрифт склеивает `l`, `1` и `I`.
 */
.km-input--mono {
	font-family: var(--km-mono);
	font-size: 12.5px;
}

/*
 * НА УЗКОМ «ГДЕ СТОИТ» УХОДИТ ПОД НАЗВАНИЕ ОТДЕЛЬНОЙ СТРОКОЙ.
 *
 * `flex-basis: 100%` здесь и есть перенос: без него `flex-wrap` у строки
 * укладывает колонку рядом с именем, и обещание «уходит под название»
 * остаётся написанным в комментарии и невыполненным. Найдено глазами
 * на 375: правило применялось целиком — `text-align` и отступ стояли, —
 * а колонка была справа. Мерка при этом молчала: за экран ничего
 * не вылезало, и вылезать было нечему.
 *
 * Отступ 46px равен значку плюс промежуток: строка выравнивается по имени,
 * а не по левому краю карточки.
 */
@media (max-width: 560px) {
	.km-lib__row { flex-wrap: wrap; row-gap: 6px; }

	.km-lib__where {
		flex-basis: 100%;
		max-width: none;
		text-align: left;
		margin-left: 46px;
	}
}

/* ---------------------------------------------------------------------------
 * Сценарии. Спецификация 9.11, макет `design/scenarios-prototype.html`.
 * ------------------------------------------------------------------------- */

/*
 * Шапка экрана: заголовок слева, действия справа.
 *
 * Заведена своим именем, а не собрана из `km-row`: у того ДВА определения
 * в этом же файле — списковая строка с рамкой и подложкой при наведении
 * и строка полей формы, — и они складываются, а не спорят. Довешивать
 * к ним третий смысл значило бы делать хуже то, что уже надо чинить.
 */
.km-head {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	justify-content: space-between;
	gap: 12px;
	margin-bottom: 12px;
}

.km-head__acts {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
}

/* Раздел редактора: «Когда срабатывает», «Кому», «Что делаем».
   Кружок с номером отсюда убран 7 сентября 2026: порядок читается
   сверху вниз и без него, а заголовки разделов стали надзаголовками
   (`.km-section-title`) — на странице один H1, как в макете. */
.km-block {
	background: var(--km-surface);
	border: 1px solid var(--km-border);
	border-radius: 14px;
	padding: 16px 18px;
	margin-bottom: 12px;
}


/*
 * Предпросмотр письма: показывает то, что увидит человек.
 *
 * `pre-wrap` — потому что письмо набирают переносами строк, а уходит
 * оно абзацами (`Letter::markup()`). Без него предпросмотр слепляет
 * письмо в один поток и врёт про вид ровно там, где его и смотрят.
 *
 * `anywhere` — потому что в письме бывает адрес курса, а он едет одним
 * словом без пробелов. Неразрывное слово задаёт минимальную ширину
 * блоку, блок — странице: на 375 экран уезжал за край. Найдено глазами
 * на стенде 7 сентября 2026, фикстурой с настоящим адресом.
 */
/* ПИСЬМО В ПРЕДПРОСМОТРЕ — таким, каким его увидят в почте.
 * Правка Алены 14 сентября 2026.
 *
 * До неё письмо лежало в `.km-note`, а это **флексовая плашка**: первый
 * её ребёнок становится узкой левой ячейкой. Тема оказывалась серой
 * колонкой в верхнем регистре, тело текло справа — на письмо это
 * не походило ничем, хотя разметка была верной.
 *
 * Колонка чтения ограничена намеренно: в почте письмо никогда не шире
 * своего окна, и строка в сто двадцать знаков читается иначе, чем та,
 * что человек получит. Мерять его надо в той ширине, в какой оно придёт.
 */
.km-letter {
	max-width: 680px;
	background: var(--km-surface);
	border: 1px solid var(--km-border);
	border-radius: var(--km-radius-card);
	box-shadow: var(--km-shadow-card);
	padding: 26px 30px 30px;
}

.km-letter + .km-letter { margin-top: 16px; }

/*
 * Шапка письма — строка над темой: что придёт на зелёной полосе шаблона
 * (курс, у письма без курса — эфир). Решение Алены 12 октября 2026.
 */
.km-letter__header {
	margin: 0 0 8px;
	font-size: 13px;
	line-height: 1.5;
	color: var(--km-text-secondary);
}

.km-letter__header b { color: var(--km-text); }

/* Тема — обычным заголовком письма, а не подписью столбца. */
.km-letter__subject {
	font-family: var(--km-font-display);
	font-size: 21px;
	font-weight: 700;
	line-height: 1.3;
	margin: 0;
	color: var(--km-text);
}

/* Черта под темой — та же граница, что у шапки письма в почте. */
.km-letter__body {
	margin-top: 16px;
	padding-top: 18px;
	border-top: 1px solid var(--km-border);
}

.km-letter-preview {
	/*
	 * `normal`, а не `pre-wrap`. С 8 сентября 2026 предпросмотр приходит
	 * РАЗМЕТКОЙ — той же, что уедет в письмо, — и переносы в ней ставит
	 * `wpautop` для читаемости исходника, а не для показа. При `pre-wrap`
	 * каждый такой перенос стал бы пустой строкой на экране, и письмо
	 * выглядело бы разреженным вдвое против настоящего.
	 */
	white-space: normal;
	overflow-wrap: anywhere;
}

/*
 * ПРЕДУПРЕЖДЕНИЯ ПОД ПИСЬМОМ ОТБИТЫ ОТ НЕГО И ДРУГ ОТ ДРУГА.
 *
 * У `.km-caution` своих полей нет намеренно: отступ задаёт место, где она
 * стоит. Здесь мест два — «подставить нечем» и счёт пустых у эфиров, —
 * и без отбивки первая строка касалась последнего абзаца письма ровно
 * в ноль пикселей. Слипшиеся строки не видит ни одна проверка на текст:
 * обе фразы на месте, обе верны.
 */
.km-letter > .km-caution { margin-top: 12px; }

.km-letter > .km-caution + .km-caution { margin-top: 6px; }

/* Цепочка шагов: карточки друг под другом. */
/* ---------------------------------------------------------------------------
   Редактор сценария (9.11). Макет `design/scenario-editor-v1.html`
   ---------------------------------------------------------------------------
   Правка 8 сентября 2026 по замечаниям человека к первой сборке экрана.
   Три вещи, которые здесь выражены, — не украшение:

   - три раздела это ОДИН документ, а не три экрана: одна карточка
     с разделительными линиями, читается сверху вниз;
   - подстановки стоят СПРАВА ОТ ПОЛЯ и с примером значения. Без примера
     видно имя поля и не видно, что подставится, — а «половина пользы»
     это и есть та половина;
   - у шага есть шапка: вид, тема строкой и ручка. Голые поля не говорят,
     что это письмо и какое из двух.

   Свёртка шагов отложена (решение человека): `.km-step` всегда раскрыт.
   Метка, рейка и ручка от свёртки не зависят и сделаны сейчас.
   --------------------------------------------------------------------------- */

/* Две колонки: редактор и подстановки. Правая липнет к верху окна,
   чтобы стоять рядом с тем, что печатают. */
.km-scn {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 300px;
	gap: 20px;
	align-items: start;
}

.km-scn-side {
	position: sticky;
	/* Под липкой обвязкой темы: сколько её сверху, замеряет `chrome.js`. */
	top: calc( var(--km-chrome-top, 0px) + 20px );
	/*
	 * СВОЯ ПРОКРУТКА, КОГДА КОЛОНКА ВЫШЕ ОКНА.
	 *
	 * 14 сентября 2026 подстановок стало восемнадцать вместо двенадцати,
	 * и панель выросла с 736 до 910px при окне 768.
	 *
	 * Первое объяснение было неверным, и оно записано, чтобы его не искали
	 * заново: «низ уходит за край навсегда» — неправда. Липкость кончается
	 * вместе с контейнером: доскроллив до конца, колонку видно целиком.
	 * Замерено на стенде — последняя подстановка доезжает при прокрутке 750.
	 *
	 * Беда в другом, и она тоже замерена. Подстановка вставляется **в поле
	 * письма, туда, где курсор**, — значит поле должно быть на экране вместе
	 * с ней. На коротком сценарии так и есть. На длинном (левая колонка
	 * +2500px) `{pay_by}` доезжает только к прокрутке 3250, и поля письма
	 * на экране уже нет: вставлять некуда.
	 *
	 * Отсюда своя прокрутка: панель остаётся у поля при любой длине сценария.
	 * Число не пишется — слагаемых у верха три, и меряет их `chrome.js`.
	 */
	max-height: calc( 100vh - var(--km-chrome-top, 0px) - 40px );
	overflow-y: auto;
}

/* Шапка: крошки, «назад», заголовок, состояние и действия. */
.km-scn-head { margin: 12px 0 22px; }

.km-scn-head__row {
	display: flex;
	align-items: center;
	gap: 14px;
	flex-wrap: wrap;
	margin-top: 6px;
}

.km-scn-head__row .km-h1 { margin-right: auto; }

/* Плашка состояния: слово рядом с переключателем. Переключатель говорит,
   что СДЕЛАТЬ, плашка — что ЕСТЬ, и читать их надо вместе. */
.km-scn-state {
	font-size: 12.5px;
	font-weight: 700;
	padding: 5px 11px;
	border-radius: var(--km-radius-badge);
	background: var(--km-warm-bg);
	color: var(--km-warm-text-strong);
	border: 1px solid var(--km-warm-border);
}

.km-scn-state--on {
	background: #E9F4F2;
	color: #2E7D5B;
	border-color: #CBE5DE;
}

/* Раздел внутри общей карточки. Линия сверху — только у не первого. */
.km-scn-block { padding: 22px 24px 24px; }
.km-scn-block + .km-scn-block { border-top: 1px solid var(--km-border-soft); }

.km-scn-block__t {
	display: flex;
	align-items: baseline;
	gap: 12px;
	margin-bottom: 14px;
}

.km-scn-block__d {
	font-size: 13px;
	color: var(--km-text-secondary);
	margin-left: auto;
}

/* Цепочка: рейка слева с линией, шаги справа. */
.km-chain {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: 0;
}

.km-chain::before {
	content: "";
	position: absolute;
	left: 17px;
	top: 18px;
	bottom: 18px;
	width: 2px;
	background: var(--km-border);
}

.km-chain > * {
	position: relative;
	display: grid;
	grid-template-columns: 36px minmax(0, 1fr);
	gap: 14px;
	align-items: start;
}

.km-chain__glyph {
	width: 36px;
	height: 36px;
	border-radius: 10px;
	background: var(--km-warm-bg);
	color: var(--km-accent);
	display: flex;
	align-items: center;
	justify-content: center;
	position: relative;
	z-index: 1;
}

.km-chain__glyph--wait {
	width: 24px;
	height: 24px;
	border-radius: 50%;
	margin: 6px;
	background: var(--km-surface);
	color: var(--km-text-muted);
	border: 1.5px solid var(--km-border);
}

/* Шаг: карточка внутри карточки, на полтона темнее. */
.km-step {
	background: var(--km-surface-alt);
	border: 1px solid var(--km-border);
	border-radius: var(--km-radius-card);
}

.km-step__head {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 12px 14px 12px 16px;
	min-height: 50px;
	border-bottom: 1px solid var(--km-border-soft);
	margin-bottom: 12px;
}

/* Сжимается и переносится по словам: «Окно на платформе» втрое длиннее
   «Письма», и на 375 несжимаемая подпись выталкивала стрелки и корзину
   за край карточки (стенд формы окна, 22 сентября 2026). */
.km-step__kind {
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--km-text-muted);
	flex: 0 1 auto;
	min-width: 0;
}

/* Тема строкой: она и есть имя письма, и по ней их различают. */
.km-step__title {
	font-weight: 600;
	flex: 1;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.km-step__title--empty {
	color: var(--km-text-muted);
	font-weight: 400;
}

.km-step__acts {
	display: flex;
	gap: 4px;
	flex: none;
	margin-left: 6px;
}

.km-step__body {
	display: flex;
	flex-direction: column;
	gap: 14px;
	padding: 2px 16px 16px;
}

.km-step .km-textarea,
.km-step textarea.km-input {
	min-height: 260px;
	font-size: 14.5px;
	line-height: 1.6;
}

/* Своих полей нет: расстояние задаёт колонка, в которой стоит абзац.
   Так требует общая мерка стендов, и она права — два источника отступа
   однажды сложатся, и никто не поймёт, какой из них править. */
.km-step__foot {
	font-size: 12.5px;
	color: var(--km-text-muted);
	line-height: 1.5;
	margin: 0;
}

/* ── Шаг «Окно на платформе» в редакторе сценария ────────────────────────────

   Спецификация 12.7, «Редактор шага» (22 сентября 2026). Карточка — та же
   `km-step`, что у письма; внутри поля окна столбцом, как поля письма. */
.km-scn-popform { display: flex; flex-direction: column; gap: 14px; }

/* Текст окна — до тысячи знаков, а не письмо: поле письма (260px) было бы
   втрое выше того, что в нём поместится. Вес (0,3,0) — чтобы не спорить
   с `.km-step .km-textarea` порядком строк. */
.km-step .km-textarea.km-scn-poptext { min-height: 110px; }

/* Своя картинка: превью той ширины, в которой её узнают, и действия рядом;
   на узком действия уходят под превью. */
.km-scn-popimg { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }

.km-scn-popimg__thumb {
  display: block;
  width: 160px;
  max-width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-control);
  background: var(--km-surface);
}

.km-scn-popimg__acts { display: flex; flex-wrap: wrap; gap: 8px; }

/* Пустое поле картинки и выключенная медиатека говорят словами; отступ
   задаёт строка, в которой они стоят. */
.km-scn-popimg .km-hint { margin: 0; flex: 1 1 200px; }

/* Выбор режима и его значение — в строку; на узком друг под другом.
   `min-width: 0` обязателен: у `select` во флексе нижний предел ширины —
   самый длинный вариант («За столько-то часов до начала»), и на 375 он
   распирал страницу до 413 px (стенд формы окна, 22 сентября 2026). */
.km-scn-popwhen { display: flex; flex-wrap: wrap; gap: 10px; }

.km-scn-popwhen > .km-input { flex: 1 1 220px; width: auto; min-width: 0; }

.km-scn-popwhen > .km-input.km-scn-popwhen__value { flex: 0 1 140px; }

/* «Предпросмотр на сайте» и строка о том, что откроется: в ряд, на узком
   строка уходит под кнопку. Своих полей у строки нет — отступ задаёт ряд. */
.km-scn-popsite { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }

.km-scn-popsite > .km-hint,
.km-scn-popsite > .km-caution { margin: 0; flex: 1 1 220px; }

/* ── Окно в предпросмотре: так его увидит участник ──────────────────────────

   Карточка — общая разметка окна (`templates/parts/popup-card.php`),
   на той же подложке, что на странице, но не поверх экрана: `km-modal`
   держит окно `fixed`, а здесь оно стоит в колонке. */
.km-scn-popview { max-width: 680px; display: flex; flex-direction: column; gap: 10px; }

.km-letter + .km-scn-popview,
.km-scn-popview + .km-scn-popview { margin-top: 20px; }

.km-scn-popview__head {
  margin: 0;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--km-text-muted);
}

/* Адрес кнопки — неразрывное слово: переносится где угодно, иначе задал бы
   ширину колонке и увёл её за край на 375. */
.km-scn-popview__line { margin: 0; font-size: 13px; line-height: 1.5; color: var(--km-text-secondary); overflow-wrap: anywhere; }

.km-scn-popview__line a { color: var(--km-accent); }

.km-scn-popview > .km-hint,
.km-scn-popview > .km-caution { margin: 0; }

.km-popup-sample {
  display: flex;
  justify-content: center;
  padding: 24px 16px;
  background: rgba(63, 76, 92, 0.45);
  border-radius: var(--km-radius-card);
}

/* Кнопка-значок: убрать шаг. Своё имя, а не `.km-btn`: у той заливка,
   отступы и кегль текста, а здесь квадрат под значок. */
.km-ico {
	width: 30px;
	height: 30px;
	border-radius: 8px;
	border: 1px solid transparent;
	background: transparent;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	color: var(--km-text-muted);
	cursor: pointer;
}

.km-ico:hover:not(:disabled) {
	color: var(--km-accent);
	border-color: var(--km-warm-border);
	background: var(--km-surface);
}

/* Выключенный значок не притворяется живым: стрелка «выше» у первого шага
   и «ниже» у последнего вести никуда не могут. Вид взят у стрелки календаря
   (`.km-month__nav:disabled`) — третьего вида выключенного заводить незачем.
   Причина названа подсказкой на самой кнопке: выключенное без причины
   читается как поломка ровно так же, как пустота. */
.km-ico:disabled {
	color: var(--km-border);
	cursor: default;
}

.km-ico--danger:hover {
	color: var(--km-danger);
	border-color: #F0BDB0;
}

/* Ожидание — строка на рейке, а не карточка: оно между письмами,
   а не рядом с ними. Это про данные: шаг ожидания ничего не делает,
   он задаёт срок до следующего. */
.km-wait { padding: 8px 0; }

.km-wait__body {
	display: flex;
	align-items: center;
	gap: 8px;
	flex-wrap: wrap;
	min-height: 36px;
	font-size: 14.5px;
	color: var(--km-text-secondary);
}

.km-wait .km-input {
	width: 66px;
	text-align: center;
	padding: 7px 8px;
	font-weight: 600;
	font-variant-numeric: tabular-nums;
}

/* Число и единица набраны ОДИНАКОВО, и вес написан у обоих явно.

   Унаследованный вес разъезжается: у поля он свой, у списка — тот,
   что достался от родителя или от чужой таблицы, и на экране «3»
   и «дней» оказываются набраны по-разному. Написанный у обоих,
   он не зависит ни от того, ни от другого. */
.km-wait .km-select {
	width: auto;
	padding: 7px 34px 7px 12px;
	background-position: right 11px center;
	font-size: 14px;
	font-weight: 600;
}

.km-wait__acts {
	margin-left: auto;
	display: flex;
	gap: 4px;
}

/* Метка в CRM — строка на рейке, как ожидание: писем в ней нет.
   Свои классы, а не `km-wait`: одно имя на два смысла однажды смешалось бы
   каскадом. Поле имени растёт, подсказка переносится на свою строку. */
.km-scn-tagstep { padding: 8px 0; }

.km-scn-tagstep__body {
	display: flex;
	align-items: center;
	gap: 8px;
	flex-wrap: wrap;
	min-height: 36px;
	font-size: 14.5px;
	color: var(--km-text-secondary);
}

.km-scn-tagstep__body .km-input {
	flex: 1 1 260px;
	min-width: 0;
	padding: 7px 10px;
}

.km-scn-tagstep__acts {
	margin-left: auto;
	display: flex;
	gap: 4px;
}

.km-scn-tagstep__hint {
	flex-basis: 100%;
	margin: 0;
	font-size: 12.5px;
	line-height: 1.45;
	color: var(--km-text-muted);
}

/* Строка про метку под предпросмотром — отбита от письма над ней.
   Цвета здесь нет намеренно: строка «метки нет» носит ещё и `km-caution`,
   а это правило стоит ниже него и перебило бы ему цвет — предупреждение
   выходило серым. Серая — только «заранее не проверить», модификатором. */
.km-scn-tagnote { margin: 12px 0 0; }

.km-scn-tagnote--unchecked {
	font-size: 13px;
	color: var(--km-text-muted);
}

/* Добавить шаг — последняя позиция на рейке. */
.km-chain__add { padding-top: 10px; }

.km-chain__add .km-chain__glyph {
	background: transparent;
	color: var(--km-text-muted);
	border: 1.5px dashed var(--km-border);
}

.km-chain__add-body {
	display: flex;
	gap: 8px;
	flex-wrap: wrap;
	align-items: center;
	min-height: 36px;
}

.km-chain__add-note {
	font-size: 12.5px;
	color: var(--km-text-muted);
	margin-top: 12px;
	padding-left: 50px;
	line-height: 1.5;
}

/* Подстановки: слева поле, которое вставляется кликом, справа пример
   на живом человеке. Пример — половина пользы: без него видно имя поля
   и не видно, что подставится. */
.km-vars { padding: 18px 18px 16px; }

.km-vars__hint {
	font-size: 12.5px;
	color: var(--km-text-muted);
	line-height: 1.5;
	margin: 4px 0 12px;
}

.km-var {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	gap: 10px;
	align-items: center;
	padding: 7px 0;
	border-top: 1px solid var(--km-border-soft);
}

.km-var:first-of-type { border-top: 0; }

.km-var__key {
	font-family: var(--km-mono);
	font-size: 12px;
	color: var(--km-warm-text-strong);
	background: var(--km-warm-bg);
	border: 1px solid var(--km-warm-border);
	border-radius: 6px;
	padding: 3px 7px;
	cursor: pointer;
	white-space: nowrap;
}

.km-var__key:hover { background: var(--km-peach); }

.km-var__ex {
	font-size: 13px;
	color: var(--km-text-secondary);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	text-align: right;
}

.km-var__ex--none { color: var(--km-text-muted); }

.km-vars__foot {
	font-size: 12px;
	color: var(--km-text-muted);
	line-height: 1.5;
	margin-top: 12px;
	padding-top: 12px;
	border-top: 1px solid var(--km-border-soft);
}

/* ---------------------------------------------------------------------------
   Поле письма с панелью. Задача от 8 сентября 2026
   ---------------------------------------------------------------------------
   Имя своё, `km-write`: `km-toolbar` в системе уже есть и означает шапку
   административного экрана — шесть определений и четыре экрана. Второе имя
   на тот же класс дало бы помесь, которой никто не задумывал; случай
   с `.km-hint` в проекте уже был и прожил девять экранов.

   Поле рисуется тем же, чем `.km-textarea`: подложка, рамка, скругление,
   кегль. Одно и то же значение в двух местах разошлось бы на первой правке,
   поэтому оба стоят в одном правиле выше, а здесь только то, чего
   у многострочного поля нет. */
.km-write { display: flex; flex-direction: column; }
/* Поле с панелью в холсте редактора («Подзаголовок» ресурса, «Ресурсы» 1.4): общих `[hidden]` и `* { box-sizing }`
   в холст не доезжает — обрезка таблицы для редактора их снимает (`Support\DesignSystem::trimmed_for_editor()`).
   Без своих правил `.km-write__link { display: flex }` перебивал правило браузера для `[hidden]` — строка адреса
   ссылки стояла всегда, — а поле с `content-box` вылезало за раздел. На страницах писем и сообщества ничего не
   меняется: там те же общие правила уже есть. */
.km-write [hidden] { display: none !important; }
.km-write,
.km-write *,
.km-write *::before,
.km-write *::after { box-sizing: border-box; }

/* Панель прижата к полю: между ними ни пикселя, скругление одно на два
   блока — панель и поле читаются как один предмет, а не как кнопки
   над чем-то посторонним. */
.km-write__bar {
	display: flex;
	align-items: center;
	gap: 4px;
	flex-wrap: wrap;
	padding: 6px 8px;
	background: var(--km-bg);
	border: 1px solid var(--km-border);
	border-bottom: none;
	border-radius: var(--km-radius-control) var(--km-radius-control) 0 0;
}

.km-write__sep {
	width: 1px;
	align-self: stretch;
	margin: 2px 4px;
	background: var(--km-border);
}

.km-write__btn {
	font-family: inherit;
	font-size: 13px;
	line-height: 1;
	color: var(--km-text-secondary);
	background: transparent;
	border: 1px solid transparent;
	border-radius: var(--km-radius-control);
	padding: 7px 9px;
	min-width: 30px;
	cursor: pointer;
	transition: background 0.16s, color 0.16s, border-color 0.16s;
}

.km-write__btn:hover { background: var(--km-surface); color: var(--km-text); }

/* НАЖАТОЕ ОТЛИЧАЕТСЯ ПОДЛОЖКОЙ И РАМКОЙ, а не одним цветом букв: признак
   существует не тогда, когда поставлен, а когда его видно рядом
   с ненажатым. */
.km-write__btn[aria-pressed="true"] {
	background: var(--km-surface);
	border-color: var(--km-warm-border);
	color: var(--km-accent);
}

.km-write__btn--b { font-weight: 700; }
.km-write__btn--i { font-style: italic; }

/* Само поле. Скругление снизу, сверху прямое — стык с панелью. */
.km-write__area {
	min-height: 220px;
	border-radius: 0 0 var(--km-radius-control) var(--km-radius-control);
	overflow-wrap: break-word;
}

.km-write__area:focus { outline: none; }

/* Разметка внутри поля показывается так же, как приедет в письме:
   человек правит то, что увидит курсант. Отступ отношением соседей,
   а не полем у каждого. */
/* Одно написание на два места: поле правки и предпросмотр. Разойдись они —
   человек правил бы одно, а видел бы в предпросмотре другое, и заметил бы
   это только по пришедшему письму. */
.km-write__area > *,
.km-letter-preview > * { margin: 0; }
.km-write__area > * + *,
.km-letter-preview > * + * { margin-top: var(--km-gap-paragraph); }
.km-write__area h3,
.km-letter-preview h3 { font-size: 17px; font-weight: 700; line-height: 1.3; }
.km-write__area ul,
.km-write__area ol,
.km-letter-preview ul,
.km-letter-preview ol { padding-left: 22px; }
/* Маркеры списка — свои, а не «как у страницы»: админка WordPress снимает их у всех `ul` (`list-style: none`),
   и в поле письма и в его предпросмотре пункты стояли без точек, а в самом письме почтовая программа их
   ставит (снимок боевого 11.10.2026). Человек правит то, что увидит курсант. */
.km-write__area ul,
.km-letter-preview ul { list-style: disc; }
.km-write__area ol,
.km-letter-preview ol { list-style: decimal; }
.km-write__area li + li,
.km-letter-preview li + li { margin-top: 4px; }
.km-write__area a,
.km-letter-preview a { color: var(--km-accent); }

/* Пустое поле говорит, чего от него ждут. `:empty` для правки не годится:
   редактор кладёт внутрь пустой абзац, и `:empty` перестаёт совпадать. */
.km-write__area[data-empty="да"]::before {
	content: attr(data-placeholder);
	color: var(--km-text-muted);
	pointer-events: none;
}

/* Поле с абзацами с первой строки (`blocks`: окно поста и письмо сценария; документ сообщества 1.89,
   «строки не прыгают»; найдено на боевом 11.10.2026): подсказка лежит ПОВЕРХ первой
   строки, а не строкой в тексте. В потоке она стояла строкой над абзацем — курсор
   мигал под ней, а с первой буквой подсказка уходила, и текст подскакивал на её
   высоту. Отступы — поля самого поля (`.km-write__area`, «Поля ввода»: 12px 14px).
   Письмо сценария — так же (слово Алены 11.10.2026: «письма должны работать так же»). */
.km-write--blocks .km-write__area { position: relative; }

.km-write--blocks .km-write__area[data-empty="да"]::before {
	position: absolute;
	top: 12px;
	left: 14px;
	right: 14px;
}

/* Строка адреса разворачивается под панелью, а не всплывает над текстом:
   всплывающее перекрывает то самое место, куда смотрит человек. */
.km-write__link {
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 8px;
	background: var(--km-bg);
	border: 1px solid var(--km-border);
	border-bottom: none;
}

.km-write__link .km-input { padding: 8px 10px; font-size: 14px; }

/* Набор смайлов — под панелью, как строка адреса (документ сообщества 1.9: пост). */
.km-write__emoji {
	display: flex;
	flex-wrap: wrap;
	gap: 2px;
	padding: 8px;
	background: var(--km-bg);
	border: 1px solid var(--km-border);
	border-bottom: none;
}

.km-write__emoji[hidden] { display: none; }

.km-write__emoji-item {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 36px;
	height: 36px;
	padding: 0;
	font-size: 20px;
	line-height: 1;
	background: transparent;
	border: 1px solid transparent;
	border-radius: var(--km-radius-control);
	cursor: pointer;
}

.km-write__emoji-item:hover { background: var(--km-surface); }

/* ---------------------------------------------------------------------------
   Список сценариев. Макет `design/scenarios-list-v1.html`
   ---------------------------------------------------------------------------
   Столбцы описаны ОДИН раз и общие у шапки и строк. Разъезжались они
   ровно потому, что ширины стояли в двух местах: у `<th>` своё, у ячейки
   своё, и первое же длинное значение их расходило.
   --------------------------------------------------------------------------- */

.km-scn-list__head {
	display: flex;
	align-items: center;
	gap: 14px;
	flex-wrap: wrap;
	margin: 12px 0 8px;
}

.km-scn-list__head .km-h1 { font-size: 28px; }
.km-scn-list__head .km-input { width: auto; min-width: 220px; }
.km-scn-list__spacer { flex: 1 1 auto; }

/*
 * Выключатели «Сценарии и правила» и «Отправка наружу» на экране сценариев
 * (9.11, 18 сентября 2026). Экран строит ритм нижними полями своих блоков —
 * отсюда своё поле, а не обёртка секции, у которой его нет.
 */
.km-scn-switches {
	margin: 4px 0 20px;
}

.km-scn-lead {
	font-size: 14px;
	color: var(--km-text-secondary);
	max-width: 70ch;
	margin: 0 0 20px;
	line-height: 1.6;
}

/* Столбцы: ширины одни на шапку и строки.
 *
 * РАСПРЕДЕЛЕНЫ ПО СОДЕРЖИМОМУ. Правка Алены 14 сентября 2026: «Кому»
 * обрезалось до «Только потоку «С...», а это главное, чем отличаются два
 * сценария с одним событием, — и место у него отнимали два узких числа,
 * которым столько не нужно.
 *
 * Растут двое — название и «Кому»; числа стоят по содержимому, состояние
 * прижато вправо. */
.km-scn-col--name { flex: 1 1 260px; min-width: 0; }
.km-scn-col--when { flex: 0 1 190px; min-width: 0; }
.km-scn-col--who { flex: 1 1 240px; min-width: 0; }
.km-scn-col--steps { flex: 0 0 52px; text-align: right; }
.km-scn-col--fired { flex: 0 0 68px; text-align: right; }
.km-scn-col--state { flex: 0 0 104px; text-align: right; }

.km-scn-row { cursor: pointer; }
.km-scn-row:hover { background: var(--km-surface-alt); }
.km-scn-row:hover .km-scn-row__name { color: var(--km-accent); }

.km-scn-row__name {
	display: block;
	font-weight: 600;
	font-size: 14.5px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* Безымянный сценарий — законное состояние черновика, и он назван
   словами, а не пустотой: пустое место человек читает как поломку. */
.km-scn-row__name--unnamed {
	color: var(--km-text-muted);
	font-weight: 400;
	font-style: italic;
}

.km-scn-row__sub {
	display: block;
	font-size: 12.5px;
	color: var(--km-text-muted);
	margin-top: 2px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* «Письма: передано N · доставлено …» (10.7) — переносится, а не режется:
   главное в строке — числа в конце, и многоточие съедало их первыми
   (боевой 02.10: «…статусов Unisender ещё н…»). Силой селектора (0,2,0). */
.km-scn-row__sub.km-scn-row__sub--wrap {
	overflow: visible;
	text-overflow: clip;
	white-space: normal;
}

.km-scn-row__when,
/* «Кому» — ЦЕЛИКОМ, без обрезки.
 *
 * Обрезка тут врала тихо: «Только потоку «С...» одинаково у сентябрьского
 * и у майского, а это ровно то, чем два сценария с одним событием
 * и различаются. Строка переносится — места на это хватает, потому что
 * столбец теперь растущий. */
.km-scn-row__who {
	font-size: 13.5px;
	color: var(--km-text-secondary);
	overflow-wrap: anywhere;
}

.km-scn-row__num {
	font-family: var(--km-font-display);
	font-size: 16px;
	font-variant-numeric: tabular-nums;
}

.km-scn-row__num--zero { color: var(--km-text-muted); }

/* Выключенное состояние плашки — третий вид рядом с «черновик»
   и «включён». Все три различаются словом, а не только цветом. */
.km-scn-state--off {
	background: var(--km-track);
	color: var(--km-text-muted);
	border-color: var(--km-border);
}

/* Заглушка отправки — полоса НАД списком, а не сноска внизу.
   Пока она стоит, «Включён» в таблице значит «поставит задачу»,
   а не «пошлёт письмо», и знать это надо до чтения списка. */
.km-scn-warn {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	background: var(--km-warm-bg);
	border: 1px solid var(--km-warm-border);
	border-radius: var(--km-radius-control);
	padding: 11px 14px;
	font-size: 13.5px;
	line-height: 1.55;
	color: var(--km-warm-text);

	/* ОТБИТА С ОБЕИХ СТОРОН, А НЕ ТОЛЬКО СНИЗУ. Правка человека
	   8 сентября 2026: полоса прилипала к блоку над ней и читалась
	   его частью — «пустой блок с предупреждением внутри».

	   Шаг общий, `--km-gap-group`: полоса это отдельная вещь на экране,
	   а не подпись к соседу. Прежние 14 снизу были числом ниоткуда. */
	margin: var(--km-gap-group) 0;
}

.km-scn-warn b { color: var(--km-warm-text-strong); font-weight: 700; }
.km-scn-warn svg { flex: none; margin-top: 2px; color: var(--km-warm-text-strong); }

.km-scn-foot {
	display: flex;
	align-items: center;
	gap: 14px;
	flex-wrap: wrap;
	margin-top: 14px;
	font-size: 13px;
	color: var(--km-text-muted);
}

.km-scn-foot a { font-weight: 600; }

/* ---------------------------------------------------------------------------
   Общие сценарии. Спецификация 9.11, этап 11
   ---------------------------------------------------------------------------
   У курса общие стоят отдельным блоком под своими и только для чтения:
   правятся они во «Всех сценариях» (решение Алены 14 сентября 2026).
   Строка поэтому не прикидывается кнопкой — ни курсором, ни подсветкой.
   --------------------------------------------------------------------------- */

.km-scn-shared { margin-top: var(--km-gap-group); }

.km-scn-shared__lead {
	font-size: 13.5px;
	color: var(--km-text-secondary);
	max-width: 70ch;
	margin: 4px 0 12px;
	line-height: 1.55;
}

.km-scn-row--readonly { cursor: default; }
.km-scn-row--readonly:hover { background: transparent; }
.km-scn-row--readonly:hover .km-scn-row__name { color: inherit; }

/* «Не действует здесь» — своей строкой под названием и тёплым цветом:
   это то, из-за чего письмо на этом курсе не придёт, и прочитать это
   надо раньше числа срабатываний. Переносится, а не обрезается. */
.km-scn-row__off {
	display: block;
	font-size: 12.5px;
	line-height: 1.45;
	color: var(--km-warm-text);
	margin-top: 4px;
	white-space: normal;
	overflow-wrap: anywhere;
}

.km-scn-row__edit {
	display: inline-block;
	font-size: 12.5px;
	font-weight: 600;
	margin-top: 4px;
}

/* Выбор курсов охвата — столбик флажков под полем «Курсы».
   `fieldset` отдаёт свою рамку и поля браузера: подпись у группы
   законная, а вид — наш. */
.km-scn-programs {
	border: 0;
	padding: 0;
	margin: 14px 0 0;
	min-width: 0;
}

/* «Показать письмо на курсе» — над предпросмотром, в одну строку. */
.km-scn-preview-on {
	display: flex;
	align-items: center;
	gap: 12px;
	flex-wrap: wrap;
	margin: var(--km-gap-group) 0 12px;
}

.km-scn-preview-on .km-label { margin: 0; }
.km-scn-preview-on .km-input { width: auto; min-width: 220px; max-width: 100%; }

/* Узкий экран: строка перестаёт быть таблицей и становится карточкой. */
@media ( max-width: 820px ) {
	.km-scn-list__head .km-h1 { font-size: 24px; flex-basis: 100%; }

	/*
	 * СТРОКА ОТПУСКАЕТ ШИРИНУ ТАБЛИЦЫ, ИНАЧЕ КАРТОЧКИ НЕ БЫВАЕТ.
	 *
	 * `.km-table__row` держит `min-width: 1040px` под восемь колонок экрана
	 * зачислений, и переноса у неё нет. Правила ниже раскладывали столбцы
	 * карточкой, а строка оставалась шириной 1040 и не складывалась:
	 * телефон раздвигал окно раскладки до 1084 и показывал весь экран
	 * уменьшенным. Комментарий обещал карточку, код её не делал.
	 *
	 * Найдено стендом общих сценариев 14 сентября 2026: он первым мерил
	 * список на 375. Прежний стенд мерил на узком только редактор, а список
	 * к тому мигу был спрятан.
	 *
	 * Шапка столбцов на карточке не нужна: у чисел своё слово (ниже),
	 * а подпись над столбцом, которого нет, висела бы над пустотой.
	 */
	.km-scn-row { min-width: 0; flex-wrap: wrap; }
	.km-scn-colhead { display: none; }

	/*
	 * Метка в CRM на узком: поле при основе 260px рядом с подписью не влезает,
	 * переносится — и корзина уезжала за ним одна на свою строку. Подпись
	 * и корзина остаются строкой, поле встаёт под ними во всю ширину.
	 */
	.km-scn-tagstep__body .km-input { order: 3; flex-basis: 100%; }
	.km-scn-tagstep__hint { order: 4; }

	/*
	 * НА КАРТОЧКЕ НАЗВАНИЕ ПЕРЕНОСИТСЯ, А НЕ РЕЖЕТСЯ. В строке таблицы
	 * обрезка честна: рядом столбцы, и полное название в подсказке.
	 * На карточке шириной в телефон «Поздравление с окончанием ку…» —
	 * это ровно то, чем два сценария различаются, и обрезка врала тихо,
	 * как врала у «Кому». Увидено глазами на стенде 14 сентября 2026.
	 */
	.km-scn-row__name,
	.km-scn-row__sub { white-space: normal; overflow-wrap: anywhere; }

	.km-scn-col--name { flex: 1 1 100%; }
	.km-scn-col--when { flex: 1 1 100%; order: 3; }
	.km-scn-col--who { flex: 0 0 auto; order: 4; }
	.km-scn-col--steps,
	.km-scn-col--fired { flex: 0 0 auto; order: 5; text-align: left; }
	.km-scn-col--state { flex: 0 0 auto; order: 2; margin-left: auto; text-align: right; }

	/*
	 * На карточке у числа появляется слово: столбец без подписи
	 * над ним — это просто число, и «1» рядом с «0» не различить.
	 */
	.km-scn-col--steps .km-scn-row__num::after,
	.km-scn-col--fired .km-scn-row__num::after {
		font-family: var(--km-font);
		font-size: 12.5px;
		color: var(--km-text-muted);
		font-weight: 400;
	}

	.km-scn-col--steps .km-scn-row__num::after { content: " шага"; }
	.km-scn-col--fired .km-scn-row__num::after { content: " раз"; }
}

/* Узкий экран: одна колонка, подстановки под редактором. */
@media ( max-width: 860px ) {
	.km-scn { grid-template-columns: 1fr; }
	.km-scn-side { position: static; }
	.km-scn-block { padding: 18px 16px 20px; }
	.km-chain__add-note { padding-left: 0; }
}

/* Пары «что подставится»: имя поля и значение. */
/*
 * Своих полей у списка нет: расстояние задаёт колонка, в которой он стоит.
 * Так требует общая мерка стендов — «у абзацев в колонках нет своих полей»,
 * и она права: два источника отступа однажды сложатся, и никто не поймёт,
 * какой из них править.
 */
.km-kv {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
	gap: 4px 12px;
	margin: 0;
}

.km-kv dt { color: var(--km-text-secondary); }
.km-kv dd { margin: 0; overflow-wrap: anywhere; }

@media (max-width: 600px) {
	.km-kv { grid-template-columns: minmax(0, 1fr); gap: 2px; }
	.km-kv dd { margin-bottom: 6px; }
}


/* ОКНО ВХОДА ПОД «НАЧАТЬ БЕСПЛАТНО». Правка 8 сентября 2026.
 *
 * Модального окна в системе не было вовсе — это первое. Имена проверены
 * на занятость: `km-modal` и `km-login` не определены больше нигде.
 *
 * Образец назван человеком — модалка LearnDash на курсах старой системы
 * этого же сайта: две половины, слева вход, справа «Создать аккаунт».
 * Оттуда взят состав, а не оформление: вид здесь свой, на наших токенах.
 *
 * ВНУТРЕННИЕ СЕЛЕКТОРЫ ФОРМЫ — РАЗМЕТКА WORDPRESS, а не выдуманные
 * классы: `wp_login_form()` печатает `login-username`, `login-password`,
 * `login-remember`, `login-submit` и `input`. Своей формы входа мы
 * не пишем (второй способ проверить пароль — это второй способ ошибиться),
 * поэтому оформляем чужую разметку, и только под своим контейнером.
 * Правило 13 — про инлайновые стили, а не про то, чья разметка внутри. */
.km-modal {
  position: fixed;
  inset: 0;
  z-index: 10000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}

.km-modal__veil { position: absolute; inset: 0; background: rgba(63, 76, 92, 0.45); }

.km-modal__box {
  position: relative;
  width: 100%;
  max-width: 720px;
  max-height: calc(100vh - 40px);
  overflow-y: auto;
  background: var(--km-surface);
  border-radius: var(--km-radius-card);
  box-shadow: var(--km-shadow-lift);
}

.km-modal__close {
  position: absolute;
  top: 10px;
  right: 12px;
  width: 32px;
  height: 32px;
  padding: 0;
  font-size: 22px;
  line-height: 1;
  color: var(--km-text-muted);
  background: none;
  border: none;
  border-radius: var(--km-radius-control);
  cursor: pointer;
}

.km-modal__close:hover { color: var(--km-text); background: var(--km-surface-alt); }

/* ── Вопрос «точно?» окном сайта ─────────────────────────────────────────────

   `assets/js/confirm.js`, `window.lmsConfirm()` — звёзды курса 1.16, 6.4: снять «Пройдено» только после вопроса,
   окно в виде сайта, а не браузерное. Окно — `km-modal`, здесь только его размер и порядок внутри. */
/* Над окнами сайта: вопрос задают из уже открытого окна (поздравление, окно поста). */
.km-confirm { z-index: 10001; }

.km-confirm__box { max-width: 440px; padding: 28px 24px 22px; }

.km-confirm__text { margin: 0 28px 20px 0; font-size: 16px; font-weight: 600; line-height: 1.55; color: var(--km-text); }

.km-confirm__actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 10px; }

/* Окно с числами (слово Алены 23.10.2026): что изменится и у скольких — строками под вопросом. */
.km-confirm__box:has(.km-confirm__lines) { max-width: 560px; }

.km-confirm__lines { display: grid; gap: 6px; margin: -8px 0 20px; padding: 0 0 0 18px; font-size: 14px; line-height: 1.5; color: var(--km-text); }

.km-confirm__line { margin: 0; }

@media (max-width: 480px) {
  .km-confirm__actions .km-btn { flex: 1 1 auto; }
}

/* ── Окно на платформе ───────────────────────────────────────────────────────

   Спецификация 12.7, решение Алены 22 сентября 2026: приглашение на эфир
   поверх страницы. Окно — то же `km-modal`, что у входа; внутри карточка:
   картинка сверху, ниже заголовок, текст и одна кнопка, «Закрыть».

   Стоит и на ЧУЖИХ страницах — тема BuddyBoss, сообщество, — поэтому
   заголовок, абзац и ссылка-кнопка держатся весом (0,2,0): у темы
   `h2`, `p` и `a` объявлены голыми элементами и классом страницы, и ничья
   по силе выигрывалась бы порядком таблиц, а порядок меняет правка, которая
   о нём не знает (CLAUDE.md, «ничья по силе»).

   Выше всего на странице, включая чат Carrot quest: окно модальное,
   и кружок чата над подложкой читался бы как часть окна. */
.km-modal.km-popup { z-index: 2147483600; }

.km-modal__box.km-popup__box { max-width: 420px; overflow: hidden; }

.km-popup__cover {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

/* Три группы — заголовок, текст, действия — на расстоянии групп; внутри
   текста абзацы на расстоянии абзацев письма, внутри действий кнопка
   и «Закрыть» — на расстоянии подписи. Всё токенами: своих чисел у окна
   нет (правка 22 сентября 2026 — прежние 10 px везде слепляли карточку
   в один ком). */
.km-popup__body {
  display: flex;
  flex-direction: column;
  gap: var(--km-gap-group);
  padding: 22px 24px 16px;
}

.km-popup__texts { display: flex; flex-direction: column; gap: var(--km-gap-paragraph); }

.km-popup__acts { display: flex; flex-direction: column; gap: var(--km-gap-label); margin-top: 8px; }

.km-popup .km-popup__title {
  margin: 0;
  padding: 0;
  font-size: 20px;
  line-height: 1.3;
  font-weight: 700;
  color: var(--km-text);
  overflow-wrap: anywhere;
}

/* Неразрывное слово — прямая ссылка на трансляцию, вставленная в текст
   подстановкой, — переносится где угодно: иначе оно задало бы ширину окну
   и увело бы его за край на 375. */
.km-popup .km-popup__text {
  margin: 0;
  font-size: 15px;
  line-height: 1.5;
  color: var(--km-text-secondary);
  overflow-wrap: anywhere;
}

.km-popup .km-popup__go { text-decoration: none; }

.km-popup .km-popup__later { align-self: center; }

/* Крестик лежит на картинке: без своей подложки он пропал бы на тёмной
   обложке. */
.km-popup .km-modal__close {
  z-index: 1;
  background: rgba(255, 255, 255, 0.92);
  box-shadow: none;
}

.km-popup .km-modal__close:hover,
.km-popup .km-modal__close:focus { background: var(--km-surface); color: var(--km-text); box-shadow: none; }

/* Рамку «Закрыть» и крестика объявляем во всех состояниях, в каких её
   объявляет тема (`button:hover, button:focus { border-color }`). Сегодня
   рамки не видно — у наших кнопок её нет вовсе, — но выигрывала бы цвет
   тема, и первая же правка рамки отдала бы окно ей. Мерка `themeBleed`. */
.km-popup .km-popup__later,
.km-popup .km-popup__later:hover,
.km-popup .km-popup__later:focus,
.km-popup .km-modal__close,
.km-popup .km-modal__close:hover,
.km-popup .km-modal__close:focus { border-color: transparent; }

/* ДВЕ ПОЛОВИНЫ, и правая — на тёплой подложке: она про другое действие,
 * и без разделения читается как продолжение формы. */
.km-login { display: grid; grid-template-columns: 1fr 1fr; }

.km-login__half { padding: 28px; }

.km-login__half--aside {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  background: var(--km-warm-bg);
  border-left: 1px solid var(--km-warm-border);
  border-radius: 0 var(--km-radius-card) var(--km-radius-card) 0;
}

.km-login__title { margin: 0 0 6px; font-size: 18px; font-weight: 700; color: var(--km-text); }
.km-login__text { margin: 0 0 16px; font-size: 14px; line-height: 1.5; color: var(--km-text-secondary); }
.km-login__half--aside .km-login__text { margin-bottom: 4px; }

.km-login__link { display: inline-block; margin-top: 12px; font-size: 13px; color: var(--km-text-secondary); }
.km-login__link:hover { color: var(--km-accent); }

.km-login__form p { margin: 0 0 12px; }
.km-login__form label { display: block; font-size: 13px; color: var(--km-text-secondary); }

.km-login__form .input {
  width: 100%;
  margin-top: 4px;
  padding: 11px 12px;
  font-family: inherit;
  font-size: 15px;
  color: var(--km-text);
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-control);
}

.km-login__form .input:hover { border-color: var(--km-warm-border); }

.km-login__form .input:focus {
  border-color: var(--km-accent);
  outline: 2px solid var(--km-warm-border);
  outline-offset: 1px;
}

.km-login__form .login-remember label {
  display: flex;
  gap: 8px;
  align-items: center;
  margin-top: 2px;
}

.km-login__form .login-submit { margin: 0; }

.km-login__form .button-primary {
  width: 100%;
  padding: 12px 18px;
  font-family: inherit;
  font-size: 15px;
  font-weight: 600;
  color: #fff;
  background: var(--km-accent);
  border: none;
  border-radius: var(--km-radius-control);
  cursor: pointer;
}

.km-login__form .button-primary:hover { background: var(--km-accent-light); }

/* НА УЗКОМ ПОЛОВИНЫ ВСТАЮТ ДРУГ ПОД ДРУГА, и рамка переезжает наверх:
 * слева её было бы не видно, а без неё половины сливаются. */
@media (max-width: 640px) {
  .km-login { grid-template-columns: 1fr; }
  .km-login__half { padding: 22px; }

  .km-login__half--aside {
    border-left: none;
    border-top: 1px solid var(--km-warm-border);
    border-radius: 0 0 var(--km-radius-card) var(--km-radius-card);
  }
}

/* ---------------------------------------------------------------------------
   «Заметили ошибку» — вертикальная вкладка у правого края экрана (12.6)
   ---------------------------------------------------------------------------
   Правка Алены 14 сентября 2026: строка в подвале страницы «никто
   не заметит». Вкладка прижата к правому краю посередине по высоте и стоит
   на месте, пока страница прокручивается; нажали — рядом открывается панель.

   Печатается в конце `<body>`: у `position: fixed` внутри предка
   с `transform` та же ловушка, что у липкости внутри `.site` темы.

   Слой один на вкладку и панель и назван один раз: выше шапки темы (612)
   и BuddyPanel (611), ниже её мобильной панели (999) и лайтбоксов (от 1042).
   Вкладка не ложится поверх окна, которое человек открыл сам.
*/
.km-defect { --km-defect-layer: 900; }

/* СОДЕРЖИМОЕ НЕ ЗАХОДИТ ПОД ВКЛАДКУ — НА ПЛАНШЕТЕ И ШИРЕ. Правки Алены
   15 сентября 2026 (12.6). Вкладка шириной 34 px; место под неё — её ширина
   и 16 воздуха, 50 px:
   - у колонки занятия, которая доходит до края на любой ширине;
   - у «Программы курса», пока она до 1100 px стоит над занятием во всю
     ширину. Первая редакция (1.251.0) её пропустила — «так и не видно
     полностью».
   НА ТЕЛЕФОНЕ, ДО 640, МЕСТА НЕТ. Решение Алены того же дня: «Вкладка пусть
   висит поверх содержимого, это нормально. Не ужимай рабочую поверхность
   без моего решения». Порог — узкий блок дизайн-системы, `max-width: 640px`.
   У страницы курса места нет ни на какой ширине: боковые поля её корня сняты
   целиком (`.km-page--flush`).
   `:has()` у корня, а не у предка: вкладка печатается в конце `<body>`
   и предком содержимого не бывает. Мерки — `stand.clearOfTab()` по всей
   странице и `stand.tabOverPlayer()` на телефоне. */
@media (min-width: 641px) {
	:root:has(.km-defect__tab) .km-player__main { padding-right: 50px; }
}

@media (min-width: 641px) and (max-width: 1100px) {
	:root:has(.km-defect__tab) .km-player__side { padding-right: 50px; }
}

/* ЭКРАНЫ БИБЛИОТЕКИ — МЕСТО ПОД ВКЛАДКУ И НА ТЕЛЕФОНЕ. Задача Алены 4 октября
   2026: «На телефоне не перекрывает кнопки страницы». У занятия на телефоне
   вкладка лежит поверх (решение 15 сентября), у библиотеки — нет: у неё
   у правого края кнопки — сердечки карточек, «Поделиться», поиск.
   До 1250 px: шире содержимое библиотеки (1164 и 1214 с полями 28) до вкладки
   не доходит само. Вес (0,4,0) — сильнее поля телефона `.km-page.km-cast`
   (0,2,0), не порядком. Мерка — `stand.clearOfTab()` на 1280 и 375. */
@media (max-width: 1250px) {
	:root:has(.km-defect__tab) .km-page.km-cast { padding-right: 50px; }
}

/*
 * ЧУЖОЕ УМОЛЧАНИЕ КНОПКИ ГАСИТСЯ ВО ВСЕХ ЕГО СОСТОЯНИЯХ. Механизм записан
 * у `.km-tab` 19 августа и повторился здесь.
 *
 * Тема ставит всякому `button` в покое рамку, `border-radius: 100px`,
 * отступы 10px 20px, `line-height: 1.3`, `text-align: center` и переход
 * `all 0.2s`, а на `:hover` и `:focus` — свой фон, цвет, рамку и серую
 * тень (0,1,1). Первая редакция этой кнопки радиуса не объявляла вовсе,
 * а состояния отдала теме: на боевом вышел «серый текст в пунктирной рамке
 * с закруглением», и после нажатия, в фокусе, — серый ободок.
 *
 * Поэтому раскладка объявлена в покое, а всё, что тема трогает
 * в состояниях, — в каждом из них. Фон пишется ДОЛГОЙ формой
 * `background-color`: короткая `background` с `var()` не раскладывается
 * в CSSOM на долгие, и мерка `stand.themeBleed()` не увидела бы, чьё правило
 * побеждает.
 */
.km-defect__tab {
	position: fixed;
	top: 50%;
	right: 0;
	z-index: var(--km-defect-layer);
	/*
	 * НЕ ЛОЖИТСЯ НА ЧАТ CARROT. Задача Алены 4 октября 2026 (библиотека):
	 * «на телефоне не перекрывает … чат Carrot». Кнопка чата — квадрат 80 px
	 * в правом нижнем углу с полем 65 (его же стиль): верх на 145 px от низа
	 * окна (замер на боевом, 375×812). Посередине высоты вкладка до него
	 * не достаёт, пока окно выше ~500 px; на низком — телефон, повёрнутый
	 * набок, — её поднимает ровно настолько, чтобы низ стоял над чатом
	 * с воздухом 8 px. В сдвиге `50%` — своя высота вкладки, `50vh` —
	 * половина окна: высоту вкладки знать не нужно.
	 */
	transform: translateY(calc(-50% - max(0px, 50% + 153px - 50vh)));
	display: block;
	/* Ширина числом: 14 подписи и по 10 полей. Выведенную из повёрнутой
	   подписи Safari на iPad схлопывал до полей — 20 px из 34, подпись уходила
	   за край экрана (скриншот Алены 15 сентября 2026). Chrome выводит верно,
	   и стенд этого не видит. */
	width: 34px;
	margin: 0;
	padding: 18px 10px;
	border-radius: var(--km-radius-control) 0 0 var(--km-radius-control);
	font-family: inherit;
	font-size: 14px;
	font-weight: 600;
	font-style: normal;
	line-height: 1;
	letter-spacing: 0.02em;
	text-align: center;
	vertical-align: baseline;
	cursor: pointer;
	transition: background-color 0.16s;
}

.km-defect__tab,
.km-defect__tab:hover,
.km-defect__tab:focus,
.km-defect__tab:active {
	border: 0;
	border-color: transparent;
	outline: 0;
	box-shadow: var(--km-shadow-lift);
	background-color: var(--km-accent);
	color: #fff;
	text-decoration: none;
}

.km-defect__tab:hover { background-color: var(--km-accent-light); }

/*
 * НАДПИСЬ ЧИТАЕТСЯ СНИЗУ ВВЕРХ. Правка Алены 14 сентября 2026: «так читается
 * лучше».
 *
 * Поворачивается ПОДПИСЬ, а не кнопка. Поверни мы на 180° саму кнопку —
 * вместе с ней перевернулись бы тень (упала бы вверх), скругление (ушло бы
 * к краю экрана) и обводка фокуса. `writing-mode: sideways-lr`, который
 * пишет снизу вверх без поворота, поддерживается не всеми браузерами, где
 * открывают курс. Направление охраняет мерка стенда: первая буква на экране
 * обязана стоять ниже последней.
 */
.km-defect__label {
	display: block;
	/* Число, а не вывод из текста — по той же причине, что ширина вкладки.
	   Колонка вертикального письма — кегль при `line-height: 1`. */
	width: 14px;
	writing-mode: vertical-rl;
	transform: rotate(180deg);
}

/*
 * Признак фокуса С КЛАВИАТУРЫ — тёмный, а не акцентный: акцентная обводка
 * на акцентной кнопке не видна. Мышью нажимают туда, куда смотрят,
 * и обводка там лишняя — поэтому `:focus-visible`, а не `:focus`.
 */
.km-defect__tab:focus-visible {
	outline: 2px solid var(--km-text);
	outline-offset: 2px;
}

/*
 * Панель — рядом с вкладкой, слева от неё и на той же высоте. Ширина
 * оставляет вкладку видной и на 320: панель её не накрывает.
 *
 * `display: flex` здесь безопасен для `hidden`: в дизайн-системе стоит общее
 * `[hidden] { display: none !important }`, и стенд это спрашивает.
 */
.km-defect__panel {
	position: fixed;
	top: 50%;
	right: 52px;
	z-index: var(--km-defect-layer);
	transform: translateY(-50%);
	box-sizing: border-box;
	display: flex;
	flex-direction: column;
	gap: 12px;
	width: min(380px, calc(100vw - 72px));
	max-height: calc(100vh - 32px);
	overflow-y: auto;
	padding: 18px 20px 20px;
	background-color: var(--km-surface);
	border: 1px solid var(--km-border);
	border-radius: var(--km-radius-card);
	box-shadow: var(--km-shadow-lift);
}

/*
 * Абзацы панели без своих полей — и это не про нас, а про тему:
 * `p { margin: 0 0 1.6875rem }` из `theme.css` раздвинул бы панель
 * на 27 пикселей под каждой строкой. Расстояние задаёт колонка.
 */
.km-defect__panel p { margin: 0; }

.km-defect__head {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 12px;
}

.km-defect__title {
	font-size: 16px;
	font-weight: 600;
	line-height: 1.35;
	color: var(--km-text);
}

.km-defect__close {
	flex: none;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	margin: -6px -8px 0 0;
	padding: 0;
	border-radius: var(--km-radius-control);
	font-family: inherit;
	font-size: 22px;
	font-weight: 400;
	line-height: 1;
	cursor: pointer;
	transition: background-color 0.16s;
}

.km-defect__close,
.km-defect__close:hover,
.km-defect__close:focus,
.km-defect__close:active {
	border: 0;
	border-color: transparent;
	outline: 0;
	box-shadow: none;
	background-color: transparent;
	color: var(--km-text-muted);
	text-decoration: none;
}

.km-defect__close:hover { background-color: var(--km-surface-alt); color: var(--km-text); }

.km-defect__close:focus-visible {
	outline: 2px solid var(--km-accent);
	outline-offset: 2px;
}

.km-defect__form { display: flex; flex-direction: column; gap: 8px; }

.km-defect__text { resize: vertical; }

.km-defect__actions { display: flex; flex-wrap: wrap; gap: 8px; }

/* Ответ о том, что случилось. После удачной отправки он стоит в панели один. */
.km-defect__said {
	font-size: 14px;
	line-height: 1.45;
	color: var(--km-ok);
}

.km-defect__said--bad { color: var(--km-warn); }

/* Строка списка сообщений об ошибках (12.3). */
.km-defect-row {
	display: flex;
	flex-direction: column;
	gap: 6px;
}

/*
 * Разобранное приглушено, а не спрятано: список «все» заводится ровно
 * затем, чтобы видеть и то, с чем уже разобрались. Признак существует,
 * когда отличается, — поэтому приглушение видимое, а не только классом.
 */
.km-defect-row--done { opacity: 0.6; }

.km-defect-row__head { margin: 0; font-weight: 600; }

.km-defect-row__where { margin: 0; color: var(--km-text-muted); font-size: 13px; }

/*
 * Почта и профиль автора — слово Алены 17 сентября 2026. Почта приходит
 * машинным именем без пробелов: без разрыва она раздвинула бы карточку.
 */
.km-defect-row__author {
	margin: 0;
	display: flex;
	flex-wrap: wrap;
	gap: 4px 12px;
	font-size: 13px;
	color: var(--km-text-muted);
	overflow-wrap: anywhere;
}
.km-defect-row__author span { min-width: 0; }

/*
 * Своих полей у абзаца нет: расстояние задаёт колонка, в которой он стоит.
 * Так требует общая мерка стендов, и она права — два источника отступа
 * однажды сложатся, и никто не поймёт, какой из них править.
 */
.km-defect-row__body { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }

/*
 * Адрес приходит машинным именем — без пробелов и какой угодно длины.
 * Неразрывное слово задаёт минимальную ширину карточке, карточка — строке,
 * строка — странице: на узком экран уехал бы за край.
 */
.km-defect-row__url {
	font-size: 12px;
	color: var(--km-text-muted);
	overflow-wrap: anywhere;
}

.km-defect-row__actions {
	display: flex;
	align-items: center;
	gap: 10px;
	flex-wrap: wrap;
	margin-top: 6px;
}

.km-defect-row__done { color: var(--km-text-muted); font-size: 13px; }

/*
 * Заметка и ответ письмом — под сообщением, за чертой.
 *
 * Черта здесь не украшение: выше в карточке лежит то, что написал человек,
 * ниже — то, что делаем мы. Без неё два свободных текста подряд читаются
 * как один, и заметка выглядит продолжением жалобы.
 *
 * Своих полей по бокам нет: их задаёт карточка, в которой блок стоит.
 * Два источника отступа однажды сложатся, и никто не поймёт, какой править.
 */
.km-defect-row__extras {
	margin-top: 10px;
	padding-top: 12px;
	border-top: 1px solid var(--km-border-soft);
}

/* --- «Мои работы»: липкая полоса отбора ---
 *
 * При сотнях работ отбор нужен на любой высоте прокрутки — поэтому
 * липкая, и это из макета `my-work-v2.html`.
 *
 * ## Почему не `km-sticky-bar`
 *
 * Та — «курс и цена»: `top: 0`, поля 28px, размытие под собой, и её
 * носят четыре административных экрана как панель действий. Здесь
 * другое устройство и, главное, другой верх: полоса обязана вставать
 * ПОД липкой обвязкой темы, а не под краем окна.
 *
 * ## Верх — замером, а не числом
 *
 * Сколько сверху занимают шапка темы, промо-полоса и панель
 * администратора, знает только живая страница: на боевом это 134
 * у курсанта и 166 у нас, и слагаемые приходят и уходят сами.
 * Замеряет `chrome.js` (исключение правила 13), а формула здесь —
 * та же, что у колонки курса и у панели сценариев: двадцать сверху
 * это воздух, а не поправка на чужое.
 */
.km-works-bar {
	position: sticky;
	top: calc( var(--km-chrome-top, 0px) + 20px );
	z-index: 5;
	background: var(--km-page);
	padding: 16px 0 12px;
	border-bottom: 1px solid var(--km-border);
	display: flex;
	gap: 10px;
	flex-wrap: wrap;
	align-items: center;
}

/* Поиск тянется, списки — нет: искать по тексту человек будет чаще,
   чем сужать курсом. */
.km-works-bar__search { flex: 1; min-width: 220px; }

/* Список не во всю ширину: рядом с ним ещё один и ряд чипов. */
.km-works-bar__sel { max-width: 230px; }

/* Строка «сколько нашлось» — своей строкой под полосой, во всю ширину:
   она отвечает на вопрос, заданный всей полосой сразу, а не соседним
   полем. */
.km-works-bar__found { width: 100%; }

/* «Показать ещё» — по центру списка, отдельной строкой. */
.km-works__more { display: flex; justify-content: center; padding: 13px; }

@media (max-width: 700px) {
	/* Списки встают в ряд и делят ширину: по 230px их двое не помещаются. */
	.km-works-bar__sel { max-width: none; flex: 1; }
}

/* --- «Мои работы»: строка раскрывается, под вопросом стоит ответ ---
 *
 * Макет `design/my-work-v2.html`, слово Алены 16 сентября 2026.
 *
 * ## Почему не `km-accordion`
 *
 * Тот рисует МОДУЛЬ ПРОГРАММЫ: название 20px дисплейным шрифтом, шапка
 * 18×22, кружок с номером. У него трое живых потребителей — продающая
 * страница, карта курса, экран зачислений. Строка работы другая по
 * устройству: 14,5px обычным, шапка 14×18, квадратная оправа знака,
 * дата справа. Натянуть одно на другое можно только переопределив
 * у модификатора всё, что и составляет компонент, — то есть завести
 * второй смысл под старым именем. Ровно так вышло с `.km-hint`,
 * и девять экранов носили помесь.
 *
 * ## Список — одна поверхность с разделителями
 *
 * Не карточки с зазором: при сотнях работ воздух между строками
 * превращает список в лестницу. Приём взят у `km-accordion--joined`,
 * а не класс — довод общий, устройство разное.
 */
.km-works { display: flex; flex-direction: column; gap: 26px; }

.km-works__group { display: flex; flex-direction: column; gap: 10px; }

/* Шапка группы — надстрочником: это подпись к списку, а не заголовок
   раздела. Курс человек уже выбрал полосой отбора, и крупное название
   спорило бы с названиями самих работ. */
.km-works__course {
	display: flex;
	align-items: center;
	gap: 12px;
	flex-wrap: wrap;
	padding: 6px 2px 0;
}

.km-works__name {
	font-size: 12px;
	font-weight: 700;
	letter-spacing: 0.07em;
	text-transform: uppercase;
	color: var(--km-text-muted);
}

.km-works__count { font-size: 12px; color: var(--km-text-muted); }

.km-works__list {
	background: var(--km-surface);
	border: 1px solid var(--km-border);
	border-radius: var(--km-radius-card);
	box-shadow: var(--km-shadow-card);
	overflow: hidden;
}

/* Черта между строками — мягкая: строки одной группы, а не отдельные
   карточки. Первая строки не получает её вовсе. */
.km-work + .km-work { border-top: 1px solid var(--km-border-soft); }

.km-work__head {
	display: flex;
	align-items: center;
	gap: 13px;
	padding: 14px 18px;
	cursor: pointer;
}

.km-work__head:hover { background: var(--km-surface-alt); }

/*
 * Оправа знака — КВАДРАТНАЯ СО СКРУГЛЕНИЕМ, а не круг `km-icon-circle`:
 * круг в списке читается как аватар или состояние, а здесь знак говорит,
 * какого рода работа. 9px — половина между радиусом кнопки и круга;
 * токена под него нет, и заводить ради одного места незачем.
 */
.km-work__ico {
	flex: none;
	width: 32px;
	height: 32px;
	border-radius: 9px;
	background: var(--km-warm-bg);
	color: var(--km-accent);
	display: flex;
	align-items: center;
	justify-content: center;
}

.km-work__ico svg { display: block; }

.km-work__main { flex: 1; min-width: 0; }

/*
 * Название в одну строку с многоточием: у работ боевого названия длинные
 * («Практикум по Местам Вознесения 2026 — Неделя 1»), и в две строки
 * список перестаёт просматриваться. На узком многоточие снимается —
 * там ширины нет вовсе, и обрезать значило бы прятать.
 */
.km-work__name {
	/*
	 * `block` ОБЯЗАТЕЛЕН, И ЭТО НЕ КОСМЕТИКА. Найдено человеком на боевом
	 * 16 сентября 2026.
	 *
	 * Оба — `<span>`, то есть строчные по умолчанию, и без этого они
	 * встают В ОДНУ СТРОКУ, слипаясь без пробела:
	 * «1.2 Дневник наблюдений1.2 Диагностика энергий · дневник».
	 *
	 * Обрезка с многоточием при этом **работала**, и потому выглядело
	 * правдоподобно: `overflow` и `text-overflow` строчному элементу
	 * не помогают и не мешают, а `white-space: nowrap` держал всё в одной
	 * строке ещё крепче.
	 *
	 * Проверкой на текст такое не ловится по устройству — `textContent`
	 * склеивает соседей без пробела и видит две «найденные» фразы. Ловится
	 * измерением: строка «где» лежит НИЖЕ названия.
	 */
	display: block;
	font-weight: 600;
	font-size: 14.5px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.km-work__where {
	display: block;
	font-size: 12.5px;
	color: var(--km-text-muted);
	margin-top: 2px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.km-work__date {
	font-size: 13px;
	color: var(--km-text-muted);
	flex: none;
	width: 112px;
	text-align: right;
}

.km-work__chev { flex: none; color: #C2CBD6; transition: transform 0.15s; }

details[open] > .km-work__head .km-work__chev { transform: rotate(180deg); }

/*
 * Ответ отступает под название, а не под знак: читается он как
 * продолжение работы, и левый край текста обязан совпасть с её именем.
 * 63 = 18 (поле) + 32 (оправа) + 13 (зазор).
 */
/*
 * ТЕЛО БЕЗ ОТСТУПА ОТ КРАЯ. Макет v3, слово Алены 16 сентября 2026:
 * «никаких полос слева, никакого отступа тела от края».
 *
 * Прежде левое поле равнялось 63px, чтобы текст ответа встал вровень
 * с именем работы: 18 (поле) + 32 (оправа) + 13 (зазор). В v3 внутри
 * строки лежат несколько ответов, разделённых датой и линией, и линия
 * обязана идти во всю ширину карточки — сдвинутая вправо, она читалась
 * бы как полоса сбоку.
 */
.km-work__body {
	padding: 2px 18px 18px;
	display: flex;
	flex-direction: column;
	gap: 14px;
}

.km-work__acts { display: flex; gap: 10px; flex-wrap: wrap; padding-top: 2px; }

/* --- Пара «вопрос — ответ» --- */

.km-qa { display: flex; flex-direction: column; gap: 5px; }

.km-qa__q { font-size: 13px; font-weight: 700; color: var(--km-text-secondary); }

/*
 * `pre-line`, а не `pre-wrap`: человек писал абзацами, и переносы строк
 * — часть того, что он написал. Но отступы в начале строк приходят
 * из формы, а не от него, и сохранять их незачем.
 *
 * `overflow-wrap: anywhere` — в ответах бывают адреса и длинные слова
 * без пробелов; неразрывное слово задало бы минимальную ширину строке,
 * строка — странице, и на 375 экран уехал бы за край.
 */
.km-qa__a {
	font-size: 14.5px;
	line-height: 1.7;
	white-space: pre-line;
	overflow-wrap: anywhere;
}

.km-qa__list { margin: 0; padding-left: 20px; }

/* --- Число ответов в строке и сами ответы (макет v3) --- */

/*
 * ЧИСЛО ОТВЕТОВ — приглушённое, слева от даты. Решение Алены
 * 16 сентября 2026: строка стала формой занятия, и число говорит,
 * сколько раз человек в неё писал: «1 ответ», «183 ответа».
 */
.km-work__count {
	font-size: 12.5px;
	color: var(--km-text-muted);
	flex: none;
	margin-right: 6px;
}

/*
 * ОДИН ОТВЕТ ВНУТРИ СТРОКИ. Ответы идут свежими сверху и отделяются
 * друг от друга ТОНКОЙ ЛИНИЕЙ СВЕРХУ, а не полосой слева: линия
 * принадлежит границе между ответами, полоса принадлежала бы всему
 * блоку и читалась бы как цитата.
 *
 * У первого ответа линии нет — ему не от чего отделяться.
 */
.km-answer { display: flex; flex-direction: column; gap: 8px; }

.km-answer + .km-answer {
	margin-top: 6px;
	padding-top: 14px;
	border-top: 1px solid var(--km-border-soft);
}

/*
 * ДАТА ОТВЕТА. У занятия с одним ответом её здесь нет вовсе — она уже
 * стоит в строке, и повторять значило бы сказать одно дважды.
 */
.km-answer__date {
	font-size: 12.5px;
	font-weight: 700;
	color: var(--km-text-secondary);
	letter-spacing: 0.03em;
}

/*
 * «ПОКАЗАТЬ ЕЩЁ N ОТВЕТОВ» — внутри строки, не карточкой.
 *
 * Отличается от `km-works__more` (тот показывает следующие занятия
 * курса) и потому зовётся иначе: одно имя на два смысла — это сдвиг,
 * который не заметят.
 */
.km-work__more { display: flex; gap: 16px; align-items: center; padding-top: 2px; }

.km-work__more button,
.km-work__more button:hover,
.km-work__more button:focus,
.km-work__more button:active {
	background: none;
	border: 0;
	padding: 0;
	box-shadow: none;
	color: var(--km-accent);
	font-size: 14px;
	font-weight: 600;
	cursor: pointer;
	line-height: 1.4;
}

.km-work__more button:hover { color: var(--km-accent-deep); }

/*
 * ССЫЛКА «ОТКРЫТЬ ЗАНЯТИЕ» — мелкая, в правом нижнем углу, не кнопка.
 * Решение Алены 16 сентября 2026: она дополнение, а не содержимое
 * строки, и кнопка обещала бы главное действие.
 *
 * Состояния темы перечислены явно: BuddyBoss красит `a` своим цветом
 * в `:hover` и `:focus`, и необъявленное здесь досталось бы ей.
 */
.km-work__link,
.km-work__link:hover,
.km-work__link:focus,
.km-work__link:active {
	font-size: 13px;
	color: var(--km-text-muted);
	text-decoration: none;
	box-shadow: none;
}

.km-work__link:hover,
.km-work__link:focus { color: var(--km-accent); }

@media (max-width: 700px) {
	/*
	 * Дата уходит: ширины на колонку нет, а в раскрытой строке она
	 * всё равно стоит рядом с ответом.
	 */
	.km-work__date { display: none; }

	/* Обрезать нечего — показываем целиком, в сколько угодно строк. */
	.km-work__name,
	.km-work__where { white-space: normal; overflow: visible; }

	/* Под знак отступать нечем: 63 съедает треть ширины. */
	.km-work__body { padding-left: 18px; }
}


/* ── Каталог курсов — макет design/catalog-v2.html ──────────────────────────

   Алена, 19 сентября 2026 (спецификация 12.1). Всё своими именами
   `km-catalog-*`: карточка кабинета живёт по решению 3 сентября («сетка
   не растягивает»), а каталогу макет велит обратное — низ карточек ряда
   на одной линии. Одно имя на два решения смешалось бы молча (`.km-hint`). */

.km-catalog-head { display: flex; flex-direction: column; gap: 14px; margin-bottom: 30px; }
.km-catalog-head__title {
  margin: 0;
  font-family: var(--km-font-display);
  font-size: 40px;
  line-height: 1.1;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--km-text);
}
/* Подзаголовок — одной строкой, без ограничения ширины (правка макета 19 сентября 2026). */
.km-catalog-head__lead { margin: 0; font-size: 17px; line-height: 1.55; color: var(--km-text-secondary); }

/* ОТБОРЫ БЕЗ ПАНЕЛИ — правка макета 19 сентября 2026. Поиск отдельным
   полем слева, не во всю ширину; ниже строка по горизонтальной линии:
   разделы вкладками, справа порядок. */
.km-catalog-bar { display: flex; flex-direction: column; gap: 16px; }
.km-catalog-bar__search { max-width: 460px; }
.km-catalog-bar__search .km-input {
  height: 48px;
  padding-top: 0;
  padding-bottom: 0;
  background: var(--km-surface);
  font-size: 15px;
  box-shadow: var(--km-shadow-card);
}
/* По низу, а не по центру: подчёркивание активной обязано лечь на линию
   при любой высоте блока «Сначала». По центру оно всплывало над линией,
   как только тема меняла метрики текста (боевой, 1.302.0–1.302.1). */
.km-catalog-bar__row {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  flex-wrap: wrap;
  border-bottom: 1px solid var(--km-border);
}

.km-catalog-tabs { display: flex; gap: 2px; flex-wrap: wrap; }

/* Вкладка раздела — подчёркнута оранжевым снизу, когда активна; число
   приглушено рядом с названием. Подчёркивание ложится на линию строки
   (`margin-bottom: -1px`).

   ЧУЖОЕ УМОЛЧАНИЕ КНОПКИ ГАСИТСЯ ВО ВСЕХ СОСТОЯНИЯХ, в которых тема его
   объявляет (`button`, `:hover`, `:focus`, `:active`): тема смотрит на имя
   элемента, а не на наш класс. Рамка задаётся целиком — иначе тема
   дорисовала бы три стороны. */
.km-catalog-tab,
.km-catalog-tab:hover,
.km-catalog-tab:focus,
.km-catalog-tab:active {
  appearance: none;
  border: none;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  box-shadow: none;
  background: transparent;
  font-family: inherit;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.4;
  color: var(--km-text-secondary);
  padding: 0 4px 13px;
  margin: 0 12px -1px;
  height: auto;
  cursor: pointer;
  white-space: nowrap;
}
.km-catalog-tab:first-child { margin-left: 0; }
.km-catalog-tab:hover { color: var(--km-text); }
.km-catalog-tab.is-active,
.km-catalog-tab.is-active:hover,
.km-catalog-tab.is-active:focus,
.km-catalog-tab.is-active:active { color: var(--km-text); border-bottom-color: var(--km-accent); }
.km-catalog-tab:focus-visible { outline: 2px solid var(--km-accent); outline-offset: 2px; }
.km-catalog-tab__count { font-weight: 600; font-size: 13.5px; color: var(--km-text-muted); margin-left: 6px; }
.km-catalog-tab.is-active .km-catalog-tab__count { color: var(--km-accent); }

/* «Сначала: новые» справа на той же линии — без рамки и без кнопок. */
/* Метрики свои: тема даёт `label` кегль 17 px, а странице — межстрочный 27 px. */
.km-catalog-sort { display: flex; align-items: center; gap: 6px; margin-left: auto; padding-bottom: 11px; font-size: 14px; line-height: 1.4; }
.km-catalog-sort__label { font-size: 13.5px; color: var(--km-text-muted); white-space: nowrap; }
.km-catalog-sort__select {
  appearance: none;
  -webkit-appearance: none;
  border: 0;
  outline: 0;
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  color: var(--km-text);
  background: transparent url("data:image/svg+xml,%3Csvg width='12' height='8' viewBox='0 0 12 8' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' stroke='%239AA7B6' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat right center;
  padding: 0 20px 0 0;
  /* Высота своя, а не темы: тема ставит всем полям `height: 41px`, и список
     вырастал выше вкладок — подчёркивание активной висело на 10 px над
     линией (боевой, 19 сентября 2026). */
  height: auto;
  min-height: 0;
  line-height: 1.4;
  vertical-align: baseline;
  cursor: pointer;
}
.km-catalog-sort__select:focus-visible { outline: 2px solid var(--km-accent); outline-offset: 2px; }

/* Сетка: три, две, одна (правка макета 19 сентября 2026: карточки крупнее,
   обложки и названия читаются). Растягивает — низ карточек ряда на одной линии. */
.km-grid-cards--catalog {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px;
  align-items: stretch;
  margin-top: 26px;
}
.km-grid-cards--catalog + .km-empty { margin-top: 26px; }

/*
 * КАРТОЧКА — КАРТОЧКА КАБИНЕТА. Правка Алены 19 сентября 2026: «несоответствие
 * тому, как обложка и название курса выглядят в кабинете», «отступы внутри
 * карточки замеряй в кабинете — в каталоге расперло», «размеры шрифтов
 * сравни — нет последовательности».
 *
 * Обложка, тело, кегли и промежутки берутся классами кабинета —
 * `km-course-card`, `km-card__body`, `km-text-secondary`, `km-meta`,
 * `km-course-card__group`, `km-price`, `km-btn`. Здесь только то, чего
 * у кабинета нет по устройству: тень при наведении, растяжка по ряду
 * и раскладка низа (цена справа от длительности). Своих кеглей и отступов
 * здесь нет — любой из них был бы вторым написанием кабинета.
 *
 * ПОД КУРСОРОМ КАРТОЧКА НЕ ДВИГАЕТСЯ. *Слово Алены 23 сентября 2026:
 * «убери дёргающуюся анимацию».* Подъём на 2 px был единственным местом
 * дизайн-системы, где элемент прыгал под курсором: курсор идёт к карточке,
 * карточка уходит из-под курсора. Остаётся тень — она говорит «сюда можно
 * нажать» и ничего не двигает.
 */
.km-catalog-card { transition: box-shadow 0.15s; }
.km-catalog-card:hover { box-shadow: 0 6px 18px rgba(63, 76, 92, 0.14); }

/* Растяжка по ряду (catalog-v2): тело занимает остаток, низ прижат к низу.
   Поле сверху у низа — то же, что даёт группа кабинета, иначе на самой
   высокой карточке ряда оно схлопнулось бы до промежутка тела. Сила (0,2,0),
   а не порядок: у группы кабинета своё `margin-top` той же силы (0,1,0). */
.km-catalog-card__body { flex: 1; }
.km-catalog-card .km-catalog-card__foot { margin-top: auto; padding-top: calc(var(--km-gap-group) - var(--km-gap-label)); }

/* Кнопка — своя группа: после цены и полосы прогресса промежуток тела (10)
   читается как «прилипла» (слово Алены 19 сентября 2026). В кабинете перед
   кнопкой мелкая строка срока, там десятки хватает. */
.km-catalog-card .km-card__body > .km-btn { margin-top: calc(var(--km-gap-group) - var(--km-gap-label)); }

.km-catalog-card__row { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.km-catalog-card__line { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.km-catalog-card__meta { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.km-catalog-card__seats { font-weight: 600; color: var(--km-warm-text-strong); }
.km-catalog-card__seats--none { color: var(--km-danger); }
.km-catalog-card__price { margin: 0; margin-left: auto; text-align: right; }

/* Кнопка своего курса: тёплая подложка, акцентный текст, тёплая рамка. */
.km-btn--warm,
.km-btn--warm:hover,
.km-btn--warm:focus,
.km-btn--warm:active { background: var(--km-warm-bg); color: var(--km-accent); border: 1px solid var(--km-warm-border); box-shadow: none; }
/* Поле на пиксель меньше, чем у `km-btn`: рамка берёт своё, и высота та же, что у остальных кнопок кабинета (как у `--secondary`). */
.km-btn--warm:hover { background: var(--km-peach); color: var(--km-warm-text-strong); }

@media ( max-width: 1040px ) {
  .km-grid-cards--catalog { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media ( max-width: 560px ) {
  .km-catalog-head__title { font-size: 30px; }
  .km-catalog-head__lead { font-size: 15px; }
  .km-catalog-bar__search { max-width: none; }
  .km-catalog-tabs { width: 100%; overflow-x: auto; flex-wrap: nowrap; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
  .km-catalog-tabs::-webkit-scrollbar { display: none; }
  .km-catalog-bar__row { gap: 10px; }
  .km-catalog-sort { margin-left: 0; padding-bottom: 12px; }
  .km-grid-cards--catalog { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------------------------
 * «Клиенты» — список людей и карточка клиента. Спецификация 12.3, макет
 * `design/clients-v1.html`, решения Алены 24 сентября 2026.
 *
 * Карточка клиента — не карточка зачисления: там одна покупка, здесь человек
 * целиком. Строки всех её списков — одной семьёй `km-client-item`, как
 * в макете: название, строка пояснения под ним, справа дата и метка.
 * ------------------------------------------------------------------------- */

/* «{N} клиентов · показаны 1–50» — в ярусе отборов, прижато вправо (макет).
   На узком ярус переносится, и число встаёт своей строкой слева. */
.km-filters__found { margin-left: auto; font-size: 13px; color: var(--km-text-muted); }

/* Тревожный чип — «Платёж не пришёл». Нажатый говорит как все нажатые:
   тревогу уже увидели. Под курсором меняется только цвет. */
.km-chip.km-chip--alarm:not(.is-active),
.km-chip.km-chip--alarm:not(.is-active):hover,
.km-chip.km-chip--alarm:not(.is-active):focus,
.km-chip.km-chip--alarm:not(.is-active):active { color: var(--km-danger); border-color: var(--km-warm-border); }

/* Строка таблицы ведёт в карточку целиком: курсор говорит об этом до нажатия. */
.km-table--link-rows tbody tr { cursor: pointer; }

/* Число у заголовка карточки: «Курсы 12», «Деньги 5 900 ₽ за всё время».
   Подсказка, а не значение, и пишется обычной строкой: заголовок карточки
   набран заглавными, и «5 900 ₽ ЗА ВСЁ ВРЕМЯ» читалось бы как вторая
   надпись, а не пояснение к первой (макет — `<small>` обычным кеглем). */
.km-card__count { margin-left: 8px; font-size: 13px; font-weight: 400; letter-spacing: 0; text-transform: none; color: var(--km-text-muted); }

/* Шапка клиента: фото, имя, строка сведений, действие справа. */
.km-client-head { display: flex; align-items: flex-start; gap: 18px; }

.km-client-head__photo {
  flex: none;
  width: 60px;
  height: 60px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--km-border-soft);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  font-weight: 700;
  color: var(--km-text-muted);
}

.km-client-head__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }

/* Имя — заголовок страницы размером макета (24), а не общего H1: фамилия
   бывает одним неразрывным словом («Турикова-Воскресенская»), и на 375
   общий размер выталкивал страницу до 403. Переносится, если не влезает.
   Силой селектора (0,2,0), а не порядком: `.km-h1` той же силы стоит выше
   по файлу, и ничья, выигранная порядком, проигрывается первой же правкой,
   которая о ней не знает. */
.km-client-head .km-client-head__name { margin: 0; font-size: 24px; line-height: 1.25; overflow-wrap: anywhere; }

/* Почты, «С нами с», «Последний визит», профиль — через пробел, с переносом:
   почта бывает длиннее строки на телефоне и рвётся где угодно. */
.km-client-head__meta { display: flex; flex-wrap: wrap; gap: 6px 18px; margin: 0; font-size: 13.5px; color: var(--km-text-secondary); }
.km-client-head__meta > * { overflow-wrap: anywhere; min-width: 0; }

/* «Почта» под строкой сведений: состояние стоп-листа Unisender, кнопка
   «Снять» рядом и пояснение под ними (10.7). Пояснение — на всю строку:
   рядом с кнопкой длинная фраза ломала бы её. */
.km-client-mail { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; font-size: 13.5px; }
.km-client-mail__state { overflow-wrap: anywhere; min-width: 0; }
/* Состояние здесь — фраза, а не значение столбца: «недоступен навсегда —
   ящик не принимает почту» на 375 без переноса выталкивала страницу до 829.
   Силой селектора (0,2,0), а не порядком: `.km-state` держит `nowrap`. */
.km-client-mail__state .km-state { white-space: normal; align-items: flex-start; }
.km-client-mail__state .km-state__dot { margin-top: 0.45em; }
.km-client-mail__hint { flex: 1 1 100%; margin: 0; font-size: 13px; line-height: 1.5; color: var(--km-text-muted); }
.km-client-mail__hint--danger { color: var(--km-danger); }

/* Строки карточки клиента. */
.km-client-list { display: flex; flex-direction: column; }

.km-client-item {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 13px 0;
  border-top: 1px solid var(--km-border-soft);
  color: inherit;
  text-decoration: none;
}

.km-client-item:first-child { border-top: none; padding-top: 4px; }

.km-client-item__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.km-client-item__name { font-size: 14.5px; font-weight: 600; line-height: 1.35; overflow-wrap: anywhere; }
.km-client-item__meta { font-size: 13px; line-height: 1.45; color: var(--km-text-muted); overflow-wrap: anywhere; }

/* Строка курса ведёт в карточку зачисления: под курсором темнеет название,
   ничего не двигается. */
.km-client-item--link { cursor: pointer; }
.km-client-item--link:hover .km-client-item__name,
.km-client-item--link:focus-visible .km-client-item__name { color: var(--km-accent); }

.km-client-item__side {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 3px;
  text-align: right;
  font-size: 13px;
  color: var(--km-text-muted);
}

/* Полоса прогресса под названием курса — короче строки, как в макете. */
.km-client-item .km-progress { max-width: 220px; margin-top: 6px; }

@media (max-width: 640px) {
  .km-client-head { flex-wrap: wrap; }
  .km-client-head .km-head__acts { width: 100%; }

  /* Правый столбец встаёт под название: рядом ему места нет. */
  .km-client-item { flex-wrap: wrap; }
  .km-client-item__side { flex: 1 1 100%; flex-direction: row; flex-wrap: wrap; align-items: center; gap: 4px 12px; text-align: left; }
}

/* ── Библиотека клиента: админка ───────────────────────────────────────────
 *
 * Макеты `design/admin-library-v1.html` (список) и `design/admin-series-v1.html`
 * (серия), спецификация 12.3 и 4.16. Шапка экрана — общая `km-head`, полоса
 * отбора — общие `km-filters` и `km-chip`, как в «Моих работах».
 */

.km-ad-h2 {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: 30px 0 14px;
  font-family: var(--km-font-display);
  font-size: 20px;
  font-weight: 700;
  line-height: 1.2;
}
.km-ad-h2 span { font-family: var(--km-font); font-size: 14px; font-weight: 600; color: var(--km-text-muted); }

.km-series { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
.km-series__card {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px;
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-card);
  box-shadow: var(--km-shadow-card);
  color: var(--km-text);
  text-decoration: none;
}
.km-series__card:hover { border-color: var(--km-warm-border); color: var(--km-text); }
.km-series__name { font-family: var(--km-font-display); font-size: 17px; font-weight: 700; overflow-wrap: anywhere; }
.km-series__line { font-size: 13px; color: var(--km-text-muted); }

.km-ad-list {
  margin-top: 14px;
  overflow: hidden;
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-card);
  box-shadow: var(--km-shadow-card);
}
.km-ad-list > .km-empty { margin: 0; padding: 16px 18px; }
.km-ad-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 18px;
  color: var(--km-text);
  text-decoration: none;
}
.km-ad-row + .km-ad-row { border-top: 1px solid var(--km-border-soft); }
.km-ad-row:hover { background: var(--km-surface-alt); color: var(--km-text); }
.km-ad-row__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.km-ad-row__title { font-size: 15px; font-weight: 600; overflow-wrap: anywhere; }
.km-ad-row__where { font-size: 13px; color: var(--km-text-muted); }
.km-ad-row__meta { flex: none; display: flex; align-items: center; gap: 16px; }
.km-ad-row__badge { width: 96px; display: flex; justify-content: flex-end; }

.km-ad-more { display: flex; justify-content: center; padding: 13px; border-top: 1px solid var(--km-border-soft); }
.km-ad-more__button,
.km-ad-more__button:hover,
.km-ad-more__button:focus,
.km-ad-more__button:active {
  padding: 0;
  background: none;
  border: 0;
  box-shadow: none;
  color: var(--km-accent);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}

/* Дата-кружок прошедшего — приглушённый; без даты — прочерк на том же месте. */
.km-date-chip--past,
.km-date-chip--none { background: var(--km-track); color: var(--km-text-secondary); }

/*
 * `.km-panel` (карточка полей серии и редактора трансляции, 24.09) снят 17.10.2026: с 25.09 его не ставил никто —
 * экраны ушли в редактор WordPress, — а имя занято страницей Алены «Расписание» (Elementor, `/treningi/kalendar`):
 * так у неё зовётся контейнер со всеми месяцами. Встраиваемая таблица стоит на страницах темы с 11.10, и правило
 * красило этот контейнер белой карточкой с рамкой и тенью. Имя не заводить заново: оно её.
 */

@media (max-width: 900px) {
  .km-series { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 640px) {
  .km-series { grid-template-columns: 1fr; }
  .km-ad-row { flex-wrap: wrap; }
  .km-ad-row__meta { width: 100%; padding-left: 62px; }
  .km-ad-row__badge { width: auto; }
}

/* ── Библиотека клиента: экран трансляции ─────────────────────────────────
 *
 * Макет `design/admin-broadcast-v3.html`: слева содержимое, справа настройки.
 * Части страницы трансляции стояли карточками `km-panel` — класс снят 17.10.2026 (см. выше).
 */

.km-weditor {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: 20px;
  align-items: start;
  margin-top: 22px;
}
.km-weditor__main,
.km-weditor__side { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.km-weditor__title { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; min-width: 0; }
.km-weditor__title .km-h1 { overflow-wrap: anywhere; }
.km-weditor__pair { display: grid; grid-template-columns: 140px minmax(0, 1fr); gap: 10px; }
.km-weditor__when { display: grid; grid-template-columns: minmax(0, 1fr) 110px; gap: 10px; }
/* «Удалить трансляцию» и его вопрос — столбиком под последним разделом,
   кнопка по своей ширине, а не во всю колонку. */
.km-weditor__remove { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; }
.km-weditor__remove > .km-ask { align-self: stretch; }

/* Поле блоками: рамка поля, внутри — редактор блоков ядра. */
.km-blockfield {
  min-height: 150px;
  padding: 10px 14px;
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-control);
}
.km-blockfield--tall { min-height: 220px; }
/* Шрифт холста — наш, а не засечки редактора ядра. Селектор сильнее
   `.editor-styles-wrapper` ядра (0,2,0 против 0,1,0): чужое правило
   перебивается силой, а не порядком таблиц — порядок меняет правка,
   которая о нём не знает (урок 17 сентября, `.site`). */
.km-blockfield .km-blockfield__canvas {
  padding: 0;
  font-family: var(--km-font);
  font-size: 15px;
  line-height: 1.6;
  color: var(--km-text);
}
.km-blockfield .km-blockfield__canvas h2,
.km-blockfield .km-blockfield__canvas h3,
.km-blockfield .km-blockfield__canvas h4 { font-family: var(--km-font-display); }
.km-blockfield__plain { width: 100%; min-height: 130px; }

/* Строка «площадка + ссылка + убрать». Справа, в узкой колонке, площадка
   встаёт над ссылкой. */
.km-link-rows { display: flex; flex-direction: column; gap: 8px; }
.km-link-row { display: grid; grid-template-columns: 150px minmax(0, 1fr) 40px; gap: 8px; align-items: center; }
.km-link-row--file { grid-template-columns: minmax(0, 1fr) 40px; }
.km-link-rows--stacked .km-link-row { grid-template-columns: minmax(0, 1fr) 40px; }
.km-link-rows--stacked .km-link-row .km-select { grid-column: 1 / -1; }

.km-x,
.km-x:hover,
.km-x:focus,
.km-x:active {
  width: 40px;
  height: 40px;
  padding: 0;
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-control);
  background: var(--km-surface);
  box-shadow: none;
  color: var(--km-text-muted);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
}
.km-x:hover { color: var(--km-danger); border-color: var(--km-warm-border); }

.km-add,
.km-add:hover,
.km-add:focus,
.km-add:active {
  align-self: flex-start;
  padding: 4px 0;
  background: none;
  border: 0;
  box-shadow: none;
  color: var(--km-accent);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
.km-add:disabled { color: var(--km-text-muted); cursor: default; }

/* Разобранные главы: время, заголовок, пометка «Практика». */
.km-parsed { border: 1px solid var(--km-border); border-radius: 12px; overflow: hidden; }
/* Строка главы — сеткой, как в макете `admin-webcast-v5`: время, тема,
   пометка. Флексом тема делила ширину с пустой третьей ячейкой и
   переносилась на половине строки (снимок админки 26 сентября 2026). */
.km-parsed__row { display: grid; grid-template-columns: 64px minmax(0, 1fr) auto; gap: 10px; align-items: baseline; padding: 8px 14px; font-size: 14px; line-height: 1.5; }
.km-parsed__row + .km-parsed__row { border-top: 1px solid var(--km-border-soft); }
.km-parsed__row b { color: #A8592F; font-weight: 700; font-variant-numeric: tabular-nums; }
.km-parsed__row span { min-width: 0; overflow-wrap: anywhere; }
.km-parsed__row small { font-size: 11.5px; font-weight: 700; color: #A8592F; background: var(--km-warm-bg); border-radius: 6px; padding: 2px 8px; }
.km-parsed-issues { margin: 0; padding-left: 20px; font-size: 13px; line-height: 1.5; color: var(--km-warn); }
.km-parsed-issues li + li { margin-top: 4px; }

/* Шаги инструкции: номер, текст, убрать. */
.km-step-rows { display: flex; flex-direction: column; gap: 8px; }
.km-step-row { display: grid; grid-template-columns: 28px minmax(0, 1fr) 40px; gap: 8px; align-items: start; }
.km-step-row__num {
  width: 28px;
  height: 28px;
  margin-top: 6px;
  border-radius: 50%;
  background: var(--km-warm-bg);
  color: #A8592F;
  font-size: 13px;
  font-style: normal;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}
.km-textarea--short { min-height: 60px; }
.km-textarea--step { min-height: 40px; }

/* Обложка 16:9: пусто — подпись, выбрана — картинка. */
.km-cover-pick,
.km-cover-pick:hover,
.km-cover-pick:focus,
.km-cover-pick:active {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  padding: 0;
  overflow: hidden;
  border: 1px dashed var(--km-border);
  border-radius: 12px;
  background: var(--km-track);
  box-shadow: none;
  cursor: pointer;
}
.km-cover-pick:hover { border-color: var(--km-warm-border); }
.km-cover-pick__image { width: 100%; height: 100%; object-fit: cover; display: block; }
.km-cover-pick__empty { font-size: 12px; color: var(--km-text-muted); }

/* Подпись выключателя в две строки: что и что это значит. */
.km-switch__text { font-size: 14px; line-height: 1.4; }
.km-switch__text small { display: block; font-size: 12.5px; color: var(--km-text-muted); }

@media (max-width: 900px) {
  .km-weditor { grid-template-columns: 1fr; }
  .km-link-row { grid-template-columns: minmax(0, 1fr) 40px; }
  .km-link-row .km-select { grid-column: 1 / -1; }
}

/* ── Библиотека клиента: страница трансляции ─────────────────────────────
 *
 * Прототип Алены `design/library-prototype/record/index.html` (без параметров —
 * «Запись», `?state=live` — «Эфир»), задача 26 сентября 2026; заменил макеты
 * v3 и v5 целиком. Вид, сетка, шрифты, цвета, отступы и скругления — из его
 * `style.css`, значениями, какими их считает браузер (снято в прототипе
 * на 1280 и 375): у прототипа поверх основной таблицы лежит вторая,
 * «Reading sizes», и прочитанное глазами число часто не то, что на экране.
 * Своих значений нет; добавленное задачей — «Отметить пройденным»,
 * комментарии, кнопки площадок и календарей — собрано из частей прототипа.
 *
 * ТЕМА НЕ РЕШАЕТ НИЧЕГО. Тема BuddyBoss задаёт заголовкам цвет, насыщенность
 * и размер, кнопкам — обводку в наведении, фокусе и нажатии, ссылкам
 * и кнопкам гасит обводку фокуса, а сниппет сайта даёт `h1` отступ сверху
 * с `!important` (замер на боевом 25 сентября 2026). Поэтому каждый элемент
 * страницы объявляет своё во всех состояниях — покой, наведение, фокус,
 * нажатие, — силой селектора под `.km-cast`, а не порядком таблиц (урок
 * `.site`, 17 сентября 2026).
 */

/* Шрифты прототипа — его же файлами, в плагине. Имена свои: «Manrope»
   и «Oswald» — общее пространство, и чужое объявление с тем же именем
   сложилось бы с нашим по диапазонам букв. */
@font-face { font-family: 'KM Manrope'; src: url('../fonts/manrope-latin.woff2') format('woff2'); font-weight: 200 800; font-display: swap; unicode-range: U+0000-00FF, U+2000-206F, U+20AC, U+2122; }
@font-face { font-family: 'KM Manrope'; src: url('../fonts/manrope-cyrillic.woff2') format('woff2'); font-weight: 200 800; font-display: swap; unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: 'KM Oswald'; src: url('../fonts/oswald-latin.woff2') format('woff2'); font-weight: 200 700; font-display: swap; unicode-range: U+0000-00FF, U+2000-206F, U+20AC, U+2122; }
@font-face { font-family: 'KM Oswald'; src: url('../fonts/oswald-cyrillic.woff2') format('woff2'); font-weight: 200 700; font-display: swap; unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }

.km-cast {
  --km-cast-font: 'KM Manrope', Arial, sans-serif;
  --km-cast-display: 'KM Oswald', Arial, sans-serif;
  --km-cast-ink: #33315e;
  --km-cast-body: #51495f;
  --km-cast-red: #d54844;
  --km-cast-red-hover: #ad3533;
  --km-cast-line: #e7dfeb;
  --km-cast-focus: #9b7fb0;
  /* 1164 прототипа + 50: правая колонка шире на 50 (330 вместо 280), а основная
     осталась своих 805 — слово Алены 26 сентября. */
  max-width: 1214px;
  font-family: var(--km-cast-font);
  font-size: 16px;
  line-height: 1.65;
  color: var(--km-cast-body);
}
.km-cast *,
.km-cast *::before,
.km-cast *::after { box-sizing: border-box; }

/* Фон страницы — прототипа (у него `body` #f8f5f9, у темы — #fafbfd).
   Страница трансляции стоит на шаблоне темы во всю ширину, и фон у неё —
   фон тела; меняется он только там, где стоит страница трансляции. */
body:has(.km-page.km-cast) { background-color: #f8f5f9; }

/* Заголовки, ссылки и кнопки страницы — наши во всём, что трогает тема.
   Разговор wpDiscuz (`.km-plain-host`) — его, у него ниже своё. `:where()`
   держит вес (0,1,1): темы (0,0,1) и (0,1,1) порядком не решается,
   наших частных правил (0,2,0) — слабее. */
.km-cast h1:where(:not(.km-plain-host *)),
.km-cast h2:where(:not(.km-plain-host *)),
.km-cast h3:where(:not(.km-plain-host *)),
.km-cast h4:where(:not(.km-plain-host *)),
.km-cast h5:where(:not(.km-plain-host *)),
.km-cast h6:where(:not(.km-plain-host *)) {
  margin: 0;
  padding: 0;
  font-family: var(--km-cast-display);
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: normal;
  text-transform: none;
  color: var(--km-cast-ink);
}
.km-cast p:where(:not(.km-plain-host *)) { margin: 0; }
.km-cast a:where(:not(.km-plain-host *)),
.km-cast a:visited:where(:not(.km-plain-host *)),
.km-cast a:hover:where(:not(.km-plain-host *)),
.km-cast a:focus:where(:not(.km-plain-host *)),
.km-cast a:active:where(:not(.km-plain-host *)),
.km-cast button:where(:not(.km-plain-host *)),
.km-cast button:hover:where(:not(.km-plain-host *)),
.km-cast button:focus:where(:not(.km-plain-host *)),
.km-cast button:active:where(:not(.km-plain-host *)) {
  margin: 0;
  text-decoration: none;
  text-transform: none;
  letter-spacing: normal;
  outline: 0;
  transition: color .18s, background .18s, box-shadow .18s, transform .18s;
  -webkit-tap-highlight-color: transparent;
}
.km-cast a:where(:not(.km-plain-host *)),
.km-cast a:visited:where(:not(.km-plain-host *)),
.km-cast a:hover:where(:not(.km-plain-host *)),
.km-cast a:focus:where(:not(.km-plain-host *)),
.km-cast a:active:where(:not(.km-plain-host *)) { background-color: transparent; }
.km-cast button:where(:not(.km-plain-host *)) { cursor: pointer; font-family: inherit; }
/* Признак фокуса с клавиатуры — прототипа; тема его гасит. */
.km-cast a:focus-visible:where(:not(.km-plain-host *)),
.km-cast button:focus-visible:where(:not(.km-plain-host *)) { outline: 3px solid var(--km-cast-focus); outline-offset: 4px; }
.km-cast svg:where(:not(.km-plain-host *)) { width: 20px; height: 20px; flex-shrink: 0; stroke-width: 1.7; vertical-align: middle; }

/* Карточка прототипа (`.panel`). */
.km-cast .km-cast-card {
  background: #fff;
  border: 1px solid var(--km-cast-line);
  border-radius: 15px;
  box-shadow: 0 5px 20px #44255006;
  overflow: hidden;
}

/* Надстрочник (`.eyebrow`). */
/* «Дата встречи» — и подпись «Ближайших встреч» сообщества (документ сообщества 1.110: «как «Дата встречи»»). */
.km-cast .km-cast-eyebrow,
.km-hub p.km-hub-meet__head,
.km-hub p.km-hub-today__head {
  margin: 0 0 9px;
  font-size: 11px;
  font-weight: 800;
  line-height: 1.65;
  letter-spacing: 1.8px;
  text-transform: uppercase;
  color: #9a7dab;
}

/* ── Крошки (`.breadcrumb`) ── */
.km-cast .km-cast-crumbs {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 18px;
  font-size: 12px;
  line-height: 1.65;
  color: #9c8da6;
}
.km-cast .km-cast-crumbs a,
.km-cast .km-cast-crumbs a:visited,
.km-cast .km-cast-crumbs a:hover,
.km-cast .km-cast-crumbs a:focus,
.km-cast .km-cast-crumbs a:active { color: #8e7a9b; text-decoration: none; }
.km-cast .km-cast-crumbs svg { width: 12px; height: 12px; }
.km-cast .km-cast-crumbs__here { color: #9c8da6; }

/* ── Шапка (`.record-header`) ── */
.km-cast .km-cast-head { max-width: 860px; margin-bottom: 26px; }
/* Стрелки «назад» и «вперёд» справа от шапки — как у занятия (задача Алены 12.10.2026): кнопки `km-btn--square`,
   «назад» обычная, «вперёд» оранжевая; на телефоне 32 px (`.km-btn--square` до 560). Пара не сжимается
   и не переносится. Нет перехода в какую-то сторону — нет и стрелки. */
.km-cast .km-cast-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; }
.km-cast .km-cast-top > .km-cast-head { flex: 0 1 860px; min-width: 0; }
.km-cast .km-cast-arrows { flex: none; display: flex; gap: 6px; padding-top: 4px; }
/* Вид кнопок — дизайн-системы (`.km-btn--primary`, `.km-btn--secondary`), закреплённый весом: общее правило ссылок
   страницы `.km-cast a` (0,1,1) и его состояния (0,2,1) сильнее кнопочных (0,1,0)/(0,2,0) и гасили бы фон. Только
   цвета: рамку и размер даёт дизайн-система, состояние их не меняет (мерка `buttonSize()`). */
.km-cast .km-cast-arrows a.km-btn--primary,
.km-cast .km-cast-arrows a.km-btn--primary:visited,
.km-cast .km-cast-arrows a.km-btn--primary:focus,
.km-cast .km-cast-arrows a.km-btn--primary:active { background: var(--km-accent); color: #fff; }
.km-cast .km-cast-arrows a.km-btn--primary:hover { background: var(--km-accent-light); color: #fff; }
.km-cast .km-cast-arrows a.km-btn--secondary,
.km-cast .km-cast-arrows a.km-btn--secondary:visited,
.km-cast .km-cast-arrows a.km-btn--secondary:focus,
.km-cast .km-cast-arrows a.km-btn--secondary:active { background: var(--km-surface); color: var(--km-text); border-color: var(--km-border); }
.km-cast .km-cast-arrows a.km-btn--secondary:hover { background: var(--km-surface); color: var(--km-accent); border-color: var(--km-warm-border); }
@media (max-width: 700px) {
  .km-cast .km-cast-top { gap: 12px; }
}
.km-cast .km-cast-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 8px;
  border-radius: 5px;
  background: #efe7f5;
  font-family: 'KM Manrope';
  font-size: 11px;
  font-weight: 750;
  line-height: 1.4;
  color: #88639c;
}
.km-cast .km-cast-badge--live { background: #fae9e9; color: #bc5659; }
.km-cast .km-cast-badge svg { width: 12px; height: 12px; }
/* `!important` — только против `!important` сниппета сайта у `h1`. */
.km-cast h1.km-cast-head__title {
  margin: 12px 0;
  padding: 0 !important;
  font-family: var(--km-cast-display);
  font-size: 36px;
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: -.4px;
  text-transform: uppercase;
  color: var(--km-cast-ink);
}
.km-cast .km-cast-head__meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 14px;
  font-size: 13px;
  line-height: 1.65;
  color: #9b81a7;
}
.km-cast .km-cast-head .km-editlinks { margin: 12px 0 0; }
/* Ссылки правки — вид курса (`.km-editlinks`), но во всех состояниях и весом
   выше темы: её `a:hover` (0,1,1) перекрашивал бы их. */
.km-cast .km-editlinks__item,
.km-cast .km-editlinks__item:visited,
.km-cast .km-editlinks__item:focus { color: var(--km-text-secondary); text-decoration: none; }
.km-cast .km-editlinks__item:hover,
.km-cast .km-editlinks__item:active { color: var(--km-accent); text-decoration: none; }
.km-cast .km-cast-head__meta a,
.km-cast .km-cast-head__meta a:visited,
.km-cast .km-cast-head__meta a:hover,
.km-cast .km-cast-head__meta a:focus,
.km-cast .km-cast-head__meta a:active { color: #8c6b9c; text-decoration: none; }

/* ── Сетка (`.record-layout`): основная колонка и 330 справа (правка Алены
   26 сентября: прототип давал 280, основная остаётся прежней). Комментарии —
   под основной колонкой; на узком карточка даты встаёт перед ними, а не
   после разговора любой длины. ── */
.km-cast .km-cast-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 330px;
  grid-template-areas: "main side" "talk side";
  /* Колонки независимы (правка Алены 27 сентября 2026): правая идёт через
     обе строки, и вторая строка гибкая — высота правой колонки уходит в неё,
     а первая строка по основной. Комментарии встают сразу под «Отметить
     пройденным» при любой длине тайминга; на `auto auto` длинный тайминг
     раздувал первую строку и оставлял под основной колонкой пустоту. */
  grid-template-rows: auto 1fr;
  column-gap: 23px;
  align-items: start;
}
.km-cast .km-cast-main { grid-area: main; min-width: 0; }
.km-cast .km-cast-side { grid-area: side; min-width: 0; }
.km-cast .km-cast-talk { grid-area: talk; min-width: 0; }

/* ── Плеер (`.player-panel`): переключатель площадок OmniVideo — вкладками
   прототипа, справа «Выберите удобную площадку», обложка — кругом
   с подписью. Знак и подпись на обложке кладёт `WebcastPage::with_player_look()`
   дверью OmniVideo. ── */
.km-cast .km-cast-player { position: relative; padding: 13px; }
.km-cast .km-cast-player__screen,
.km-cast .km-cast-panel { min-width: 0; }
/* Вкладок нет (одно «О встрече», 29.09) — раздел сразу под плеером: тот же промежуток, что между карточками страницы. */
.km-cast .km-cast-player + .km-cast-panel { margin-top: 23px; }
.km-cast .km-cast-player__hint {
  position: absolute;
  top: 13px;
  right: 15px;
  height: 41px;
  display: flex;
  align-items: center;
  margin: 0;
  font-size: 11px;
  line-height: 1.65;
  color: #a58bae;
  pointer-events: none;
}
/* Рамка плеера без ссылок в «Видео» (29.09.2026): обложка трансляции без надписей,
   в размер плеера — 16:9, те же скругления. Нет обложки — пустая рамка
   фона карточки: место плеера не пустеет и не говорит неправды. */
.km-cast .km-cast-player__frame { position: relative; width: 100%; aspect-ratio: 16 / 9; overflow: hidden; border-radius: 10px; background: #e7ddea; }
.km-cast .km-cast-player__cover { display: block; width: 100%; height: 100%; object-fit: cover; }
.km-cast .km-cast-player .omnivideo-block {
  --omnivideo-embed-border-radius: 10px;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
}
/* Между площадками и видео — 12 px прототипа: у OmniVideo своя щель 16 px. */
.km-cast .km-cast-player .omnivideo-block .omnivideo-body { gap: 0; }
.km-cast .km-cast-player .omnivideo-block .omnivideo-links {
  /* По ширине площадок, как вкладки прототипа: `.omnivideo-body` — флекс,
     и `inline-flex` внутри него стал бы блоком во всю ширину. */
  display: flex;
  width: fit-content;
  align-self: flex-start;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  max-width: calc(100% - 4px);
  margin: 0 0 12px 2px;
  padding: 3px;
  border-radius: 7px;
  background: #f6f1f9;
  overflow: visible;
}
.km-cast .km-cast-player .omnivideo-block .omnivideo-links .omnivideo-link,
.km-cast .km-cast-player .omnivideo-block .omnivideo-links .omnivideo-link:visited,
.km-cast .km-cast-player .omnivideo-block .omnivideo-links .omnivideo-link:hover,
.km-cast .km-cast-player .omnivideo-block .omnivideo-links .omnivideo-link:focus,
.km-cast .km-cast-player .omnivideo-block .omnivideo-links .omnivideo-link:active {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 5px;
  width: auto;
  height: auto;
  padding: 6px 10px;
  border: 0;
  border-radius: 5px;
  background: transparent;
  box-shadow: none;
  font-family: var(--km-cast-font);
  font-size: 14px;
  font-weight: 400;
  line-height: 1.65;
  color: #a18baa;
  text-align: center;
  text-decoration: none;
  transform: none;
}
.km-cast .km-cast-player .omnivideo-block .omnivideo-links .omnivideo-link.current,
.km-cast .km-cast-player .omnivideo-block .omnivideo-links .omnivideo-link.current:hover,
.km-cast .km-cast-player .omnivideo-block .omnivideo-links .omnivideo-link.current:focus,
.km-cast .km-cast-player .omnivideo-block .omnivideo-links .omnivideo-link.current:active,
.km-cast .km-cast-player .omnivideo-block .omnivideo-links:not(:has(.current)) .omnivideo-link:first-child,
.km-cast .km-cast-player .omnivideo-block .omnivideo-links:not(:has(.current)) .omnivideo-link:first-child:hover,
.km-cast .km-cast-player .omnivideo-block .omnivideo-links:not(:has(.current)) .omnivideo-link:first-child:focus,
.km-cast .km-cast-player .omnivideo-block .omnivideo-links:not(:has(.current)) .omnivideo-link:first-child:active {
  background: #fff;
  box-shadow: 0 1px 4px #3f235d0c;
  color: #765389;
}
.km-cast .km-cast-player .omnivideo-block .omnivideo-links .omnivideo-link:focus-visible { outline: 3px solid var(--km-cast-focus); outline-offset: 4px; }
/* Знак площадки — воспроизведение прототипа (`km-cast-pill__icon`), а не логотип OmniVideo. */
.km-cast .km-cast-player .omnivideo-block .omnivideo-links .omnivideo-link svg,
.km-cast .km-cast-player .omnivideo-block .omnivideo-links .omnivideo-link:hover svg,
.km-cast .km-cast-player .omnivideo-block .omnivideo-links .omnivideo-link .km-cast-pill__icon { width: 13px; height: 20px; fill: none; stroke-width: 1.7; transform: none; }
.km-cast .km-cast-player .omnivideo-block .omnivideo-links .omnivideo-link span { font: inherit; color: inherit; }
/* Подложки нет: сиреневая до загрузки плеера — убрана словом Алены 29.09.2026. */
.km-cast .km-cast-player .omnivideo-embed { border-radius: 10px; }
.km-cast .km-cast-player .omnivideo-poster,
.km-cast .km-cast-player .omnivideo-poster:hover { border-radius: 10px; filter: none; }
.km-cast .km-cast-player .omnivideo-icon {
  inset: 0;
  width: auto;
  height: auto;
  border-radius: 10px;
  background: linear-gradient(0deg, #28283c39, transparent 65%);
  transform: none;
}
.km-cast .km-cast-player .km-cast-stage__play {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 58px;
  height: 58px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: #ffffffed;
  box-shadow: 0 4px 24px #36304d17;
  color: #826194;
  transform: translate(-50%, -50%);
}
.km-cast .km-cast-player .omnivideo-icon .km-cast-stage__play svg,
.km-cast .km-cast-player .omnivideo-embed:hover .omnivideo-icon .km-cast-stage__play svg {
  width: 22px;
  height: 22px;
  margin-left: 3px;
  fill: currentColor;
  stroke-width: 0;
  filter: none;
  transform: none;
}
.km-cast .km-cast-player .km-cast-stage__cap {
  position: absolute;
  bottom: 21px;
  left: 0;
  right: 0;
  font-size: 13px;
  line-height: 1.65;
  text-align: center;
  color: #fff;
  text-shadow: 0 2px 10px #333;
}

/* Под плеером (`.under-player`): «В избранное», «Поделиться». */
.km-cast .km-cast-under {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 9px;
  padding: 13px 4px 1px;
}
.km-cast .km-cast-under__btn,
.km-cast .km-cast-under__btn:hover,
.km-cast .km-cast-under__btn:focus,
.km-cast .km-cast-under__btn:active {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  font-size: 13px;
  font-weight: 400;
  line-height: 1.65;
  color: #9b7aab;
}
.km-cast .km-cast-under__btn[aria-pressed="true"],
.km-cast .km-cast-under__btn[aria-pressed="true"]:hover,
.km-cast .km-cast-under__btn[aria-pressed="true"]:focus,
.km-cast .km-cast-under__btn[aria-pressed="true"]:active { color: var(--km-cast-red); }
.km-cast .km-cast-under__btn svg { width: 16px; height: 16px; fill: none; }

/* ── «Эфир»: обложка вместо плеера (`.live-stage`), без «Добавить
   в календарь» — задача 26 сентября; кнопки площадок — под ней. ── */
/* `width: 100%` — не украшение: `aspect-ratio` с `min-height` у прототипа
   раздвигает обложку до 270 × 16/9 = 480 px на телефоне, и заголовок с датой
   режутся справа (в прототипе на 375 так и есть). С шириной колонки высота
   остаётся не меньше минимума, а на широком — 16:9, как было. */
.km-cast .km-cast-live {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  min-height: 310px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  border-radius: 10px;
  background: #e7ddea;
  text-align: center;
}
.km-cast .km-cast-live::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(0deg, #f5eff9ee, #f5eff9ba);
}
.km-cast .km-cast-live__image { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; object-fit: cover; }
/* Заголовок и строка — обёрткой: поля у них прототипа, а во флекс-колонке
   поля абзацев не схлопываются. */
.km-cast .km-cast-live__icon,
.km-cast .km-cast-live__body { position: relative; z-index: 2; }
.km-cast .km-cast-live__icon {
  width: 53px;
  height: 53px;
  display: grid;
  place-items: center;
  margin-bottom: 18px;
  border-radius: 50%;
  background: #fff;
  color: #ac8abc;
}
.km-cast h2.km-cast-live__title { margin: 0 0 10px; font-size: 27px; color: #80588d; }
.km-cast .km-cast-live__text { max-width: 360px; margin: 0 0 20px; padding: 0 20px; font-size: 13px; line-height: 1.65; color: #9f81a9; }
.km-cast .km-cast-live__acts { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; padding: 13px 0 0; }

/* Строка с пояснением (`.info-strip`). */
.km-cast .km-cast-note {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: 22px 0 0;
  padding: 14px 18px;
  border: 1px solid #e6ddeb;
  border-radius: 10px;
  background: #f0eaf5;
  font-size: 14px;
  line-height: 1.65;
  color: #8c729c;
}
.km-cast .km-cast-note svg { width: 17px; height: 17px; margin-top: 2px; }

/* ── Кнопки прототипа (`.primary`, `.secondary`, `.quiet-link`) ── */
.km-cast .km-cast-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.km-cast .km-cast-btn,
.km-cast .km-cast-btn:visited,
.km-cast .km-cast-btn:hover,
.km-cast .km-cast-btn:focus,
.km-cast .km-cast-btn:active {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  min-height: 44px;
  padding: 11px 17px;
  border-radius: 8px;
  font-family: var(--km-cast-font);
  font-size: 14px;
  font-weight: 700;
  line-height: 1.5;
  text-decoration: none;
}
.km-cast .km-cast-btn svg { width: 17px; }
.km-cast .km-cast-btn--primary,
.km-cast .km-cast-btn--primary:visited,
.km-cast .km-cast-btn--primary:focus {
  border: 0;
  background: var(--km-cast-red);
  box-shadow: 0 3px 7px #d5484418;
  color: #fff;
}
.km-cast .km-cast-btn--primary:hover,
.km-cast .km-cast-btn--primary:active { border: 0; background: #bd3e3a; box-shadow: 0 3px 7px #d5484418; color: #fff; }
.km-cast .km-cast-btn--secondary,
.km-cast .km-cast-btn--secondary:visited,
.km-cast .km-cast-btn--secondary:focus {
  border: 1px solid #dfd0e7;
  background: #fff;
  box-shadow: none;
  color: #856595;
}
.km-cast .km-cast-btn--secondary:hover,
.km-cast .km-cast-btn--secondary:active { border: 1px solid #dfd0e7; background: #f4edf8; box-shadow: none; color: #6b477f; }
/* «Пройдено» — зелёным прототипа (`.badge.green`). */
.km-cast .km-cast-btn--done,
.km-cast .km-cast-btn--done:hover,
.km-cast .km-cast-btn--done:focus,
.km-cast .km-cast-btn--done:active { border: 1px solid #edf4ef; background: #edf4ef; box-shadow: none; color: #688c79; }
.km-cast .km-cast-link,
.km-cast .km-cast-link:visited,
.km-cast .km-cast-link:focus {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  line-height: 1.65;
  white-space: nowrap;
  color: var(--km-cast-red);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
}
.km-cast .km-cast-link:hover,
.km-cast .km-cast-link:active { color: var(--km-cast-red-hover); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; }

/* ── Вкладки (`.record-body-tabs`) ── */
.km-cast .km-cast-tabs {
  display: flex;
  gap: 22px;
  margin: 28px 0 24px;
  border-bottom: 1px solid var(--km-cast-line);
}
.km-cast .km-cast-tab,
.km-cast .km-cast-tab:hover,
.km-cast .km-cast-tab:focus,
.km-cast .km-cast-tab:active {
  min-height: 39px;
  margin: 0 0 -1px;
  padding: 0 0 12px;
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  font-size: 14px;
  font-weight: 650;
  line-height: 1.65;
  color: #ab93b6;
}
.km-cast .km-cast-tab[aria-selected="true"],
.km-cast .km-cast-tab[aria-selected="true"]:hover,
.km-cast .km-cast-tab[aria-selected="true"]:focus,
.km-cast .km-cast-tab[aria-selected="true"]:active { border-bottom-color: #9c76ad; color: #785188; }

/* ── Текст вкладок (`.article-panel`) ── */
.km-cast .km-cast-article { padding: 29px; }
.km-cast .km-cast-prose > * { margin: 0 0 17px; }
.km-cast .km-cast-prose > :last-child { margin-bottom: 0; }
/* Внутри блока-группы — тот же отступ, что у текста: абзацы группы (часть
   закрыта меткой, «Правила» у «Кодекса») слипались, 0 px вместо 17 (слово
   Алены 28.09: «разные абзацы не должны прилипать друг к другу, даже если
   они закрыты тегом»). `:where` держит силу на уровне `> *` выше, чтобы
   заголовки и списки сохраняли свои отступы. Скрытый меткой блок не
   рисуется вовсе, и `:last-child` приходится на последний видимый. */
.km-cast .km-cast-prose :where(.wp-block-group, .wp-block-group__inner-container) > * { margin: 0 0 17px; }
.km-cast .km-cast-prose :where(.wp-block-group, .wp-block-group__inner-container) > :last-child { margin-bottom: 0; }
.km-cast .km-cast-prose + .km-cast-prose { margin-top: 17px; }
.km-cast .km-cast-prose p { font-size: 16px; line-height: 1.95; color: #756381; }
.km-cast .km-cast-prose ul,
.km-cast .km-cast-prose ol:not(.km-steps) { padding-left: 21px; font-size: 16px; line-height: 1.9; color: #756381; }
.km-cast .km-cast-prose li + li { margin-top: 4px; }
.km-cast .km-cast-prose strong,
.km-cast .km-cast-prose b { font-weight: 700; }
.km-cast .km-cast-prose a,
.km-cast .km-cast-prose a:visited,
.km-cast .km-cast-prose a:focus { color: var(--km-cast-red); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; }
.km-cast .km-cast-prose a:hover,
.km-cast .km-cast-prose a:active { color: var(--km-cast-red-hover); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; }
.km-cast .km-cast-prose h2,
.km-cast .km-cast-prose .km-practice__title { margin: 0 0 17px; font-family: var(--km-cast-display); font-size: 26px; font-weight: 500; line-height: 1.25; color: var(--km-cast-ink); }
.km-cast .km-cast-prose h3,
.km-cast .km-cast-prose h4,
.km-cast .km-cast-prose h5,
.km-cast .km-cast-prose .km-practice__head { margin: 28px 0 14px; font-family: var(--km-cast-display); font-size: 23px; font-weight: 500; line-height: 1.25; color: var(--km-cast-ink); }
.km-cast .km-cast-prose > h3:first-child,
.km-cast .km-cast-prose > h4:first-child,
.km-cast .km-cast-prose > .km-summary__head:first-child > * { margin-top: 0; }
.km-cast .km-cast-prose .km-practice__head strong { font-weight: inherit; }
/* «Цель практики» — абзацем, как набрано, но с отступом раздела: в прототипе с неё начинается своя часть. */
.km-cast .km-cast-prose .km-practice__goal { margin-top: 28px; }
.km-cast h3.km-cast-article__sub { margin: 28px 0 14px; font-size: 23px; }

/* Конспект прототипа начинается заголовком крупнее прочих (`h2`, дальше `h3`). */
.km-cast .km-cast-summary > :is(h2, h3, h4):first-child,
.km-cast .km-cast-summary > .km-summary__head:first-child > :is(h2, h3, h4) { margin: 0 0 17px; font-size: 26px; }

/* Шаги практики — «Последовательность» прототипа (`.practice-steps`).
   Номер — отдельно слева, текст пункта — ОДНИМ потоком, как абзац: прототип
   ставил `display: flex`, и в нём каждый кусок текста и каждый `<strong>`
   становились отдельной колонкой — жирное в пунктах 02 и 05 «Сети Света»
   уходило столбцом (правка Алены 28.09). Отступ текста 37 px — прежние
   24 px номера и 13 px промежутка. */
.km-cast .km-cast-prose ol.km-steps { counter-reset: km-step; margin: 20px 0; padding: 0; list-style: none; }
.km-cast .km-cast-prose ol.km-steps > li {
  counter-increment: km-step;
  position: relative;
  margin: 0;
  padding: 15px 0 15px 37px;
  border-top: 1px solid var(--km-cast-line);
  font-size: 16px;
  line-height: 1.8;
  color: #756381;
}
.km-cast .km-cast-prose ol.km-steps > li::before {
  content: counter(km-step, decimal-leading-zero);
  position: absolute;
  top: 15px;
  left: 0;
  min-width: 24px;
  font-family: var(--km-cast-display);
  font-size: 20px;
  font-weight: 400;
  color: #b296c0;
}
.km-cast .km-cast-article > .km-cast-actions { margin-top: 20px; }

/* Время у заголовка конспекта (`VideoNav::read`). */
.km-summary__head { display: flex; align-items: center; gap: 12px; }
.km-cast .km-summary__head > h2,
.km-cast .km-summary__head > h3,
.km-cast .km-summary__head > h4 { margin: 0; }
.km-cast .km-cast-prose > .km-summary__head { margin: 28px 0 14px; }
.km-time-btn,
.km-time-btn:hover,
.km-time-btn:focus,
.km-time-btn:active {
  height: 30px;
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0 10px;
  border: 1px solid #dfd0e7;
  border-radius: 8px;
  background: #fff;
  box-shadow: none;
  color: #856595;
  font-size: 13px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}
.km-time-btn:hover,
.km-time-btn:active { background: #f4edf8; color: #6b477f; }

/* ── Карточка практики (`.practice-callout`) ── */
.km-cast .km-cast-callout {
  margin-top: 23px;
  padding: 22px 24px;
  border: 1px solid #e0d1e8;
  border-radius: 12px;
  background: #f0e7f5;
}
.km-cast .km-cast-callout .km-cast-eyebrow { margin-bottom: 8px; }
.km-cast h3.km-cast-callout__title { margin: 0 0 11px; font-size: 25px; color: #785388; }
.km-cast .km-cast-callout__text { margin: 0 0 18px; font-size: 16px; line-height: 1.8; color: #7f698e; }

/* ── «Отметить пройденным» — в конце основной колонки, перед комментариями ── */
/* По центру основной колонки — и «Отметить пройденным», и «Пройдено» (правка Алены 26 сентября). */
.km-cast .km-cast-finish { display: flex; justify-content: center; margin-top: 23px; }

/* ── Справа: карточка даты (`.detail-card`) и «В этом видео» (`.toc`) ── */
.km-cast .km-cast-date,
.km-cast .km-cast-sched { padding: 23px; }
.km-cast .km-cast-date .km-cast-eyebrow { margin-bottom: 13px; }

/* ── «Расписание трансляций» в правой колонке — доска `schedule-side-v1`, вариант Б (задача Алены 12.10.2026,
   1.480.2): отдельная белая карточка под «Датой встречи» тем же видом (`km-cast-card`, отступы — общим правилом
   с `.km-cast-date` выше и в ширинах ниже), подпись маленькой строкой, листки календаря, название сливовым без
   подчёркивания (подчёркивание — при наведении), под ним «Вторник · 19:00 МСК». Ближайшая — закрашенный листок,
   светлая подложка, ярлык «ближайшая»; идущая — тем же порядком красным. Прежняя карточка (`km-schedule`) остаётся
   в описании и в занятиях. ── */
.km-cast .km-cast-schedule { margin-top: 19px; }
.km-cast .km-cast-sched { display: flex; flex-direction: column; gap: 14px; --km-leafs-side: 23px; }
.km-cast .km-cast-sched .km-cast-eyebrow { margin: 0; }
/* СТРОКИ С ЛИСТКОМ КАЛЕНДАРЯ — общий вид `km-leafs` на две страницы (одно правило, а не два написания): расписание
   в правой колонке страницы трансляции курса и «Ближайшие встречи» в правой колонке сообщества (доска
   `nearest-meetings-v1`, документ сообщества 1.110 — «вид должен совпадать», слово Алены 12.10.2026). Каждый селектор
   — с корнем страницы: вес держит ссылку против `.km-cast a` и `.km-hub a`, а сборщик встраиваемой таблицы берёт
   только начинающиеся с `.km-`. */
.km-cast .km-leafs,
.km-hub .km-leafs { display: flex; flex-direction: column; gap: 6px; }
/* Строка — от края до края карточки (документ сообщества 1.111, слово Алены 12.10.2026): подложка ближайшей идёт
   во всю ширину, без полей справа и слева, а листок и текст стоят там же, где в остальных строках. Сколько вылезать
   за поле карточки, знает карточка — `--km-leafs-side` ставится рядом с её полем (`km-cast-sched`, `km-hub-meet`);
   мерка стенда «подложка от края до края» ловит, если поле и вылет разойдутся.
   Листок — по верхнему краю названия, а не по центру строки (общее правило: цифры — по верхнему краю соседнего
   текста, spec 12.4): ряд по верху, листок ниже на расстояние от верха строки названия до верха её букв (15 px
   Manrope при межстрочном 1.35 — 5 px; замер стенда 12.10). Держит общая мерка `stand.numberTops()`. */
.km-cast .km-leafs__row,
.km-hub .km-leafs__row { display: flex; align-items: flex-start; gap: 12px; margin: 0 calc(-1 * var(--km-leafs-side, 0px)); padding: 8px var(--km-leafs-side, 0px); }
.km-cast .km-leafs__row--next,
.km-hub .km-leafs__row--next { background: #f6f1f8; }
.km-cast .km-leafs__row--now,
.km-hub .km-leafs__row--now { background: var(--km-danger-bg); }
.km-cast .km-leafs__leaf,
.km-hub .km-leafs__leaf { flex: none; display: flex; flex-direction: column; align-items: center; justify-content: center; box-sizing: border-box; width: 46px; height: 50px; margin-top: 5px; border: 1px solid #e2d8e8; border-radius: 10px; background: #fff; }
.km-cast .km-leafs__day,
.km-hub .km-leafs__day { font-family: 'KM Oswald', Arial, sans-serif; font-size: 20px; font-weight: 500; line-height: 1; color: #5e4270; }
.km-cast .km-leafs__month,
.km-hub .km-leafs__month { margin-top: 3px; font-size: 10px; font-weight: 800; line-height: 1; letter-spacing: .08em; text-transform: uppercase; color: #9a86a8; }
.km-cast .km-leafs__row--next .km-leafs__leaf,
.km-hub .km-leafs__row--next .km-leafs__leaf { background: #6b4c7c; border-color: #6b4c7c; }
.km-cast .km-leafs__row--now .km-leafs__leaf,
.km-hub .km-leafs__row--now .km-leafs__leaf { background: var(--km-live); border-color: var(--km-live); }
.km-cast .km-leafs__row--next .km-leafs__day,
.km-cast .km-leafs__row--next .km-leafs__month,
.km-cast .km-leafs__row--now .km-leafs__day,
.km-cast .km-leafs__row--now .km-leafs__month,
.km-hub .km-leafs__row--next .km-leafs__day,
.km-hub .km-leafs__row--next .km-leafs__month,
.km-hub .km-leafs__row--now .km-leafs__day,
.km-hub .km-leafs__row--now .km-leafs__month { color: #fff; }
.km-cast .km-leafs__text,
.km-hub .km-leafs__text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; font-family: 'KM Manrope', Arial, sans-serif; }
.km-cast .km-leafs__name,
.km-cast a.km-leafs__name,
.km-cast a.km-leafs__name:visited,
.km-cast a.km-leafs__name:focus,
.km-hub .km-leafs__name,
.km-hub a.km-leafs__name,
.km-hub a.km-leafs__name:visited,
.km-hub a.km-leafs__name:focus { font-size: 15px; font-weight: 600; line-height: 1.35; color: #5e4270; text-decoration: none; overflow-wrap: anywhere; }
.km-cast a.km-leafs__name:hover,
.km-cast a.km-leafs__name:active,
.km-hub a.km-leafs__name:hover,
.km-hub a.km-leafs__name:active { color: #5e4270; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
.km-cast .km-leafs__when,
.km-hub .km-leafs__when { display: flex; flex-wrap: wrap; align-items: center; row-gap: 2px; font-size: 13px; line-height: 1.45; color: #8e8496; }
/* Ярлык на 1 pt мельче доски (11 → 10, разрядка .06 → .05): колонка страницы трансляции 330, а не 360 доски, и при 11
   «Вторник · 19:00 МСК» с ярлыком не помещались в строку на 1 px (замер боевого 12.10.2026). Длинные дни — «Понедельник»,
   «Воскресенье» — переносят ярлык под время, ровно (`flex-wrap`, как на доске). У «Ближайших встреч» ярлык один —
   «идёт сейчас» в общей ленте (документ сообщества 1.126); ближайшая там без ярлыка. */
.km-cast .km-leafs__tag,
.km-hub .km-leafs__tag { margin-left: 6px; padding: 2px 7px; border-radius: 999px; background: #f7e4dc; font-size: 10px; font-weight: 800; line-height: 1.5; letter-spacing: .05em; text-transform: uppercase; white-space: nowrap; color: #9a4a3a; }
.km-cast .km-leafs__tag--now,
.km-hub .km-leafs__tag--now { background: #f8d7d3; color: var(--km-live); }
/* Серая строка под временем — группа или подрубрика «Расписания» (доска `nearest-meetings-v1`, `.grp`). */
.km-cast .km-leafs__note,
.km-hub .km-leafs__note { margin-top: 1px; font-size: 12px; font-weight: 600; line-height: 1.4; color: #7e6a8c; overflow-wrap: anywhere; }
.km-cast .km-cast-sched__foot { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; padding-top: 2px; }
.km-cast p.km-cast-sched__more,
.km-cast p.km-cast-sched__empty { margin: 0; font-size: 13px; line-height: 1.6; color: #8e8496; }
.km-cast a.km-cast-sched__all,
.km-cast a.km-cast-sched__all:visited,
.km-cast a.km-cast-sched__all:focus { font-size: 14px; font-weight: 700; color: #5e4270; text-decoration: none; }
.km-cast a.km-cast-sched__all:hover,
.km-cast a.km-cast-sched__all:active { color: #5e4270; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
/* Число — по верху букв месяца, а не по центру (spec 12.4): по центру на 1280 сходилось случайно (1,5 px), а на телефоне
   число стояло на 4,4 px ниже букв — нашла общая мерка, когда стала искать места сама (12.10.2026). По верху — −0,5
   и 0 px без сдвига: строка числа в его кегль. */
.km-cast .km-cast-date__when { display: flex; align-items: flex-start; gap: 13px; margin: 13px 0 18px; }
.km-cast .km-cast-date__day { font-family: var(--km-cast-display); font-size: 47px; font-weight: 400; line-height: 1; color: #a080b2; }
.km-cast .km-cast-date__month { display: block; font-size: 15px; font-weight: 600; line-height: 1.65; color: #71527f; }
.km-cast .km-cast-date__line { font-size: 12px; line-height: 1.65; color: #a086ac; }
.km-cast .km-cast-host {
  display: flex;
  align-items: center;
  gap: 11px;
  padding-top: 18px;
  border-top: 1px solid var(--km-cast-line);
}
.km-cast .km-cast-host__icon {
  width: 35px;
  height: 35px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: #eee5f4;
  color: #a081b1;
}
.km-cast .km-cast-host__label { display: block; font-size: 12px; line-height: 1.65; color: #a990b2; }
.km-cast .km-cast-host__name { font-size: 13px; font-weight: 650; line-height: 1.65; color: #82648f; }
/* Фото ведущего из профиля — в том же кружке, что значок (правка Алены
   26 сентября 2026). Имя — ссылкой на профиль: в покое как было,
   при наведении — как текстовые ссылки страницы (`.km-cast-link`):
   цвет и подчёркивание, без сдвигов. Состояния списком — тема трогает
   их все (`a:hover` (0,1,1)). */
.km-cast .km-cast-host__icon { overflow: hidden; }
.km-cast .km-cast-host__photo { display: block; width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
.km-cast .km-cast-host__name:link,
.km-cast .km-cast-host__name:visited,
.km-cast .km-cast-host__name:focus { color: #82648f; text-decoration: none; }
.km-cast .km-cast-host__name:hover,
.km-cast .km-cast-host__name:active { color: var(--km-cast-red-hover); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; }
.km-cast .km-cast-date__cal { display: grid; gap: 8px; margin-top: 18px; }
.km-cast .km-cast-date__cal .km-cast-btn { width: 100%; }
/* Строка о доступе в карточке даты — `access-note` прототипа: замочек и
   «Для участников … курсов» на сиреневой подложке (задача доступа 28.09). */
.km-cast .km-cast-access { display: flex; gap: 8px; margin-top: 18px; padding: 12px; border-radius: 8px; background: #f3edf8; font-size: 14px; line-height: 1.7; color: #9b7eab; }
.km-cast .km-cast-access svg { flex: none; width: 15px; height: 15px; margin-top: 4px; stroke-width: 1.7; }

/* Закрытая трансляция (задача доступа 28.09): карточка вместо плеера
   и разделов — замочек, «Трансляция закрыта», строка о доступе, кнопка. */
.km-cast .km-cast-closed { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; max-width: 805px; padding: 29px; }
.km-cast .km-cast-closed__icon { display: grid; place-items: center; width: 53px; height: 53px; border-radius: 50%; background: #f3edf8; color: #ac8abc; }
.km-cast .km-cast-closed__icon svg { width: 22px; height: 22px; stroke-width: 1.7; }
.km-cast .km-cast-closed__title { margin: 0; font-family: var(--km-cast-display); font-size: 26px; font-weight: 500; line-height: 1.25; color: var(--km-cast-ink); }
.km-cast .km-cast-closed__line { margin: 0; font-size: 16px; line-height: 1.8; color: #756381; }
.km-cast .km-cast-closed .km-cast-btn { margin-top: 6px; }

.km-cast .km-cast-toc { margin-top: 19px; padding: 21px; }
.km-cast h2.km-cast-toc__title { margin: 0 0 14px; font-size: 21px; }
/* Строки тайминга прокручиваются внутри карточки — как «Навигация по видео»
   групповых медитаций (виджет km26, «[Медитация #170]»). Значения сняты с живой
   страницы 27 сентября 2026: не выше 550 px, на экранах до 767 px — 300 px,
   `overflow: auto`, `overscroll-behavior: contain`, полоса прокрутки браузерная.
   Короткий тайминг — по содержимому: предел, а не высота. */
.km-cast .km-cast-toc__list { max-height: 550px; overflow: auto; overscroll-behavior: contain; }
.km-cast .km-cast-toc__item,
.km-cast .km-cast-toc__item:hover,
.km-cast .km-cast-toc__item:focus,
.km-cast .km-cast-toc__item:active {
  width: 100%;
  display: flex;
  gap: 10px;
  margin: 0;
  padding: 9px 0;
  border: 0;
  border-bottom: 1px solid #f0e9f4;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  font-size: 13px;
  font-weight: 400;
  line-height: 1.7;
  color: #7f6a8b;
  text-align: left;
}
.km-cast .km-cast-toc__item:last-child,
.km-cast .km-cast-toc__item:last-child:hover,
.km-cast .km-cast-toc__item:last-child:focus,
.km-cast .km-cast-toc__item:last-child:active { border-bottom: 0; }
.km-cast .km-cast-toc__item:hover,
.km-cast .km-cast-toc__item:active { color: var(--km-cast-red); }
/* «Практика месяца» стоит под списком, вне прокрутки: черта над ней — та же,
   что была между строками, когда она шла последней строкой списка. */
.km-cast .km-cast-toc__list + .km-cast-toc__item,
.km-cast .km-cast-toc__list + .km-cast-toc__item:hover,
.km-cast .km-cast-toc__list + .km-cast-toc__item:focus,
.km-cast .km-cast-toc__list + .km-cast-toc__item:active { border-top: 1px solid #f0e9f4; }
.km-cast .km-cast-toc__time { flex: none; padding-top: 1px; font-size: 11px; line-height: 1.7; color: #baa4c5; font-variant-numeric: tabular-nums; }
/* Верх цифр времени — вровень с верхом строки названия (слово Алены 26 сентября). Без сдвига цифры 11 px
   в строке 18,7 стоят на 1,03 px выше заглавных 13 px в строке 22,1 (замер по метрикам шрифта); сдвиг 1 px
   оставляет 0,03. Та же высота строки дала бы 0,67 вниз, выравнивание по базовой линии — 1,47. */
.km-cast .km-cast-toc__item[aria-pressed="true"] .km-cast-toc__time { color: #9c76ad; }

/* ── Комментарии wpDiscuz — в основной колонке, одинаково при любой вкладке,
   в «Эфире» вместо чата. Карточкой прототипа; поле — как поиск прототипа,
   кнопка — `.primary`. Внутри `.km-plain-host` правила wpDiscuz держат
   вес с `#wpdcom`, и наши идут с ним же. ── */
.km-cast .km-cast-talk { margin-top: 23px; padding: 29px; }
/*
 * «Обсуждение» в карточке трансляции: панель смайлов выходит за карточку вниз, а карточки страницы обрезают
 * содержимое (`overflow: hidden` у `.km-cast-card` — ради скругления). Обрезалась на боевом 11.10.2026: на короткой
 * ветке видно было три ряда смайлов из семи. Отступы у карточки есть, содержимое края не касается — обрезать нечего.
 */
.km-cast .km-cast-talk.km-cast-card:has(> .km-hub-discuss) { overflow: visible; }
/* Размер, начертание и цвет — заголовка справа («В этом видео»), правка Алены 26 сентября;
   число рядом стоит по его строке. */
.km-cast h2.km-cast-talk__title { margin: 0 0 17px; font-size: 21px; font-weight: 500; color: var(--km-cast-ink); }
.km-cast .km-cast-talk__count { margin-left: 8px; font-family: var(--km-cast-font); font-size: 14px; font-weight: 800; letter-spacing: 1.8px; color: #9a7dab; }
.km-cast .km-cast-talk #wpdcom { max-width: none; margin: 0; padding: 0; font-family: var(--km-cast-font); color: var(--km-cast-body); }
/* Поля темы и wpDiscuz вокруг формы и пустого списка — наши: иначе
   в карточке стоят 50 px сверху и 70 px пустоты под «0 Комментариев». */
.km-cast .km-cast-talk #comments { margin: 0; padding: 0; }
.km-cast .km-cast-talk #wpdcom .wpd-form-head { border: 0; margin: 0; padding: 0; }
.km-cast .km-cast-talk #wpdcom .wpd-form-wrap,
.km-cast .km-cast-talk #wpdcom .wpdiscuz-textarea-wrap { padding: 0; }
.km-cast .km-cast-talk #wpdcom .wpd-thread-wrapper { margin: 0; }
.km-cast .km-cast-talk #wpdcom .wpd-thread-list { padding: 23px 0 0; }
.km-cast .km-cast-talk #wpdcom .wpd-thread-list:not(:has(.wpd-comment)) { padding: 0; }
.km-cast .km-cast-talk #wpdcom .wpd-avatar img,
.km-cast .km-cast-talk #wpdcom .wpd-avatar img.avatar { border-radius: 50%; border: 0; }
/* `.wpd-form` в селекторе — ради веса: у wpDiscuz (1,3,1), и ничья решалась бы порядком таблиц. */
.km-cast .km-cast-talk #wpdcom .wpd-form textarea.wc_comment,
.km-cast .km-cast-talk #wpdcom .wpd-form textarea.wc_comment:hover,
.km-cast .km-cast-talk #wpdcom .wpd-form textarea.wc_comment:focus,
.km-cast .km-cast-talk #wpdcom .wpd-form textarea.wc_comment:active {
  min-height: 56px;
  margin: 0;
  padding: 14px 16px;
  border: 1px solid var(--km-cast-line);
  border-radius: 10px;
  background: #fff;
  box-shadow: none;
  outline: 0;
  font-family: var(--km-cast-font);
  font-size: 15px;
  line-height: 1.65;
  color: var(--km-cast-body);
}
.km-cast .km-cast-talk #wpdcom .wpd-form textarea.wc_comment:focus { border-color: #ae91c0; box-shadow: 0 0 0 2px #dccbe766; }
.km-cast .km-cast-talk #wpdcom .wpd-form textarea.wc_comment::placeholder { color: #aa98b4; opacity: 1; }
.km-cast .km-cast-talk #wpdcom .wpd-prim-button,
.km-cast .km-cast-talk #wpdcom .wpd-prim-button:hover,
.km-cast .km-cast-talk #wpdcom .wpd-prim-button:focus,
.km-cast .km-cast-talk #wpdcom .wpd-prim-button:active,
.km-cast .km-cast-talk #wpdcom input.wc_comm_submit,
.km-cast .km-cast-talk #wpdcom input.wc_comm_submit:hover,
.km-cast .km-cast-talk #wpdcom input.wc_comm_submit:focus,
.km-cast .km-cast-talk #wpdcom input.wc_comm_submit:active {
  min-height: 44px;
  margin: 0;
  padding: 11px 17px;
  border: 0;
  border-radius: 8px;
  background: var(--km-cast-red);
  box-shadow: 0 3px 7px #d5484418;
  opacity: 1;
  outline: 0;
  text-decoration: none;
  font-family: var(--km-cast-font);
  font-size: 14px;
  font-weight: 700;
  line-height: 1.5;
  letter-spacing: normal;
  text-transform: none;
  color: #fff;
  cursor: pointer;
}
.km-cast .km-cast-talk #wpdcom .wpd-prim-button:hover,
.km-cast .km-cast-talk #wpdcom .wpd-prim-button:active,
.km-cast .km-cast-talk #wpdcom input.wc_comm_submit:hover,
.km-cast .km-cast-talk #wpdcom input.wc_comm_submit:active { background: #bd3e3a; }
.km-cast .km-cast-talk #wpdcom .wpd-prim-button:focus-visible,
.km-cast .km-cast-talk #wpdcom input.wc_comm_submit:focus-visible { outline: 3px solid var(--km-cast-focus); outline-offset: 4px; }
.km-cast .km-cast-talk #wpdcom .wpd-thread-head { margin-top: 23px; border-bottom: 1px solid var(--km-cast-line); }
.km-cast .km-cast-talk #wpdcom .wpd-thread-head .wpd-thread-info {
  padding: 0 0 12px;
  border-bottom: 2px solid #9c76ad;
  border-radius: 0;
  margin-bottom: -1px;
  letter-spacing: normal;
  font-family: var(--km-cast-font);
  font-size: 14px;
  font-weight: 650;
  line-height: 1.65;
  text-transform: none;
  color: #785188;
}
.km-cast .km-cast-talk #wpdcom .wpd-thread-head .wpd-thread-info .wpdtc { font-size: inherit; color: inherit; }
.km-cast .km-cast-talk #wpdcom .wpd-comment .wpd-comment-author,
.km-cast .km-cast-talk #wpdcom .wpd-comment .wpd-comment-author a { font-family: var(--km-cast-font); font-size: 14px; font-weight: 650; color: var(--km-cast-ink); text-decoration: none; }
.km-cast .km-cast-talk #wpdcom .wpd-comment .wpd-comment-date { font-size: 12px; color: #a28aac; }
.km-cast .km-cast-talk #wpdcom .wpd-comment .wpd-comment-text,
.km-cast .km-cast-talk #wpdcom .wpd-comment .wpd-comment-text p { font-family: var(--km-cast-font); font-size: 15px; line-height: 1.8; color: #756381; }
.km-cast .km-cast-talk #wpdcom .wpd-comment .wpd-reply-button,
.km-cast .km-cast-talk #wpdcom .wpd-comment .wpd-reply-button span,
.km-cast .km-cast-talk #wpdcom .wpd-comment .wpd-vote,
.km-cast .km-cast-talk #wpdcom .wpd-comment .wpd-comment-share { font-size: 13px; color: #9b7aab; }
.km-cast .km-cast-talk #wpdcom .wpd-comment .wpd-comment-header,
.km-cast .km-cast-talk #wpdcom .wpd-comment .wpd-comment-footer { border-color: var(--km-cast-line); }

/* Всплывающее сообщение (`#toast`). */
.km-cast .km-cast-toast {
  position: fixed;
  z-index: 100;
  bottom: 26px;
  left: 50%;
  width: max-content;
  max-width: calc(100% - 30px);
  padding: 12px 20px;
  border-radius: 10px;
  background: #4c385d;
  box-shadow: 0 7px 30px #3327442b;
  font-size: 14px;
  line-height: 1.65;
  color: #fff;
  opacity: 0;
  pointer-events: none;
  transform: translate(-50%, 20px);
  transition: opacity .2s, transform .2s;
}
.km-cast .km-cast-toast--on { opacity: 1; transform: translate(-50%, 0); }

/* ── «Назад / Дальше» — трансляция в курсе (вариант Б, 27.09.2026). Карточки
   страницы: соседи слева и справа, пустая сторона держит место. ── */
.km-cast .km-cast-pager { display: flex; gap: 23px; margin-top: 23px; }
.km-cast .km-cast-pager__gap { flex: 1 1 0; }
.km-cast a.km-cast-pager__link,
.km-cast a.km-cast-pager__link:visited,
.km-cast a.km-cast-pager__link:hover,
.km-cast a.km-cast-pager__link:focus,
.km-cast a.km-cast-pager__link:active {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 17px 21px;
  background: #fff;
  border: 1px solid var(--km-cast-line);
  border-radius: 15px;
  box-shadow: 0 5px 20px #44255006;
  text-decoration: none;
  color: var(--km-cast-ink);
}
.km-cast a.km-cast-pager__link--prev { text-align: left; }
.km-cast a.km-cast-pager__link--next { text-align: right; }
.km-cast .km-cast-pager__word { font-size: 11px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: #a08aad; }
.km-cast .km-cast-pager__title { font-family: var(--km-cast-display); font-size: 17px; font-weight: 500; line-height: 1.3; color: var(--km-cast-ink); }
.km-cast a.km-cast-pager__link:hover .km-cast-pager__title,
.km-cast a.km-cast-pager__link:active .km-cast-pager__title { color: var(--km-cast-red); }
.km-cast a.km-cast-pager__link:focus-visible { outline: 3px solid var(--km-cast-focus); outline-offset: 3px; }
@media (max-width: 700px) {
  .km-cast .km-cast-pager { gap: 12px; margin-top: 20px; }
  .km-cast a.km-cast-pager__link { padding: 14px 15px; }
  .km-cast .km-cast-pager__title { font-size: 15px; }
}

/* ── Ширины — прототипа ── */
@media (max-width: 1250px) {
  .km-cast .km-cast-layout { column-gap: 17px; }
  .km-cast .km-cast-date,
  .km-cast .km-cast-sched,
  .km-cast .km-cast-toc { padding: 18px; }
  .km-cast .km-cast-sched { --km-leafs-side: 18px; }
}
/* Между 900 и 1200 — пропорционально экрану: 330 на 1200, и не уже прежних 242. */
@media (max-width: 1199.98px) {
  .km-cast .km-cast-layout { grid-template-columns: minmax(0, 1fr) clamp(242px, 27.5vw, 330px); }
}
@media (max-width: 767px) {
  .km-cast .km-cast-toc__list { max-height: 300px; }
}
@media (max-width: 700px) {
  /* Поле по бокам на телефоне — прототипа (18 px), а не общее `.km-page` (28):
     на 28 карточка даты в две колонки переносила «сентября / 2026». Тема
     на этой странице своих полей не даёт. */
  .km-page.km-cast { padding-left: 18px; padding-right: 18px; }
  .km-cast .km-cast-crumbs { gap: 5px; margin-bottom: 15px; font-size: 11px; }
  .km-cast .km-cast-head { margin-bottom: 21px; }
  .km-cast h1.km-cast-head__title { margin: 12px 0 10px; font-size: 31px; }
  .km-cast .km-cast-head__meta { gap: 9px; }
  .km-cast .km-cast-layout { display: flex; flex-direction: column; gap: 20px; }
  /* Колонка в разметке раньше основной (приходит с первыми байтами) — на телефоне порядок прежний: основная, колонка,
     комментарии. */
  .km-cast .km-cast-layout > .km-cast-main { order: 1; }
  .km-cast .km-cast-layout > .km-cast-side { order: 2; }
  .km-cast .km-cast-layout > .km-cast-talk { order: 3; }
  .km-cast .km-cast-main,
  .km-cast .km-cast-side,
  .km-cast .km-cast-talk { width: 100%; }
  .km-cast .km-cast-talk { margin-top: 0; padding: 23px; }
  /* Подсказка wpDiscuz на узком — в две строки: поле держит обе. Кегль 16 —
     как у wpDiscuz на узком: мельче телефон увеличивает страницу при вводе.
     `!important` — только против `!important` wpDiscuz (до 600 px). */
  .km-cast .km-cast-talk #wpdcom .wpd-form textarea.wc_comment,
  .km-cast .km-cast-talk #wpdcom .wpd-form textarea.wc_comment:hover,
  .km-cast .km-cast-talk #wpdcom .wpd-form textarea.wc_comment:focus,
  .km-cast .km-cast-talk #wpdcom .wpd-form textarea.wc_comment:active { min-height: 84px; font-size: 16px !important; }
  .km-cast .km-cast-player { padding: 9px; }
  .km-cast .km-cast-player__hint { display: none; }
  .km-cast .km-cast-player .omnivideo-block .omnivideo-links { margin: 2px 0 12px 2px; }
  .km-cast .km-cast-player .km-cast-stage__play { width: 43px; height: 43px; }
  .km-cast .km-cast-player .km-cast-stage__cap { bottom: 12px; font-size: 11px; }
  .km-cast .km-cast-under { flex-wrap: wrap; padding: 10px 2px 2px; }
  .km-cast .km-cast-under__btn,
  .km-cast .km-cast-under__btn:hover,
  .km-cast .km-cast-under__btn:focus,
  .km-cast .km-cast-under__btn:active { font-size: 12px; }
  .km-cast .km-cast-live { min-height: 270px; }
  .km-cast .km-cast-note { margin-top: 18px; padding: 12px 14px; }
  .km-cast .km-cast-tabs { gap: 24px; margin: 23px 0 19px; }
  .km-cast .km-cast-article { padding: 23px; }
  .km-cast .km-cast-prose p { line-height: 1.9; }
  .km-cast .km-cast-prose h2,
  .km-cast .km-cast-prose .km-practice__title,
  .km-cast .km-cast-summary > :is(h2, h3, h4):first-child,
  .km-cast .km-cast-summary > .km-summary__head:first-child > :is(h2, h3, h4) { font-size: 25px; }
  .km-cast .km-cast-prose h3,
  .km-cast .km-cast-prose h4,
  .km-cast .km-cast-prose h5,
  .km-cast .km-cast-prose .km-practice__head,
  .km-cast h3.km-cast-article__sub { font-size: 22px; }
  .km-cast .km-cast-callout { padding: 20px; }
  /*
   * Колонка даты — по ширине своей строки, ведущая — в остатке (задача Алены 12.10.2026, 1.480.2): «Вторник · 19:00
   * Мск» помещается целиком, а «Мск» не уходит отдельной строкой — при 1fr 1fr колонка даты на боевом была 138 px,
   * строке нужно 110–138. Имя ведущей переносится в своей колонке и за неё не выходит.
   */
  .km-cast .km-cast-date { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 0 15px; padding: 17px; }
  .km-cast .km-cast-date__line { white-space: nowrap; }
  .km-cast .km-cast-date > .km-cast-host,
  .km-cast .km-cast-date > .km-cast-host > div { min-width: 0; }
  .km-cast .km-cast-date .km-cast-host__name { overflow-wrap: anywhere; }
  .km-cast .km-cast-sched { padding: 17px; --km-leafs-side: 17px; }
  .km-cast .km-cast-schedule { margin-top: 20px; }
  .km-cast .km-cast-date > .km-cast-eyebrow,
  .km-cast .km-cast-date__cal,
  .km-cast .km-cast-access { grid-column: 1 / -1; }
  .km-cast .km-cast-access { margin-top: 12px; padding: 9px; font-size: 12px; }
  .km-cast .km-cast-closed { padding: 22px; }
  .km-cast .km-cast-closed__title { font-size: 23px; }
  .km-cast .km-cast-date__when { gap: 9px; margin: 8px 0 12px; }
  .km-cast .km-cast-date__day { font-size: 39px; }
  .km-cast .km-cast-date__month { font-size: 13px; }
  .km-cast .km-cast-host { gap: 7px; padding-top: 12px; border-top: 0; }
  .km-cast .km-cast-host__icon { width: 28px; height: 28px; }
  .km-cast .km-cast-host__label { font-size: 11px; }
  .km-cast .km-cast-host__name { font-size: 12px; }
  /* «В этом видео» на телефоне — есть, как «Навигация по видео» медитаций
     (правка Алены 27 сентября 2026); прототип прятал его. Встаёт под датой. */
  .km-cast .km-cast-toc { margin-top: 20px; }
  .km-cast .km-cast-toast { bottom: 83px; font-size: 12px; }
}
@media (prefers-reduced-motion: reduce) {
  .km-cast *,
  .km-cast .km-cast-toast { transition: none; }
}

/* ── Общее с лентой: звёздочка избранного и «Пройдено» ── */
/* Звёздочка избранного: выбранная — тёплая и залитая; у крупной — ещё и тёплая подложка. */
.km-fav,
.km-fav:hover,
.km-fav:focus,
.km-fav:active {
  width: 40px;
  height: 40px;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-control);
  background: var(--km-surface);
  box-shadow: none;
  color: var(--km-text-muted);
  font-family: inherit;
  font-size: 14px;
  font-weight: 400;
  line-height: 1;
  cursor: pointer;
}
.km-fav--sm,
.km-fav--sm:hover,
.km-fav--sm:focus,
.km-fav--sm:active { width: 32px; height: 32px; border-color: transparent; background: none; }
.km-fav:hover { color: var(--km-accent); }
.km-fav[aria-pressed="true"],
.km-fav[aria-pressed="true"]:hover,
.km-fav[aria-pressed="true"]:focus { color: var(--km-accent); }
.km-fav:not(.km-fav--sm)[aria-pressed="true"],
.km-fav:not(.km-fav--sm)[aria-pressed="true"]:hover,
.km-fav:not(.km-fav--sm)[aria-pressed="true"]:focus,
.km-fav:not(.km-fav--sm)[aria-pressed="true"]:active { background: var(--km-warm-bg); border-color: var(--km-warm-border); }

/* «Пройдено» строкой в ленте. */
.km-done-mark { display: inline-flex; align-items: center; gap: 5px; font-size: 13px; font-weight: 600; color: var(--km-done); white-space: nowrap; }

/* ── Библиотека клиента: лента ─────────────────────────────────────────────
 *
 * Макет `design/library-v1.html`. Карточка ближайшего — общая `km-live`
 * (`live-card.js`) с тем, чего у карточки занятия нет: название, «откуда»,
 * полоса со звёздочкой. Записи — по месяцам, списком в карточке.
 */

.km-feed { max-width: 1000px; }
.km-feed__bar {
  position: sticky;
  top: var(--km-chrome-top, 0px);
  z-index: 5;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 16px 0 12px;
  background: var(--km-page);
  border-bottom: 1px solid var(--km-border);
}
.km-feed__h2 { margin: 30px 0 14px; font-family: var(--km-font-display); font-size: 21px; font-weight: 700; }
.km-feed__next { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }

.km-live__title { margin: 8px 0 0; font-family: var(--km-font-display); font-size: 19px; line-height: 1.25; overflow-wrap: anywhere; }
.km-live__title a { color: var(--km-text); text-decoration: none; }
.km-live__title a:hover { color: var(--km-accent); }
.km-live__where { margin-top: 2px; font-size: 13.5px; color: var(--km-text-secondary); }
.km-live__foot { display: flex; align-items: center; justify-content: flex-end; gap: 12px; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--km-border-soft); }

.km-feed__month { margin: 22px 2px 10px; font-size: 13.5px; font-weight: 700; color: var(--km-text-secondary); }
.km-feed__list {
  overflow: hidden;
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-card);
  box-shadow: var(--km-shadow-card);
}
/* Строка записи — по верху, как на телефоне: кружок с датой — цифра рядом с текстом, и его верх — на верху букв
   названия (общее правило, spec 12.4; до 1.481.1 строка стояла по центру, и кружок был выше букв на 8–20 px — нашла
   общая мерка `stand.numberTops()`, когда стала искать места сама). Сдвиг 8 px — от верха строки названия (15 px
   Manrope при межстрочном 1.65) до верха букв. */
.km-feed__item { display: flex; align-items: flex-start; gap: 14px; padding: 13px 16px 13px 18px; }
.km-feed__item + .km-feed__item { border-top: 1px solid var(--km-border-soft); }
.km-feed__item:hover { background: var(--km-surface-alt); }
.km-feed__item .km-date-chip { margin-top: 8px; text-decoration: none; }
.km-feed__main { position: relative; flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; text-decoration: none; }
.km-feed__title { font-size: 15px; font-weight: 600; color: var(--km-text); overflow-wrap: anywhere; text-decoration: none; }
.km-feed__where { font-size: 13px; color: var(--km-text-muted); }
.km-feed__meta { flex: none; display: flex; align-items: center; gap: 18px; }
.km-feed__state { width: 92px; display: flex; justify-content: flex-end; }
.km-feed__more { display: flex; justify-content: center; padding: 13px; border-top: 1px solid var(--km-border-soft); }
.km-feed__more-button,
.km-feed__more-button:hover,
.km-feed__more-button:focus,
.km-feed__more-button:active {
  padding: 0;
  border: 0;
  background: none;
  box-shadow: none;
  color: var(--km-accent);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}

@media (max-width: 760px) {
  .km-feed__next { grid-template-columns: 1fr; }
  .km-feed__item { position: relative; align-items: flex-start; flex-wrap: wrap; }
  .km-feed__main { padding-right: 36px; }
  .km-feed__meta { width: 100%; padding-left: 62px; flex-wrap: wrap; gap: 4px 14px; }
  .km-feed__state { width: auto; }
  .km-feed__meta .km-fav { position: absolute; top: 10px; right: 10px; }
}

/* БИБЛИОТЕКА КЛИЕНТА — РЕДАКТОР WORDPRESS, СЕРИЯ, ПЛИТКИ. Решение Алены
   25 сентября 2026; макеты `admin-webcast-v4.html`, `admin-series-v2.html`,
   `admin-library-v2.html`, `library-v2.html`, `library-series-v1.html`.

   Раздел на холсте редактора (`lms/library-section`): пунктирная рамка,
   подпись «Раздел · {вид}», внутри — любые блоки. Выбранный — сплошной
   рамкой в цвет акцента, как в макете.

   Шрифт, кегль и цвет текста раздел НЕ задаёт: текст внутри — как
   в обычной записи этого сайта (слово Алены 26 сентября 2026), то есть
   тем, что даёт холсту WordPress. Замерено на боевом в «[Медитация #170]»:
   системный шрифт, 18 px, межстрочный 32,4. Своё здесь — рамка и отступы. */
/* `border-box` обязателен: в холсте WordPress общего `* { box-sizing }`
   нет (оно в полной таблице и в холст не едет), и с `content-box` рамка
   раздела выходила на 19 px за колонку по обе стороны — 878 при колонке
   840 (снимок боевого 26 сентября 2026). В макете рамка идёт по краю
   колонки, вровень с названием. */
.km-sec {
  position: relative;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px 18px 18px;
  border: 1px dashed var(--km-warm-border);
  border-radius: 14px;
}
/* Первый и последний блок раздела — без внешних полей холста: отступ
   от рамки и от подписи задаёт сам раздел, как в макете. Между блоками
   поля остаются штатными — как в записи. */
.km-sec > .block-editor-inner-blocks > .block-editor-block-list__layout > :first-child { margin-top: 0; }
.km-sec > .block-editor-inner-blocks > .block-editor-block-list__layout > :last-child { margin-bottom: 0; }
.km-sec.is-selected { border-style: solid; border-color: var(--km-accent); box-shadow: 0 0 0 1px var(--km-accent); }
.km-sec__head { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.km-sec__label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 9px;
  border-radius: 6px;
  background: var(--km-warm-bg);
  color: #A8592F;
  font-family: var(--km-font);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .02em;
}
.km-sec__fields { display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: 10px; }
/* Поля раздела столбиком — «Шапка страницы» и «Над формой» ресурса («Ресурсы» 1.2, раздел 5). */
.km-sec__fields.km-sec__fields--stack { grid-template-columns: minmax(0, 1fr); gap: 12px; margin: 0 0 12px; }
/* Пометка под подписью раздела — кто его видит. Пока одна: у «Текста для незарегистрированных» закрытого эфира
   (08.10.2026). Шрифт свой: в холсте текст раздела — шрифтом записи, а пометка — подпись, как у панелей справа. */
.km-sec__note { margin: 0; font-family: var(--km-font); font-size: 12.5px; line-height: 1.5; color: var(--km-text-muted); }
.km-sec__parsed { display: flex; flex-direction: column; gap: 10px; }
.km-parsed__head {
  padding: 8px 14px;
  border-bottom: 1px solid var(--km-border-soft);
  background: var(--km-surface-alt);
  color: var(--km-text-secondary);
  font-size: 12.5px;
  font-weight: 700;
}

/* Поле «Начало в видео» с неверным временем — штатное поле WordPress,
   подсвеченное рамкой и подписью. */
.km-sec__field--error .components-text-control__input { border-color: var(--km-danger); }
.km-sec__field--error .components-base-control__help { color: var(--km-danger); }

/* Панели LMS справа — внутри штатной панели WordPress: заголовок её,
   поля и числа наши. */
.km-sp .components-panel__body-title + * { margin-top: 4px; }
.km-sp .km-field { margin-bottom: 13px; }
.km-sp .km-select,
.km-sp .km-input { width: 100%; max-width: none; font-size: 14px; }
/* ПАНЕЛЬ «ТРАНСЛЯЦИЯ» В ПОРЯДКЕ (снимок Алены 08.10.2026: «очень неаккуратно — и так во всех трансляциях»). Замер
   в колонке шириной 248: «Состояние» одной полосой на четыре варианта ставило «Закрытый эфир по регистрации» в 94 px —
   три строки, обрез краем, все кнопки ростом 65; поле даты выходило выше времени (49 против 40 — свой значок календаря
   Chrome) и при 15 px не вмещало «15.10.2026». Кегль полей колонки один — 14, как у списков WordPress рядом. */
.km-source--states { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.km-source--states .km-source__pick:nth-child(3) { border-right: 0; }
.km-source--states .km-source__pick:nth-child(4) { grid-column: 1 / -1; border-top: 1px solid var(--km-border); }
.km-sp .km-weditor__when { grid-template-columns: minmax(0, 1fr) 96px; }
.km-sp .km-weditor__when .km-input { height: 40px; min-height: 40px; padding: 0 10px; line-height: 38px; }
.km-sp__stat { display: flex; justify-content: space-between; gap: 10px; margin-bottom: 10px; font-size: 14px; }
.km-sp__stat span { color: var(--km-text-muted); }
.km-sp__note { margin: 0 0 12px; font-size: 12.5px; line-height: 1.5; color: var(--km-text-muted); }
/* Блок в панели «Закрытый эфир» («Впечатления об эфире»): подпись слева, переключатель справа, пометка под ними. */
.km-sp__block { display: grid; gap: 8px; margin: 0 0 14px; padding: 12px 0 0; border-top: 1px solid var(--km-border); }
.km-sp__block-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.km-sp__block-title { font-size: 13px; font-weight: 700; color: var(--km-text); }
/* РАЗДЕЛЫ ЗАКРЫТОГО ЭФИРА НА ХОЛСТЕ — поля вместо блоков (правило Алены 08.10.2026: в колонке — настройки, содержание —
   в теле). До 08.10 те же поля стояли в панели «Закрытый эфир» классами `km-sp__…`; переехали — переименованы. */
/* Поля — шрифтом панелей, а не текста записи: это форма, а не содержимое раздела. */
.km-sec__event { display: grid; gap: 10px; font-family: var(--km-font); }
.km-sec__event .km-field { margin: 0; }
/* «Что будет на эфире»: строка — ручка, номер, поле, «убрать» (05.10.2026). */
.km-sec__point { display: grid; grid-template-columns: 14px 18px minmax(0, 1fr) 32px; gap: 8px; align-items: center; margin: 0 0 8px; }
/* Пункт перетаскивается за ручку ⋮⋮ (задача Алены 05.10): строка, которую тянут, бледнеет. */
.km-sec__point-grip { font-size: 12px; letter-spacing: -2px; color: var(--km-text-muted); cursor: grab; user-select: none; }
.km-sec__point--drag { opacity: 0.45; }
.km-sec__point-n { font-family: var(--km-font); font-size: 12.5px; font-weight: 600; text-align: right; color: var(--km-text-muted); }
.km-sec__how { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); gap: 10px; }
.km-sec .km-sec__point-del { width: 32px; height: 32px; margin: 0; padding: 0; border: 1px solid var(--km-border); border-radius: var(--km-radius-badge); background: var(--km-surface); box-shadow: none; font-size: 16px; line-height: 1; color: var(--km-text-secondary); cursor: pointer; }
.km-sec .km-sec__point-del:hover { border-color: var(--km-danger); color: var(--km-danger); }
.km-sec .km-sec__add { justify-self: start; margin: 0; padding: 2px 0; border: 0; background: none; box-shadow: none; font-family: var(--km-font); font-size: 13px; font-weight: 600; color: var(--km-accent); cursor: pointer; }
/* «Адрес страницы» в редакторах курса, серии, трансляции и закрытого эфира (`assets/js/address-field.js`, 05.10.2026). */
.km-address { display: grid; gap: 6px; margin: 0 0 14px; }
.km-address__url { display: flex; flex-wrap: wrap; align-items: center; gap: 0; min-width: 0; padding: 6px 8px; border: 1px solid var(--km-border); border-radius: var(--km-radius-control); background: var(--km-surface); font-family: var(--km-mono); font-size: 12.5px; line-height: 1.4; color: var(--km-text-secondary); cursor: text; }
.km-address__url:focus-within { border-color: var(--km-accent); box-shadow: 0 0 0 2px var(--km-peach); }
.km-address__base { overflow-wrap: anywhere; }
.km-address .km-address__slug { flex: 1 1 120px; min-width: 80px; width: auto; height: auto; min-height: 0; margin: 0; padding: 2px 0; border: 0; border-radius: 0; background: transparent; box-shadow: none; font-family: var(--km-mono); font-size: 12.5px; line-height: 1.4; color: var(--km-text); }
.km-address .km-address__slug:focus { outline: none; box-shadow: none; }
.km-address__note { margin: 0; font-size: 12.5px; line-height: 1.45; color: var(--km-text); }
.km-address__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.km-address .km-address__btn { display: inline-flex; align-items: center; margin: 0; padding: 5px 10px; border: 1px solid var(--km-border); border-radius: var(--km-radius-badge); background: var(--km-surface); box-shadow: none; font-family: var(--km-font); font-size: 12.5px; font-weight: 600; line-height: 1.3; color: var(--km-text); text-decoration: none; cursor: pointer; }
.km-address .km-address__btn:hover,
.km-address .km-address__btn:focus { border-color: var(--km-accent); color: var(--km-text); }
.km-address .km-address__btn:focus-visible { outline: 2px solid var(--km-accent); outline-offset: 1px; }
/* Кнопка во всю ширину боковой колонки — ссылкой `<a>`, и админка
   WordPress подчёркивает ссылки общим правилом. Кегль и поля — как
   у кнопки в макете `admin-series-v2`: колонка WordPress 280 px, а не 340,
   и с полями дизайн-системы подпись переносилась на две строки. */
.km-sp__wide,
.km-sp__wide:hover,
.km-sp__wide:focus,
.km-sp__wide:active { width: 100%; justify-content: center; margin-bottom: 12px; padding: 12px 14px; font-size: 14px; text-align: center; text-decoration: none; }
.km-sp__link { font-size: 14px; font-weight: 600; color: var(--km-accent); text-decoration: none; }

/* Карточка серии в списке админки (v2): обложка слева, текст справа —
   само правило карточки выше, здесь только новые части. */
.km-series__cover {
  flex: none;
  width: 96px;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: 8px;
  background: var(--km-track);
}
.km-series__image { display: block; width: 100%; height: 100%; object-fit: cover; }
.km-series__txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }

/* Плитки серий над лентой (v2): четыре в ряд, на узком — лентой вбок. */
.km-lib-series { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; margin-top: 20px; }
.km-lib-tile {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-card);
  box-shadow: var(--km-shadow-card);
  color: var(--km-text);
  text-decoration: none;
}
.km-lib-tile:hover { border-color: var(--km-warm-border); color: var(--km-text); }
.km-lib-tile__cover { display: block; aspect-ratio: 16 / 9; background: var(--km-track); }
.km-lib-tile__image { display: block; width: 100%; height: 100%; object-fit: cover; }
.km-lib-tile__txt { display: flex; flex-direction: column; gap: 2px; padding: 12px 14px 14px; }
.km-lib-tile__name { font-family: var(--km-font-display); font-size: 16px; font-weight: 700; overflow-wrap: anywhere; }
.km-lib-tile__line { font-size: 13px; color: var(--km-text-muted); }

/* Строка записи: название — ссылкой на всю строку, серия — своей ссылкой
   поверх (ссылку в ссылке браузер разрывает). */
.km-feed__title::after { content: ''; position: absolute; inset: 0; }
.km-feed__where a {
  position: relative;
  z-index: 1;
  color: var(--km-text-muted);
  text-decoration: underline;
  text-decoration-color: var(--km-border);
  text-underline-offset: 3px;
}
.km-feed__where a:hover { color: var(--km-accent); }

/* Страница серии у клиента. */
.km-ser-head { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, .9fr); gap: 32px; align-items: start; margin-top: 4px; }
.km-ser-head__main { min-width: 0; }
.km-ser-head__kicker { font-size: 14px; font-weight: 600; color: #A8592F; }
.km-ser-head__title { margin: 6px 0 0; font-family: var(--km-font-display); font-size: 34px; font-weight: 700; line-height: 1.2; overflow-wrap: anywhere; }
.km-ser-head__about { max-width: 62ch; margin-top: 14px; font-size: 16px; line-height: 1.75; }
.km-ser-head__about p { margin: 0; }
.km-ser-head__about p + p { margin-top: 12px; }
.km-ser-head__meta { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 16px; font-size: 13.5px; color: var(--km-text-muted); }
.km-ser-cover { overflow: hidden; aspect-ratio: 16 / 9; border-radius: 12px; background: var(--km-track); }
.km-ser-cover__image { display: block; width: 100%; height: 100%; object-fit: cover; }
.km-lib-next--one { grid-template-columns: 1fr; }

@media (max-width: 980px) {
  .km-sec__fields { grid-template-columns: 1fr; }
}
@media (max-width: 900px) {
  .km-lib-series { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 860px) {
  .km-ser-head { grid-template-columns: 1fr; }
  .km-ser-cover { order: -1; }
}
@media (max-width: 600px) {
  .km-ser-head__title { font-size: 26px; }
}
@media (max-width: 560px) {
  .km-lib-series { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; margin-right: -16px; padding-right: 16px; }
  .km-lib-tile { flex: 0 0 72%; scroll-snap-align: start; }
}

/* ── Библиотека клиента: блоки для страниц Elementor ─────────────────────
 *
 * «Новое в библиотеке», «Записи серии», «Избранное» — `[lms_library_latest]`,
 * `[lms_library_series]`, `[lms_library_favorites]` (4.16, «Темы, подпись
 * в карточке и три блока для страниц Elementor»). Прототип Алены
 * `design/library-prototype/`: `index.html` (`.feature`), `workshop/index.html`
 * (`.section`, `.toolbar`, `.card-grid`, `.record-card`, `.more-row`),
 * `favorites/index.html` (`.empty`). Значения — его `style.css` вместе со второй
 * таблицей «Reading sizes», которая перебивает первую; переломы — его же.
 *
 * СНАРУЖИ У БЛОКА НЕТ СВОИХ ОТСТУПОВ. Внешняя обёртка: `margin` и `padding` 0,
 * ширина 100% колонки, без наибольшей ширины и без центрирования, фон
 * прозрачный — отступы вокруг блока ставит Алена в Elementor. Крайние дети
 * обёртки без внешних полей: иначе поле ребёнка прошло бы сквозь обёртку
 * и стало бы отступом блока.
 *
 * ТЕМА И ELEMENTOR НЕ РЕШАЮТ НИЧЕГО. Обёртка — `div.km-lb[data-lms-lb]`
 * (0,2,1): сильнее правил темы вида `.entry-content > div`. Каждый элемент —
 * классом под `.km-lb` (0,2,0), с именем элемента (0,2,1), состояния — (0,3,1):
 * правила кнопок и ссылок в состояниях у тем и наборов Elementor весят
 * (0,2,1) (`.elementor-kit-N button:hover`). Силой, а не порядком таблиц
 * (урок `.site`, 17 сентября 2026).
 */

div.km-lb[data-lms-lb] {
  --km-lb-ink: #33315e;
  --km-lb-body: #51495f;
  --km-lb-red: #d54844;
  --km-lb-red-hover: #ad3533;
  --km-lb-line: #e7dfeb;
  --km-lb-focus: #9b7fb0;
  display: block;
  box-sizing: border-box;
  width: 100%;
  max-width: none;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  box-shadow: none;
  float: none;
  font-family: 'KM Manrope', Arial, sans-serif;
  font-size: 16px;
  font-weight: 400;
  line-height: 1.65;
  letter-spacing: normal;
  text-align: left;
  color: var(--km-lb-body);
}
.km-lb *,
.km-lb *::before,
.km-lb *::after { box-sizing: border-box; }
div.km-lb[data-lms-lb] > :first-child { margin-top: 0; }
div.km-lb[data-lms-lb] > :last-child { margin-bottom: 0; }

/* Спрятанное — спрятано: `display` классов ниже перебил бы `[hidden]`. */
.km-lb .km-lb-card[hidden],
.km-lb .km-lb-empty[hidden],
.km-lb .km-lb-more[hidden],
.km-lb .km-lb-grid[hidden] { display: none; }

/* Значок прототипа (`svg` его таблицы). */
.km-lb svg.km-lb-i {
  display: inline;
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  stroke-width: 1.7;
  vertical-align: middle;
  fill: none;
}

/* Ссылки и кнопки — во всех состояниях; признак фокуса с клавиатуры —
   прототипа, тема его гасит. */
.km-lb a:is(.km-lb-primary, .km-lb-secondary, .km-lb-quiet, .km-lb-card__action, .km-lb-card__link, .km-lb-card__image, .km-lb-feature__visual),
.km-lb button:is(.km-lb-primary, .km-lb-secondary, .km-lb-chip, .km-lb-save) {
  transition: color .18s, background .18s, box-shadow .18s, transform .18s;
  -webkit-tap-highlight-color: transparent;
  outline: 0;
  text-transform: none;
  letter-spacing: normal;
}
.km-lb a:is(.km-lb-primary, .km-lb-secondary, .km-lb-quiet, .km-lb-card__action, .km-lb-card__link, .km-lb-card__image, .km-lb-feature__visual):focus-visible,
.km-lb button:is(.km-lb-primary, .km-lb-secondary, .km-lb-chip, .km-lb-save):focus-visible { outline: 3px solid var(--km-lb-focus); outline-offset: 4px; }

/* ── Надстрочник и плашка (`.eyebrow`, `.badge`) ── */
.km-lb .km-lb-eyebrow {
  margin: 0 0 9px;
  font-size: 11px;
  font-weight: 800;
  line-height: 1.65;
  letter-spacing: 1.8px;
  text-transform: uppercase;
  color: #9a7dab;
}
.km-lb .km-lb-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin: 0;
  padding: 5px 8px;
  border-radius: 5px;
  background: #efe7f5;
  font-family: 'KM Manrope', Arial, sans-serif;
  font-size: 11px;
  font-weight: 750;
  line-height: 1.4;
  letter-spacing: normal;
  text-transform: none;
  color: #88639c;
}
.km-lb .km-lb-badge svg.km-lb-i { width: 12px; height: 12px; }
.km-lb .km-lb-badge--white { background: #ffffffeb; color: #705382; }

/* ── Кнопки (`.primary`, `.secondary`) ── */
.km-lb :is(a, button):is(.km-lb-primary, .km-lb-secondary) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  min-height: 44px;
  margin: 0;
  padding: 11px 17px;
  border-radius: 8px;
  font-family: 'KM Manrope', Arial, sans-serif;
  font-size: 14px;
  font-weight: 700;
  line-height: 1.5;
  text-decoration: none;
  cursor: pointer;
}
.km-lb :is(a, button):is(.km-lb-primary, .km-lb-secondary) svg.km-lb-i { width: 17px; }
.km-lb a.km-lb-primary,
.km-lb a.km-lb-primary:link,
.km-lb a.km-lb-primary:visited,
.km-lb a.km-lb-primary:focus,
.km-lb a.km-lb-primary:active {
  border: 0;
  background: var(--km-lb-red);
  box-shadow: 0 3px 7px #d5484418;
  color: #fff;
  text-decoration: none;
}
.km-lb a.km-lb-primary:hover { border: 0; background: #bd3e3a; box-shadow: 0 3px 7px #d5484418; color: #fff; text-decoration: none; }
.km-lb :is(a, button).km-lb-secondary,
.km-lb :is(a, button).km-lb-secondary:link,
.km-lb :is(a, button).km-lb-secondary:visited,
.km-lb :is(a, button).km-lb-secondary:focus,
.km-lb :is(a, button).km-lb-secondary:active {
  border: 1px solid #dfd0e7;
  background: #fff;
  box-shadow: none;
  color: #856595;
  text-decoration: none;
}
.km-lb :is(a, button).km-lb-secondary:hover {
  border: 1px solid #dfd0e7;
  background: #f4edf8;
  box-shadow: none;
  color: #6b477f;
  text-decoration: none;
}

/* Тихая ссылка (`.quiet-link`, внутри `.actions` — 13 px). Ссылки прототипа
   подчёркнуты: `a` у него без `text-decoration: none`. */
.km-lb .km-lb-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
}
.km-lb a.km-lb-quiet,
.km-lb a.km-lb-quiet:link,
.km-lb a.km-lb-quiet:visited,
.km-lb a.km-lb-quiet:focus,
.km-lb a.km-lb-quiet:active {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  box-shadow: none;
  font-size: 13px;
  font-weight: 400;
  line-height: 1.65;
  white-space: nowrap;
  color: var(--km-lb-red);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
}
.km-lb a.km-lb-quiet:hover { background: transparent; color: var(--km-lb-red-hover); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; }

/* Значок воспроизведения (`.play`, `.play.small`). */
.km-lb .km-lb-play {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  border-radius: 50%;
  background: #ffffffed;
  box-shadow: 0 4px 24px #36304d17;
  color: #826194;
  transform: translate(-50%, -50%);
}
.km-lb .km-lb-play svg.km-lb-i { width: 22px; height: 22px; margin-left: 3px; fill: currentColor; stroke-width: 0; }
.km-lb .km-lb-play--small { width: 39px; height: 39px; }
.km-lb .km-lb-play--small svg.km-lb-i { width: 16px; }

/* ── «Новое в библиотеке» (`.feature`) ── */
.km-lb .km-lb-feature {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.18fr) minmax(250px, 1fr);
  min-height: 270px;
  margin: 0;
  background: #fff;
  border: 1px solid var(--km-lb-line);
  border-radius: 15px;
  box-shadow: 0 5px 20px #44255006;
  overflow: hidden;
}
.km-lb .km-lb-feature__copy { position: relative; z-index: 1; padding: 29px 31px; }
.km-lb h2.km-lb-feature__title {
  max-width: 400px;
  margin: 12px 0;
  padding: 0;
  font-family: 'KM Oswald', Arial, sans-serif;
  font-size: 31px;
  font-weight: 500;
  line-height: 1.28;
  letter-spacing: normal;
  text-transform: none;
  color: var(--km-lb-ink);
}
.km-lb p.km-lb-feature__text {
  max-width: 390px;
  margin: 0 0 22px;
  padding: 0;
  font-size: 16px;
  line-height: 1.7;
  color: #82708e;
}
.km-lb a.km-lb-feature__visual,
.km-lb a.km-lb-feature__visual:hover,
.km-lb a.km-lb-feature__visual:focus,
.km-lb a.km-lb-feature__visual:active {
  position: relative;
  display: block;
  min-height: 240px;
  margin: 14px 14px 14px 0;
  padding: 0;
  border: 0;
  border-radius: 11px;
  background: #eee5f3;
  box-shadow: none;
  overflow: hidden;
  text-decoration: none;
}
.km-lb a.km-lb-feature__visual::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(0deg, #33315e2b, transparent 55%);
}
.km-lb img.km-lb-feature__img {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  max-width: 100%;
  margin: 0;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  object-fit: cover;
  object-position: center;
}
.km-lb .km-lb-feature__caption {
  position: absolute;
  right: 15px;
  bottom: 16px;
  left: 20px;
  z-index: 1;
  font-size: 12px;
  line-height: 1.65;
  letter-spacing: .4px;
  text-transform: uppercase;
  color: #fff;
}

/* ── «Записи серии»: заголовок раздела, отбор, поиск ── */
.km-lb .km-lb-heading {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  margin: 0 0 17px;
}
.km-lb h2.km-lb-heading__title {
  margin: 0;
  padding: 0;
  font-family: 'KM Oswald', Arial, sans-serif;
  font-size: 24px;
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: normal;
  text-transform: uppercase;
  color: var(--km-lb-ink);
}
.km-lb .km-lb-heading__note { font-size: 12px; line-height: 1.65; color: #a28dad; }
.km-lb .km-lb-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  margin: 29px 0 23px;
  padding: 0 0 17px;
  border-bottom: 1px solid var(--km-lb-line);
}
.km-lb .km-lb-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.km-lb button.km-lb-chip,
.km-lb button.km-lb-chip:focus,
.km-lb button.km-lb-chip:active {
  margin: 0;
  padding: 8px 12px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  box-shadow: none;
  font-family: 'KM Manrope', Arial, sans-serif;
  font-size: 14px;
  font-weight: 650;
  line-height: 1.65;
  color: #937d9f;
  cursor: pointer;
}
.km-lb button.km-lb-chip[aria-pressed="true"] { background: #e9ddf0; color: #725182; }
.km-lb button.km-lb-chip:hover { border: 0; background: #eee5f4; box-shadow: none; color: #937d9f; }
.km-lb button.km-lb-chip[aria-pressed="true"]:hover { color: #725182; }
.km-lb label.km-lb-search {
  display: flex;
  align-items: center;
  gap: 9px;
  /* Вдвое шире прототипа — Алена 28.09.2026: «как будто у тебя места нет». */
  width: 470px;
  max-width: 100%;
  min-width: 205px;
  min-height: 44px;
  margin: 0;
  padding: 10px 12px;
  border: 1px solid var(--km-lb-line);
  border-radius: 8px;
  background: #fff;
  font-size: 16px;
  font-weight: 400;
  line-height: 1.65;
  color: #8d759b;
}
.km-lb label.km-lb-search:focus-within { border-color: #ae91c0; box-shadow: 0 0 0 2px #dccbe766; }
.km-lb .km-lb-search svg.km-lb-i { width: 17px; }
.km-lb .km-lb-search input.km-lb-search__input,
.km-lb .km-lb-search input.km-lb-search__input:hover,
.km-lb .km-lb-search input.km-lb-search__input:focus,
.km-lb .km-lb-search input.km-lb-search__input:focus-visible {
  width: 100%;
  min-width: 0;
  height: auto;
  min-height: auto;
  margin: 0;
  /* Отступ поля — браузерный, как у прототипа: тема его обнуляет или раздувает. */
  padding: 1px 2px;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  outline: 0;
  font-family: 'KM Manrope', Arial, sans-serif;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.65;
  color: var(--km-lb-body);
}
.km-lb .km-lb-search input.km-lb-search__input::placeholder { color: #aa98b4; opacity: 1; }

/* ── Сетка и карточка записи (`.card-grid`, `.record-card`) ──
 *
 * КОЛОНКИ РЕШАЕТ ШИРИНА САМОЙ СЕТКИ, А НЕ ЭКРАНА (задача Алены 30.09.2026).
 * Блок стоит где угодно: во всю страницу серии, в колонке кабинета рядом
 * с его меню, в узкой колонке Elementor. По ширине экрана в кабинете на
 * планшете выходили три узкие полоски. Теперь колонок столько, сколько
 * помещается карточек не уже `--km-lb-card-min`, и не больше трёх:
 * `max( минимум, треть )` — треть не даёт четвёртой колонки, `min( 100%, … )` —
 * одной колонке не вылезти за край. `auto-fill`, а не `auto-fit`: одна
 * карточка остаётся шириной колонки, а не растягивается на весь блок.
 *
 * 250 px — замер 30.09 по карточке прототипа (Oswald 23 px, поля 20 px):
 * при 250 шесть типичных названий боевого («Сеть Света и Любви, сентябрь 2026»,
 * «Практическое занятие - 6, 2.07.2026»…) встают в две строки, при 240 одно
 * уходит на третью; низ карточки помещается при любой. Spec 4.16.
 */
.km-lb .km-lb-grid {
  --km-lb-card-min: 250px;
  --km-lb-gap: 21px;
  container: km-lb-grid / inline-size;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, max(var(--km-lb-card-min), (100% - 2 * var(--km-lb-gap)) / 3)), 1fr));
  align-items: stretch;
  gap: var(--km-lb-gap);
  margin: 0;
}
.km-lb .km-lb-card {
  position: relative;
  display: flex;
  flex-direction: column;
  margin: 0;
  background: #fff;
  border: 1px solid var(--km-lb-line);
  border-radius: 15px;
  box-shadow: 0 5px 20px #44255006;
  overflow: hidden;
}
.km-lb :is(a, span).km-lb-card__image,
.km-lb a.km-lb-card__image:hover,
.km-lb a.km-lb-card__image:focus,
.km-lb a.km-lb-card__image:active {
  position: relative;
  display: block;
  aspect-ratio: 1.85;
  margin: 10px 10px 0;
  padding: 0;
  border: 0;
  border-radius: 9px;
  background: #eee5f3;
  box-shadow: none;
  overflow: hidden;
  text-decoration: none;
}
.km-lb img.km-lb-card__img {
  display: block;
  width: 100%;
  height: 100%;
  max-width: 100%;
  margin: 0;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  object-fit: cover;
  transition: transform .3s;
}
/* Под курсором картинка не растёт — правило Алены «под курсором ничего не двигается». */
.km-lb .km-lb-card__image .km-lb-badge { position: absolute; top: 10px; left: 10px; }
/*
 * «✓ Пройдено» — справа сверху на обложке, цветом «пройдено» дизайн-системы,
 * а не бирюзой старой карточки «Библиотека — Плитка» (задача Алены 4 октября
 * 2026). Плашку месяца слева перебивает силой селектора, а не порядком:
 * (0,4,0) против (0,3,0) — и у широкой, и у узкой.
 */
.km-lb .km-lb-badge.km-lb-badge--done { background: var(--km-done-bg); color: var(--km-done); }
.km-lb .km-lb-card__image .km-lb-badge.km-lb-badge--done { right: 10px; left: auto; }
.km-lb .km-lb-feature__visual .km-lb-badge.km-lb-badge--done { position: absolute; top: 14px; right: 14px; z-index: 1; }
.km-lb .km-lb-card__copy {
  display: flex;
  flex: 1;
  flex-direction: column;
  padding: 17px 20px 18px;
}
.km-lb .km-lb-card__date {
  display: block;
  margin: 0 0 7px;
  font-size: 13px;
  line-height: 1.65;
  color: #a28aac;
}
.km-lb a.km-lb-card__link,
.km-lb a.km-lb-card__link:hover,
.km-lb a.km-lb-card__link:focus,
.km-lb a.km-lb-card__link:active {
  display: block;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  box-shadow: none;
  text-decoration: none;
}
.km-lb h3.km-lb-card__title {
  margin: 0 0 10px;
  padding: 0;
  font-family: 'KM Oswald', Arial, sans-serif;
  font-size: 23px;
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: normal;
  text-transform: none;
  overflow-wrap: break-word;
  color: #54405f;
}
.km-lb p.km-lb-card__text {
  margin: 0;
  padding: 0;
  font-size: 14px;
  line-height: 1.7;
  color: #82708e;
}
/* «Внутри: {практика}» — «Последние записи» кабинета, цветом нынешнего кабинета (30.09.2026). */
.km-lb p.km-lb-card__inside {
  margin: 0 0 8px;
  padding: 0;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.5;
  overflow-wrap: break-word;
  color: var(--km-accent);
}
.km-lb .km-lb-card__bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: auto;
  padding-top: 17px;
}
.km-lb :is(a, span).km-lb-card__action,
.km-lb a.km-lb-card__action:link,
.km-lb a.km-lb-card__action:visited,
.km-lb a.km-lb-card__action:focus,
.km-lb a.km-lb-card__action:active {
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  box-shadow: none;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.65;
  color: var(--km-lb-red);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
}
.km-lb a.km-lb-card__action:hover { background: transparent; color: var(--km-lb-red-hover); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; }
.km-lb .km-lb-lock { display: inline-flex; color: var(--km-lb-body); }

/* Сердечко (`.save-btn`): 33 px прототипа и его `min-width: 36px`. */
.km-lb button.km-lb-save,
.km-lb button.km-lb-save:hover,
.km-lb button.km-lb-save:focus,
.km-lb button.km-lb-save:active {
  display: grid;
  place-items: center;
  width: 33px;
  height: 33px;
  min-width: 36px;
  min-height: 36px;
  margin: 0;
  /* Отступ и шрифт кнопки — браузерные, как у прототипа (`font: inherit`). */
  padding: 1px 6px;
  border: 0;
  border-radius: 50%;
  background: #f7f2fa;
  box-shadow: none;
  font: inherit;
  color: #a589b5;
  cursor: pointer;
}
.km-lb button.km-lb-save[aria-pressed="true"],
.km-lb button.km-lb-save[aria-pressed="true"]:hover,
.km-lb button.km-lb-save[aria-pressed="true"]:focus,
.km-lb button.km-lb-save[aria-pressed="true"]:active { background: #eee1f3; color: #805492; }
.km-lb button.km-lb-save:disabled { cursor: default; }
.km-lb .km-lb-save svg.km-lb-i { width: 16px; height: 16px; }
/* «❤ N» — сколько людей держат запись в избранном, рядом с сердечком (4 октября 2026). */
.km-lb .km-lb-likes { display: inline-flex; align-items: center; gap: 6px; }
.km-lb .km-lb-actions .km-lb-likes { margin-left: auto; }
.km-lb .km-lb-likes__count {
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  color: #a589b5;
  font-variant-numeric: tabular-nums;
}
.km-lb .km-lb-save[aria-pressed="true"] svg.km-lb-i { fill: #805492; }

/* «Показать более ранние встречи» (`.more-row`). */
.km-lb .km-lb-more { margin: 26px 0 0; text-align: center; }

/* Пусто (`.empty`): «Записи не найдены» и «Здесь будут ваши записи». */
.km-lb .km-lb-empty {
  grid-column: 1 / -1;
  margin: 0;
  padding: 55px 20px;
  border: 1px dashed #d9c9e3;
  border-radius: 13px;
  background: #fff;
  text-align: center;
  color: #826c90;
}
.km-lb .km-lb-empty svg.km-lb-i { width: 28px; height: 28px; margin-bottom: 12px; }
/* Стрелка в кнопке пустого «Избранного» — тоже 28 px с полем 12 снизу: у прототипа
   `.empty svg` стоит в таблице позже `.secondary svg` и перебивает его (кнопка 64 px). */
.km-lb .km-lb-empty :is(a, button).km-lb-secondary svg.km-lb-i { width: 28px; height: 28px; margin-bottom: 12px; }
.km-lb h3.km-lb-empty__title {
  margin: 0 0 9px;
  padding: 0;
  font-family: 'KM Oswald', Arial, sans-serif;
  font-size: 24px;
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: normal;
  text-transform: none;
  color: var(--km-lb-ink);
}
.km-lb p.km-lb-empty__text { margin: 0 0 18px; padding: 0; font-size: 14px; line-height: 1.65; color: #826c90; }

/* Всплывающая строка (`#toast`) — в конце `<body>`, вне обёрток. */
.km-lb-toast {
  position: fixed;
  bottom: 26px;
  left: 50%;
  z-index: 100000;
  width: max-content;
  max-width: calc(100% - 30px);
  padding: 12px 20px;
  border-radius: 10px;
  background: #4c385d;
  box-shadow: 0 7px 30px #3327442b;
  font-family: 'KM Manrope', Arial, sans-serif;
  font-size: 14px;
  line-height: 1.65;
  color: #fff;
  opacity: 0;
  pointer-events: none;
  transform: translate(-50%, 20px);
  transition: opacity .2s, transform .2s;
}
.km-lb-toast.km-lb-toast--on { opacity: 1; transform: translate(-50%, 0); }

@media (min-width: 1600px) {
  .km-lb .km-lb-feature { min-height: 284px; }
}
@media (max-width: 1250px) {
  .km-lb .km-lb-feature { grid-template-columns: 1.15fr 1fr; }
  .km-lb .km-lb-feature__copy { padding: 24px; }
  .km-lb h2.km-lb-feature__title { font-size: 28px; }
  .km-lb .km-lb-grid { --km-lb-gap: 16px; }
  .km-lb .km-lb-card__copy { padding: 17px; }
  .km-lb .km-lb-toolbar { flex-wrap: wrap; }
  .km-lb .km-lb-chips { flex: 1; }
  .km-lb label.km-lb-search { width: 420px; min-width: 170px; }
}
@media (max-width: 1000px) {
  .km-lb .km-lb-feature { min-height: 260px; }
  .km-lb h2.km-lb-feature__title { font-size: 29px; }
}
@media (max-width: 700px) {
  .km-lb .km-lb-feature { display: flex; flex-direction: column-reverse; }
  .km-lb a.km-lb-feature__visual,
  .km-lb a.km-lb-feature__visual:hover,
  .km-lb a.km-lb-feature__visual:focus,
  .km-lb a.km-lb-feature__visual:active { min-height: 0; height: auto; margin: 11px 11px 0; aspect-ratio: 2.05; }
  .km-lb .km-lb-feature__copy { padding: 21px 23px 24px; }
  .km-lb h2.km-lb-feature__title { max-width: 340px; margin: 11px 0; font-size: 28px; }
  .km-lb p.km-lb-feature__text { margin-bottom: 18px; font-size: 15px; }
  .km-lb .km-lb-feature__copy .km-lb-eyebrow { font-size: 10px; }
  .km-lb .km-lb-feature__copy a.km-lb-primary { font-size: 13px; }
  .km-lb .km-lb-feature__caption { bottom: 12px; left: 15px; font-size: 11px; }
  .km-lb .km-lb-heading { margin-bottom: 15px; }
  .km-lb h2.km-lb-heading__title { font-size: 23px; }
  .km-lb .km-lb-heading__note { display: none; }
  .km-lb .km-lb-grid { --km-lb-gap: 13px; }
  .km-lb .km-lb-toolbar { gap: 13px; margin: 22px 0 18px; }
  .km-lb .km-lb-chips { flex-basis: 100%; gap: 4px; }
  .km-lb button.km-lb-chip,
  .km-lb button.km-lb-chip:focus,
  .km-lb button.km-lb-chip:active { padding: 8px 10px; font-size: 13px; }
  .km-lb label.km-lb-search { width: 100%; }
  .km-lb .km-lb-card__copy { padding: 14px; }
  .km-lb .km-lb-card__date { margin-bottom: 6px; }
  .km-lb p.km-lb-card__text { font-size: 13px; }
  .km-lb p.km-lb-card__inside { margin-bottom: 6px; font-size: 13px; }
  .km-lb :is(a, span).km-lb-card__image,
  .km-lb a.km-lb-card__image:hover,
  .km-lb a.km-lb-card__image:focus,
  .km-lb a.km-lb-card__image:active { margin: 8px 8px 0; aspect-ratio: 1.5; }
  .km-lb .km-lb-card__image .km-lb-badge { top: 7px; left: 7px; padding: 4px 6px; font-size: 10px; }
  .km-lb .km-lb-card__image .km-lb-badge.km-lb-badge--done { right: 7px; left: auto; }
  .km-lb .km-lb-card__image .km-lb-play { width: 32px; height: 32px; }
  .km-lb .km-lb-card__bottom { padding-top: 10px; }
  .km-lb :is(a, span).km-lb-card__action,
  .km-lb a.km-lb-card__action:link,
  .km-lb a.km-lb-card__action:visited,
  .km-lb a.km-lb-card__action:focus,
  .km-lb a.km-lb-card__action:active,
  .km-lb a.km-lb-card__action:hover { font-size: 13px; }
  .km-lb-toast { bottom: 83px; font-size: 12px; }
}
/*
 * На одну вертикальную карточку места нет — горизонтальная, как была на
 * телефоне: картинка слева, текст справа. Решает ширина сетки (`@container`),
 * а не экрана: на телефоне сетка шире минимума, и карточка вертикальная
 * (вопрос 1 спецификации 4.17 — «картинка полосой слева», — закрыт этим).
 * Уже минимума картинке 130 px не хватило бы места на текст: она берёт
 * не больше двух пятых, название — мельче и с переносами по слогам,
 * а не по буквам.
 */
@container km-lb-grid (max-width: 249.98px) {
  .km-lb .km-lb-card { display: grid; grid-template-columns: min(130px, 40%) minmax(0, 1fr); }
  .km-lb :is(a, span).km-lb-card__image,
  .km-lb a.km-lb-card__image:hover,
  .km-lb a.km-lb-card__image:focus,
  .km-lb a.km-lb-card__image:active { height: calc(100% - 16px); margin: 8px 0 8px 8px; aspect-ratio: auto; }
  .km-lb .km-lb-card__copy { padding: 12px; }
  .km-lb h3.km-lb-card__title { font-size: 18px; hyphens: auto; }
}
@media (prefers-reduced-motion: reduce) {
  .km-lb a:is(.km-lb-primary, .km-lb-secondary, .km-lb-quiet, .km-lb-card__action, .km-lb-card__link, .km-lb-card__image, .km-lb-feature__visual),
  .km-lb button:is(.km-lb-primary, .km-lb-secondary, .km-lb-chip, .km-lb-save),
  .km-lb img.km-lb-card__img,
  .km-lb-toast { transition: none; }
}

/* ── Библиотека клиента: главная, серия, «Избранное» — страницы кодом ───────
 *
 * Прототип Алены `design/library-prototype/` (`index.html`, `workshop/index.html`,
 * `light/index.html`, `favorites/index.html`) без шапки сайта, левой колонки,
 * нижнего меню и подвала (4.16, «Библиотека для клиента кодом», 27 сентября
 * 2026). Рамка — страницы трансляции (`.km-page.km-cast`: шрифты, фон, крошки),
 * ширина — основной колонки прототипа, 1164. Значения — его `style.css` вместе
 * со второй таблицей «Reading sizes». Силой селектора, не порядком таблиц.
 *
 * Два отличия — по правилам Алены, а не по недосмотру: карточки под курсором
 * не приподнимаются (только цвет и тень: «под курсором ничего не двигается»),
 * и красной выделена только «В прямом эфире», а не первая ссылка по порядку.
 */

.km-page.km-cast.km-lb-page { max-width: 1164px; }

/* Спрятанное отбором главной — спрятано: `display` классов перебил бы `[hidden]`. */
.km-lb [data-lms-lb-item][hidden],
.km-lb .km-lb-section[hidden] { display: none; }

/* Заголовок страницы (`h1`) и подзаголовок (`.page-subtitle`). `!important` —
   только против `!important` сниппета сайта у `h1`, как у страницы трансляции. */
.km-lb h1.km-lb-title {
  margin: 0;
  padding: 0 !important;
  font-family: 'KM Oswald', Arial, sans-serif;
  font-size: 38px;
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: -.4px;
  text-transform: uppercase;
  color: var(--km-lb-ink);
}
.km-lb p.km-lb-subtitle {
  max-width: 710px;
  margin: 10px 0 24px;
  padding: 0;
  font-size: 16px;
  line-height: 1.7;
  color: #8a7896;
}

/* Быстрые ссылки (`.quick-links`). */
.km-lb .km-lb-quick { display: flex; flex-wrap: wrap; gap: 8px; margin: 20px 0 27px; }
.km-lb a.km-lb-quick__link,
.km-lb a.km-lb-quick__link:link,
.km-lb a.km-lb-quick__link:visited,
.km-lb a.km-lb-quick__link:focus,
.km-lb a.km-lb-quick__link:active {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 43px;
  margin: 0;
  padding: 10px 13px;
  border: 1px solid var(--km-lb-line);
  border-radius: 9px;
  background: #fff;
  box-shadow: none;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.65;
  color: #80658e;
  text-decoration: none;
}
.km-lb a.km-lb-quick__link:hover { border-color: #cdb9da; background: #f2eaf7; color: #694b7b; text-decoration: none; }
.km-lb a.km-lb-quick__link--live,
.km-lb a.km-lb-quick__link--live:link,
.km-lb a.km-lb-quick__link--live:visited,
.km-lb a.km-lb-quick__link--live:hover,
.km-lb a.km-lb-quick__link--live:focus,
.km-lb a.km-lb-quick__link--live:active { border-color: #edcccf; background: #fcf0f0; color: var(--km-lb-red); }
.km-lb .km-lb-quick svg.km-lb-i { width: 17px; height: 17px; }
.km-lb a.km-lb-quick__link:focus-visible { outline: 3px solid var(--km-lb-focus); outline-offset: 4px; }

/* Плашка эфира (`.badge.red`). */
.km-lb .km-lb-badge--live { background: #fae9e9; color: #bc5659; }

/* Раздел страницы (`.section`). */
.km-lb .km-lb-section { margin: 33px 0 0; }
.km-lb .km-lb-heading a.km-lb-quiet,
.km-lb .km-lb-heading a.km-lb-quiet:link,
.km-lb .km-lb-heading a.km-lb-quiet:visited,
.km-lb .km-lb-heading a.km-lb-quiet:focus,
.km-lb .km-lb-heading a.km-lb-quiet:active,
.km-lb .km-lb-heading a.km-lb-quiet:hover { font-size: 14px; }

/* Плитка серии (`.category-card`). */
.km-lb a.km-lb-tile,
.km-lb a.km-lb-tile:link,
.km-lb a.km-lb-tile:visited,
.km-lb a.km-lb-tile:focus,
.km-lb a.km-lb-tile:active {
  display: flex;
  flex-direction: column;
  margin: 0;
  background: #fff;
  border: 1px solid var(--km-lb-line);
  border-radius: 15px;
  box-shadow: 0 5px 20px #44255006;
  overflow: hidden;
  color: inherit;
  text-decoration: none;
  transition: box-shadow .2s;
}
.km-lb a.km-lb-tile:hover { box-shadow: 0 9px 24px #5b367515; color: inherit; text-decoration: none; }
.km-lb a.km-lb-tile:focus-visible { outline: 3px solid var(--km-lb-focus); outline-offset: 4px; }
.km-lb .km-lb-tile__image {
  position: relative;
  display: block;
  aspect-ratio: 1.8;
  margin: 11px 11px 0;
  border-radius: 9px;
  overflow: hidden;
  background: #eee7f3;
}
.km-lb img.km-lb-tile__img { display: block; width: 100%; height: 100%; max-width: 100%; margin: 0; border: 0; border-radius: 0; box-shadow: none; object-fit: cover; }
.km-lb .km-lb-tile__copy { display: flex; flex: 1; flex-direction: column; padding: 18px 20px 21px; }
.km-lb h3.km-lb-tile__title {
  margin: 0 0 8px;
  padding: 0;
  font-family: 'KM Oswald', Arial, sans-serif;
  font-size: 23px;
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: normal;
  text-transform: none;
  overflow-wrap: break-word;
  color: #4a3858;
}
.km-lb p.km-lb-tile__text { flex: 1; margin: 0; padding: 0; font-size: 15px; line-height: 1.7; color: #80708c; }
.km-lb .km-lb-tile__bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 17px;
  font-size: 14px;
  line-height: 1.65;
  color: #9472a5;
}
.km-lb .km-lb-tile__open { color: var(--km-lb-red); text-decoration: underline; text-underline-offset: 4px; text-decoration-thickness: 1px; }
.km-lb .km-lb-tile__bottom svg.km-lb-i { width: 16px; }

/* Карточка группы (`.compact-card`). */
.km-lb .km-lb-compacts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 15px; }
.km-lb a.km-lb-compact,
.km-lb a.km-lb-compact:link,
.km-lb a.km-lb-compact:visited,
.km-lb a.km-lb-compact:focus,
.km-lb a.km-lb-compact:active {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  margin: 0;
  padding: 13px;
  background: #fff;
  border: 1px solid var(--km-lb-line);
  border-radius: 15px;
  box-shadow: 0 5px 20px #44255006;
  overflow: hidden;
  color: inherit;
  text-decoration: none;
}
.km-lb a.km-lb-compact:hover { border-color: #cdb9d8; color: inherit; text-decoration: none; }
.km-lb a.km-lb-compact:focus-visible { outline: 3px solid var(--km-lb-focus); outline-offset: 4px; }
.km-lb img.km-lb-compact__img { display: block; flex-shrink: 0; width: 77px; height: 98px; max-width: none; margin: 0; border: 0; border-radius: 7px; box-shadow: none; object-fit: cover; }
.km-lb .km-lb-compact__copy { display: block; min-width: 0; }
.km-lb h3.km-lb-compact__title {
  margin: 0 0 5px;
  padding: 0;
  font-family: 'KM Oswald', Arial, sans-serif;
  font-size: 22px;
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: normal;
  text-transform: none;
  color: var(--km-lb-ink);
}
.km-lb p.km-lb-compact__text { margin: 0; padding: 0; font-size: 14px; line-height: 1.65; color: #80708c; }
.km-lb .km-lb-compact__open {
  display: inline-block;
  margin-top: 8px;
  font-size: 14px;
  line-height: 1.65;
  color: var(--km-lb-red);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}

/* Шапка серии (`.category-intro`). */
.km-lb .km-lb-intro { display: flex; align-items: flex-start; gap: 27px; margin: 0 0 26px; }
.km-lb img.km-lb-intro__avatar { display: block; flex-shrink: 0; width: 85px; height: 85px; max-width: none; margin: 0; border: 0; border-radius: 16px; box-shadow: none; object-fit: cover; }
.km-lb .km-lb-intro__copy { min-width: 0; }
.km-lb p.km-lb-intro__text { max-width: 650px; margin: 12px 0 0; }
/* «Править: Серия» под описанием — 12 px, как под названием трансляции
   (`.km-cast-head .km-editlinks`); у описания нижнего поля нет, и ссылки
   прилипали к нему (правка Алены 28.09). */
.km-lb .km-lb-intro__copy > .km-editlinks { margin-top: 12px; }
/* Шапка серии без квадрата обложки (правка Алены 28.09.2026): текст от левого
 * края колонки, описание во всю её ширину. */
.km-lb .km-lb-intro--bare p.km-lb-intro__text { max-width: none; }

/* Круги (`.rounds`). */
.km-lb .km-lb-rounds {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 1px;
  margin: 24px 0;
  border: 1px solid var(--km-lb-line);
  border-radius: 11px;
  overflow: hidden;
  background: var(--km-lb-line);
}
.km-lb .km-lb-round { display: flex; align-items: flex-start; gap: 11px; padding: 13px 17px; background: #fbf9fc; color: #9c89a6; }
.km-lb b.km-lb-round__title { display: block; font-size: 13px; font-weight: 650; line-height: 1.65; }
/* НОМЕР КРУГА — ПО ВЕРХУ НАЗВАНИЯ. Правило Алены 2 октября 2026. Круг стоял
   по центру двух строк (название и срок), и «01» висело на 10,7 px ниже
   верха названия. Строка номера — в его кегль, сдвиг 4,35 px докладывает
   разницу высоты знаков Oswald 18 и Manrope 13; на 391–700 px — 2,15
   (16 и 11), до 390 номер спрятан. */
.km-lb .km-lb-round__num { font-family: 'KM Oswald', Arial, sans-serif; font-size: 18px; line-height: 1; margin-top: 4.35px; color: #b19bbe; }
.km-lb small.km-lb-round__period { font-size: 11px; line-height: 1.65; color: #a18bac; }
.km-lb .km-lb-round--current { background: #eee4f5; color: #785388; }
.km-lb .km-lb-round--current .km-lb-round__num { color: #9572a9; }

/* «С чего начать» (`.foundation`). */
.km-lb .km-lb-found { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; }
.km-lb .km-lb-found__card {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 17px;
  background: #fff;
  border: 1px solid var(--km-lb-line);
  border-radius: 15px;
  box-shadow: 0 5px 20px #44255006;
  overflow: hidden;
}
.km-lb .km-lb-found__card--special { background: #f1e9f6; }
.km-lb .km-lb-found__num { margin-bottom: 11px; font-family: 'KM Oswald', Arial, sans-serif; font-size: 24px; line-height: 1.65; color: #b398c1; }
.km-lb h3.km-lb-found__title {
  margin: 0 0 8px;
  padding: 0;
  font-family: 'KM Oswald', Arial, sans-serif;
  font-size: 20px;
  font-weight: 500;
  line-height: 1.35;
  letter-spacing: normal;
  text-transform: none;
  color: var(--km-lb-ink);
}
.km-lb p.km-lb-found__text { flex: 1; margin: 0 0 18px; padding: 0; font-size: 14px; line-height: 1.6; color: #9b84a8; }
.km-lb a.km-lb-found__link,
.km-lb a.km-lb-found__link:link,
.km-lb a.km-lb-found__link:visited,
.km-lb a.km-lb-found__link:focus,
.km-lb a.km-lb-found__link:active {
  margin-top: auto;
  padding: 0;
  border: 0;
  background: transparent;
  box-shadow: none;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.65;
  color: var(--km-lb-red);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
}
.km-lb a.km-lb-found__link:hover { background: transparent; color: var(--km-lb-red-hover); text-decoration: underline; }
.km-lb a.km-lb-found__link:focus-visible { outline: 3px solid var(--km-lb-focus); outline-offset: 4px; }

/* Заметка (`.info-strip`). */
.km-lb .km-lb-strip {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: 22px 0;
  padding: 14px 18px;
  border: 1px solid #e6ddeb;
  border-radius: 10px;
  background: #f0eaf5;
  font-size: 14px;
  line-height: 1.65;
  color: #8c729c;
}
.km-lb .km-lb-strip svg.km-lb-i { width: 17px; height: 17px; margin-top: 2px; }
.km-lb a.km-lb-strip__link,
.km-lb a.km-lb-strip__link:link,
.km-lb a.km-lb-strip__link:visited,
.km-lb a.km-lb-strip__link:focus,
.km-lb a.km-lb-strip__link:active {
  padding: 0;
  border: 0;
  background: transparent;
  box-shadow: none;
  color: var(--km-lb-red);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
}
.km-lb a.km-lb-strip__link:hover { background: transparent; color: var(--km-lb-red-hover); text-decoration: underline; }

@media (max-width: 1250px) {
  .km-lb .km-lb-tile__copy { padding: 16px; }
  .km-lb h3.km-lb-tile__title { font-size: 21px; }
  .km-lb .km-lb-compacts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .km-lb .km-lb-found { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 700px) {
  .km-lb h1.km-lb-title { font-size: 30px; }
  .km-lb p.km-lb-subtitle { margin: 11px 0 19px; font-size: 15px; }
  .km-lb .km-lb-quick { flex-wrap: nowrap; gap: 7px; margin: 20px -18px 23px; padding: 0 18px; overflow-x: auto; scrollbar-width: none; }
  .km-lb a.km-lb-quick__link,
  .km-lb a.km-lb-quick__link:link,
  .km-lb a.km-lb-quick__link:visited,
  .km-lb a.km-lb-quick__link:focus,
  .km-lb a.km-lb-quick__link:active { flex-shrink: 0; padding: 9px 11px; font-size: 13px; white-space: nowrap; }
  .km-lb .km-lb-section { margin-top: 28px; }
  .km-lb .km-lb-tile__image { margin: 8px 8px 0; aspect-ratio: 1.3; border-radius: 7px; }
  .km-lb .km-lb-tile__copy { padding: 14px; }
  .km-lb h3.km-lb-tile__title { font-size: 23px; line-height: 1.3; }
  .km-lb p.km-lb-tile__text { font-size: 14px; line-height: 1.65; }
  .km-lb .km-lb-tile__bottom { margin-top: 14px; }
  .km-lb .km-lb-tile__bottom svg.km-lb-i { width: 14px; }
  .km-lb .km-lb-compacts { grid-template-columns: 1fr; gap: 11px; }
  .km-lb a.km-lb-compact,
  .km-lb a.km-lb-compact:link,
  .km-lb a.km-lb-compact:visited,
  .km-lb a.km-lb-compact:focus,
  .km-lb a.km-lb-compact:active { gap: 17px; padding: 12px 15px; }
  .km-lb img.km-lb-compact__img { width: 74px; height: 86px; }
  .km-lb h3.km-lb-compact__title { font-size: 23px; }
  .km-lb .km-lb-compact__open { margin-top: 6px; }
  .km-lb .km-lb-intro { gap: 15px; }
  .km-lb img.km-lb-intro__avatar { width: 58px; height: 58px; border-radius: 12px; }
  .km-lb .km-lb-intro h1.km-lb-title { font-size: 29px; }
  .km-lb .km-lb-intro .km-lb-eyebrow { font-size: 10px; }
  .km-lb p.km-lb-intro__text { margin: 10px 0 0 -73px; padding-top: 10px; font-size: 15px; }
  /* Без картинки описанию некуда уходить влево — оно под названием. */
  .km-lb .km-lb-intro--bare p.km-lb-intro__text { margin: 10px 0 0; padding-top: 0; }
  .km-lb .km-lb-rounds { margin: 21px 0; }
  .km-lb .km-lb-round { align-items: flex-start; gap: 8px; padding: 10px 9px; }
  .km-lb .km-lb-round__num { font-size: 16px; margin-top: 2.15px; }
  .km-lb b.km-lb-round__title { font-size: 11px; line-height: 1.45; }
  .km-lb small.km-lb-round__period { display: block; margin-top: 4px; font-size: 9px; line-height: 1.5; }
  .km-lb .km-lb-found { gap: 12px; }
  .km-lb .km-lb-found__card { padding: 15px; }
  .km-lb h3.km-lb-found__title { font-size: 22px; }
  .km-lb p.km-lb-found__text { font-size: 13px; }
  .km-lb a.km-lb-found__link,
  .km-lb a.km-lb-found__link:link,
  .km-lb a.km-lb-found__link:visited,
  .km-lb a.km-lb-found__link:focus,
  .km-lb a.km-lb-found__link:active,
  .km-lb a.km-lb-found__link:hover { font-size: 13px; }
  .km-lb .km-lb-strip { margin: 18px 0; padding: 12px 14px; }
}
@media (max-width: 390px) {
  .km-lb a.km-lb-tile,
  .km-lb a.km-lb-tile:link,
  .km-lb a.km-lb-tile:visited,
  .km-lb a.km-lb-tile:focus,
  .km-lb a.km-lb-tile:active { flex-direction: row; }
  .km-lb .km-lb-tile__image { flex-shrink: 0; width: 100px; height: auto; min-height: 125px; margin: 9px 0 9px 9px; aspect-ratio: auto; }
  .km-lb .km-lb-tile__copy { padding: 16px; }
  .km-lb .km-lb-found { grid-template-columns: 1fr 1fr; }
  .km-lb .km-lb-round__num { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .km-lb a.km-lb-tile { transition: none; }
}

/* ── «Главная библиотеки» — настройки главной (админка) ─────────────────────
 * Спецификация 4.16, «Библиотека для клиента кодом». Группы и карточки
 * переставляются перетаскиванием за ручку `⋮⋮` (`jquery-ui-sortable`).
 */
.km-lh__lead { margin: 0 0 20px; max-width: 760px; font-size: 14px; line-height: 1.6; color: var(--km-text-secondary); }
.km-lh-block { display: flex; flex-direction: column; gap: 16px; margin: 0 0 28px; padding: 22px 24px; }
.km-lh-block .km-ad-h2 { margin: 0; }
.km-lh-groups { display: flex; flex-direction: column; gap: 18px; margin: 0 0 18px; }
.km-lh-group { display: flex; flex-direction: column; gap: 14px; padding: 18px 20px; }
.km-lh-group__head { display: flex; align-items: flex-end; gap: 14px; }
.km-lh-group__head > .km-row { flex: 1; }
.km-lh-cards { display: flex; flex-direction: column; gap: 10px; }
.km-lh-card {
  display: grid;
  grid-template-columns: auto 120px minmax(0, 1fr) auto;
  align-items: start;
  gap: 16px;
  padding: 14px;
  border: 1px solid var(--km-border);
  border-radius: 12px;
  background: var(--km-track);
}
.km-lh-card__body { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
/* Третья карточка группы серий («Трансляции по курсам»): только название и текст — без перетаскивания, картинки и удаления. */
.km-lh-card--fixed { grid-template-columns: minmax(0, 1fr); }
.km-lh-media { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
.km-lh-thumb {
  display: grid;
  place-items: center;
  width: 96px;
  height: 110px;
  border: 1px dashed var(--km-border);
  border-radius: 9px;
  background: var(--km-surface);
  overflow: hidden;
}
.km-lh-thumb__img { display: block; width: 100%; height: 100%; object-fit: cover; }
.km-lh-thumb__none { padding: 0 8px; font-size: 12px; text-align: center; color: var(--km-text-muted); }
.km-lh-text { min-height: 64px; }
.km-lh-grip {
  align-self: start;
  padding: 6px 4px;
  border: 0;
  background: transparent;
  font-size: 16px;
  line-height: 1;
  letter-spacing: -2px;
  color: var(--km-text-muted);
  cursor: grab;
}
.km-lh-grip:hover { color: var(--km-text-secondary); }
.km-lh-remove { align-self: start; }
.km-lh-spot { min-height: 60px; border: 2px dashed var(--km-warm-border); border-radius: 12px; background: var(--km-warm-bg); }
.km-lh-bar {
  position: sticky;
  bottom: 0;
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 24px;
  padding: 14px 0;
  /* Фон экрана админки WordPress: полоса «Сохранить» липнет к низу поверх карточек. */
  background: #f0f0f1;
}
.km-lh-state { font-size: 14px; color: var(--km-text-secondary); }
@media (max-width: 900px) {
  .km-lh-card { grid-template-columns: auto minmax(0, 1fr); }
  .km-lh-group__head { flex-wrap: wrap; }
}

/* Повторитель в панелях серии (круги, «С чего начать»): строка — рамкой, «×» в углу. */
.km-sp .km-sp-row { position: relative; margin: 0 0 10px; padding: 12px 12px 2px; border: 1px solid var(--km-border); border-radius: 10px; background: var(--km-surface); }
.km-sp .km-sp-row__x { position: absolute; top: 6px; right: 6px; }
.km-sp .km-sp-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.km-sp .km-sp-sub { display: block; margin: 10px 0 8px; }
.km-sp .km-sp-check { display: flex; margin: 0 0 10px; }
/* Выбор с поиском в панели «Доступ» (задача 28.09): выбранные сверху,
   найденные ниже — список своей прокруткой, чтобы панель не росла на
   четыреста строк. */
.km-sp .km-sp-pick { max-height: 240px; margin-top: 8px; padding: 8px 10px 0; overflow-y: auto; border: 1px solid var(--km-border); border-radius: var(--km-radius-control); }
.km-sp .km-sp-pick:empty { display: none; }
.km-sp .km-sp-pick .km-sp__note { margin: 0 0 10px; }

/* ======================================================================
   СПИСОК ТРАНСЛЯЦИЙ В АДМИНКЕ — «Программы → Трансляции».
   Задача Алены 29 сентября 2026, макет `design/admin-webcasts-list.html`:
   вид остальных экранов LMS, образец — «Зачисления». Полоса сверху, левая
   колонка отборов, выпадающие отборы над таблицей, чипы выбранного,
   таблица по 12, страницы. Данные готовит `AdminList`, рисует
   `templates/admin/library.php`.

   Селекторы с `.km-wl` впереди — не привычка, а сила: поля и списки
   админки WordPress оформлены `.wp-core-ui select` и `input[type=search]`
   (0,1,1), и простой класс (0,1,0) им проиграл бы.
   ====================================================================== */

/* Во всю ширину области админки, до её меню: полоса и колонка в макете —
   от края до края. `#wpcontent` даёт слева 20 px на любом экране шире 782. */
.km-page.km-wl { max-width: none; margin: 0 0 0 -20px; padding: 0 0 60px; background: var(--km-page); min-height: calc(100vh - 32px); }

.km-wl-top { position: sticky; top: 32px; z-index: 5; display: flex; align-items: center; gap: 18px; padding: 14px 28px; background: var(--km-surface); border-bottom: 1px solid var(--km-border); }
.km-wl-top__t { flex: none; }
.km-wl-top__cap { display: block; font-size: 11px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--km-text-muted); }
.km-wl-top__name { display: block; font-size: 16px; font-weight: 700; color: var(--km-text); }
.km-wl-top__vr { width: 1px; height: 34px; background: var(--km-border); flex: none; }
.km-wl-top__sp { flex: 1; }
.km-wl-search { display: flex; align-items: center; gap: 9px; width: 300px; margin: 0; padding: 0 14px; background: var(--km-page); border: 1px solid var(--km-border); border-radius: var(--km-radius-control); color: var(--km-text-muted); }
.km-wl-search svg { width: 16px; height: 16px; flex: none; }
.km-wl .km-wl-search__input { flex: 1; min-width: 0; min-height: 0; margin: 0; padding: 10px 0; border: 0; border-radius: 0; box-shadow: none; background: transparent; font: inherit; font-size: 14px; color: var(--km-text); }
.km-wl .km-wl-search__input:focus { outline: none; box-shadow: none; }
.km-wl-search:focus-within { border-color: var(--km-warm-border); }

.km-wl-cols { display: grid; grid-template-columns: 272px minmax(0, 1fr); align-items: start; }

/* Колонка отборов липнет под полосой и прокручивается сама: 32 — панель
   админки, 63 — полоса. Оба числа постоянны на экране шире 782 px. */
.km-wl-side { position: sticky; top: 95px; height: calc(100vh - 95px); overflow: auto; display: flex; flex-direction: column; gap: 4px; padding: 20px 16px 40px; background: var(--km-surface); border-right: 1px solid var(--km-border); }
.km-wl-cap { padding: 0 8px 8px; font-size: 11px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--km-text-muted); }
.km-wl-hr { height: 1px; margin: 12px; background: var(--km-border-soft); }
.km-wl-seg { display: flex; align-items: center; gap: 10px; border-radius: 10px; }
.km-wl-seg:hover { background: var(--km-page); }
.km-wl-seg--on,
.km-wl-seg--on:hover { background: var(--km-warm-bg); }
.km-wl a.km-wl-seg__link { flex: 1; min-width: 0; display: flex; align-items: center; gap: 10px; padding: 10px 12px; color: var(--km-text); text-decoration: none; box-shadow: none; }
.km-wl-seg__name { flex: 1; min-width: 0; font-size: 14px; }
.km-wl-seg__n { font-size: 12px; color: var(--km-text-muted); }
.km-wl-seg--on .km-wl-seg__name,
.km-wl-seg--on .km-wl-seg__n { color: var(--km-warm-text-strong); font-weight: 700; }
.km-wl-seg__thumb { width: 34px; height: 22px; flex: none; border-radius: 5px; background: var(--km-border); object-fit: cover; }
.km-wl-seg--sub .km-wl-seg__link { padding-left: 30px; }
.km-wl-seg--sub .km-wl-seg__name { font-size: 13px; color: var(--km-text-secondary); }

/* Карандаш — редактор серии. Виден при наведении на строку и с клавиатуры;
   место занимает всегда: под курсором ничего не сдвигается. */
.km-wl a.km-wl-seg__edit { display: inline-flex; padding: 6px; margin-right: 6px; border-radius: 8px; color: var(--km-text-muted); opacity: 0; box-shadow: none; }
.km-wl-seg:hover .km-wl-seg__edit,
.km-wl a.km-wl-seg__edit:focus-visible { opacity: 1; }
.km-wl a.km-wl-seg__edit:hover { color: var(--km-accent); background: var(--km-surface); }
.km-wl-seg__edit svg { width: 14px; height: 14px; }
.km-wl a.km-wl-add { padding: 8px 12px; font-size: 13px; font-weight: 600; color: var(--km-accent); text-decoration: none; box-shadow: none; }
.km-wl-muted { margin: 0; padding: 2px 12px 8px; font-size: 12.5px; line-height: 1.5; color: var(--km-text-muted); }

.km-wl-main { min-width: 0; padding: 24px 28px 60px; }
.km-wl-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 14px; }
.km-wl .km-wl-head__h1 { margin: 0; padding: 0; font-size: 20px; font-weight: 700; line-height: 1.3; color: var(--km-text); }
.km-wl-head__n { font-weight: 600; color: var(--km-text-muted); }
.km-wl .km-wl-order { margin-left: auto; min-height: 0; padding: 8px 30px 8px 12px; font: inherit; font-size: 13px; color: var(--km-text); background-color: var(--km-surface); border: 1px solid var(--km-border); border-radius: var(--km-radius-control); }

.km-wl-fbar { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 10px; }
.km-wl-dd { display: flex; align-items: center; gap: 8px; margin: 0; padding: 6px 6px 6px 12px; background: var(--km-surface); border: 1px solid var(--km-border); border-radius: var(--km-radius-control); }
.km-wl-dd__label { font-size: 12px; font-weight: 600; color: var(--km-text-muted); }
.km-wl .km-wl-dd__select { min-height: 0; padding: 6px 28px 6px 8px; font: inherit; font-size: 13px; color: var(--km-text); background-color: var(--km-page); border: 0; border-radius: 8px; box-shadow: none; }

.km-wl-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 14px; }
.km-wl-fchip { display: inline-flex; align-items: center; gap: 8px; padding: 5px 10px; font-size: 12.5px; font-weight: 600; color: var(--km-warm-text-strong); background: var(--km-warm-bg); border: 1px solid var(--km-warm-border); border-radius: 999px; }
.km-wl a.km-wl-fchip__x { color: var(--km-accent); font-weight: 700; text-decoration: none; box-shadow: none; }
.km-wl a.km-wl-reset { margin-left: 4px; font-size: 12.5px; font-weight: 600; color: var(--km-accent); text-decoration: none; box-shadow: none; }

/* Карточка таблицы — без прокрутки: прокрутка обрезала бы меню «…»
   у нижних строк. На узком окне прокрутка включается правилом ниже. */
.km-wl-tablebox { background: var(--km-surface); border: 1px solid var(--km-border); border-radius: 14px; }
.km-wl-table { width: 100%; border-collapse: separate; border-spacing: 0; }
.km-wl-table th { padding: 12px 14px; text-align: left; font-size: 11px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; white-space: nowrap; color: var(--km-text-muted); background: var(--km-surface-alt); border-bottom: 1px solid var(--km-border); }
.km-wl-table th:first-child { border-top-left-radius: 14px; }
.km-wl-table th:last-child { border-top-right-radius: 14px; }
.km-wl-table td { padding: 12px 14px; font-size: 14px; vertical-align: middle; border-bottom: 1px solid var(--km-border-soft); }
.km-wl-table tbody tr:last-child td { border-bottom: 0; }
.km-wl-table tbody tr:hover td { background: var(--km-surface-alt); }
.km-wl-table__date { width: 72px; }
.km-wl-table__act { width: 48px; text-align: right; }

.km-wl-date { display: flex; flex-direction: column; align-items: center; justify-content: center; width: 46px; height: 46px; border-radius: 12px; background: var(--km-page); line-height: 1.05; }
.km-wl-date__day { font-size: 16px; font-weight: 700; color: var(--km-text); }
.km-wl-date__month { font-size: 10px; color: var(--km-text-muted); }
.km-wl-date--none .km-wl-date__day { color: var(--km-text-muted); }

.km-wl a.km-wl-title { font-size: 14.5px; font-weight: 600; color: var(--km-text); text-decoration: none; box-shadow: none; }
.km-wl a.km-wl-title:hover { color: var(--km-accent); }
.km-wl-title--off { font-size: 14.5px; font-weight: 600; color: var(--km-text-secondary); }
.km-wl-sub { margin-top: 2px; font-size: 12.5px; color: var(--km-text-muted); }
/* Подпись эфира курса — ссылкой на его узел в дереве курса. Под курсором — только цвет. */
.km-wl-sub__link { color: inherit; text-decoration: none; }
.km-wl-sub__link:hover, .km-wl-sub__link:focus-visible { color: var(--km-accent); text-decoration: underline; }

.km-wl-st { display: inline-block; padding: 4px 10px; font-size: 12px; font-weight: 600; white-space: nowrap; border-radius: 999px; }
.km-wl-st--rec { color: var(--km-ok); background: var(--km-done-bg); }
.km-wl-st--live { color: var(--km-warm-text-strong); background: var(--km-warm-bg); }
.km-wl-st--mat { color: var(--km-text-secondary); background: var(--km-border-soft); }
.km-wl-st--draft { color: var(--km-text-muted); background: var(--km-border-soft); }
.km-wl-st--trash { color: var(--km-danger); background: var(--km-danger-bg); }

/* Доступ — строкой, обрезается по ширине столбца; полная — подсказкой.
   190, а не шире: в настоящей админке слева меню WordPress, и таблице
   достаётся на 180 px меньше, чем в макете; при 280 названия трансляций
   переносились на три строки (снимок боевого 29.09.2026). */
.km-wl-acc { display: inline-flex; align-items: center; gap: 6px; max-width: 190px; font-size: 12.5px; white-space: nowrap; color: var(--km-text-secondary); }
.km-wl-acc__t { overflow: hidden; text-overflow: ellipsis; }
.km-wl-acc svg { width: 13px; height: 13px; flex: none; }
.km-wl-acc--own { color: var(--km-warm-text-strong); }
.km-wl-acc--empty { font-weight: 600; color: var(--km-danger); }

.km-wl-num { white-space: nowrap; color: var(--km-text-secondary); }
.km-wl-num svg { width: 15px; height: 15px; margin-right: 6px; vertical-align: -3px; color: var(--km-text-muted); }

/* МЕНЮ «…» СТРОКИ — `details`: открывается без скрипта, закрывается
   повторным нажатием; скрипт закрывает соседние, щелчок мимо и Esc. */
.km-rowmenu { position: relative; display: inline-block; text-align: left; }
.km-rowmenu__btn { display: inline-flex; padding: 6px; border-radius: 8px; color: var(--km-text-muted); cursor: pointer; list-style: none; }
.km-rowmenu__btn::-webkit-details-marker { display: none; }
.km-rowmenu__btn::marker { content: ''; }
.km-rowmenu__btn:hover,
.km-rowmenu[open] > .km-rowmenu__btn { background: var(--km-border-soft); }
.km-rowmenu__btn svg { width: 18px; height: 18px; }
.km-rowmenu__list { position: absolute; top: calc(100% + 4px); right: 0; z-index: 10; display: flex; flex-direction: column; min-width: 210px; padding: 6px; background: var(--km-surface); border: 1px solid var(--km-border); border-radius: 12px; box-shadow: 0 8px 24px rgba(63, 76, 92, 0.14); }
.km-wl a.km-rowmenu__item,
.km-wl button.km-rowmenu__item { display: block; width: 100%; padding: 8px 10px; font: inherit; font-size: 13.5px; text-align: left; white-space: nowrap; color: var(--km-text); text-decoration: none; background: none; border: 0; border-radius: 8px; box-shadow: none; cursor: pointer; }
.km-wl a.km-rowmenu__item:hover,
.km-wl button.km-rowmenu__item:hover { background: var(--km-page); color: var(--km-text); }
.km-wl button.km-rowmenu__item--danger { color: var(--km-danger); }
.km-wl button.km-rowmenu__item[disabled] { color: var(--km-text-muted); cursor: default; }

.km-wl-pager { display: flex; align-items: center; gap: 8px; margin-top: 14px; font-size: 13px; color: var(--km-text-muted); }
.km-wl-pager__info { flex: 1; }
.km-wl a.km-wl-pg { display: inline-flex; align-items: center; justify-content: center; min-width: 34px; height: 34px; font-weight: 600; color: var(--km-text); text-decoration: none; background: var(--km-surface); border: 1px solid var(--km-border); border-radius: 9px; box-shadow: none; }
.km-wl a.km-wl-pg--on { color: var(--km-warm-text-strong); background: var(--km-warm-bg); border-color: var(--km-warm-border); }

/* Узкое окно: колонка отборов над списком, без липкости; таблица —
   своей прокруткой (меню у нижних строк тогда листается вместе с ней). */
@media (max-width: 1100px) {
  .km-wl-cols { grid-template-columns: minmax(0, 1fr); }
  .km-wl-side { position: static; height: auto; border-right: 0; border-bottom: 1px solid var(--km-border); }
  .km-wl-tablebox { overflow-x: auto; }
}
@media (max-width: 782px) {
  .km-page.km-wl { margin-left: -10px; }
  .km-wl-top { position: static; flex-wrap: wrap; padding: 14px 16px; }
  .km-wl-search { width: 100%; }
  .km-wl-main { padding: 20px 16px 48px; }
}

/* ═══════════════════════════════════════════════════════════════════════
   ПРОДАЮЩАЯ СТРАНИЦА КУРСА — прототип `design/course-guest-prototype/
   probuzhdenie-chakr.html`, отзывы — `course-guest-reviews-1280.png`.
   Задача Алены 1 октября 2026, спецификация 12.1.

   Мир прототипа под своим классом `.km-guest` — тем же порядком, что у
   страницы трансляции (`.km-cast`): свои цвета, шрифты прототипа (`KM Manrope`,
   `KM Oswald` объявлены выше) и защита от темы весом `:where()`, а не порядком
   таблиц. Размеры — прототипа, пиксель в пиксель.
   ═══════════════════════════════════════════════════════════════════════ */

/* Акцентный фиолетовый гостевой — и на всей странице закрытого эфира: её шапка стоит над `.km-guest`,
   а надзаголовок окрашен им (задача Алены 07.10.2026). */
.km-guest,
.km-page.km-ce { --km-guest-purple: #866591; }
.km-guest {
  --km-guest-bg: #f7f5f9;
  --km-guest-ink: #33315e;
  --km-guest-text: #5c5868;
  --km-guest-muted: #847c8e;
  --km-guest-line: #e7e1ec;
  --km-guest-lavender: #ede5f3;
  --km-guest-red: #d54844;
  --km-guest-red-hover: #bd3d39;
  --km-guest-display: 'KM Oswald', 'Arial Narrow', sans-serif;
  font-family: 'KM Manrope', Arial, sans-serif;
  font-size: 16px;
  line-height: 1.7;
  color: var(--km-guest-text);
  -webkit-font-smoothing: antialiased;
}
.km-guest *,
.km-guest *::before,
.km-guest *::after { box-sizing: border-box; }
body:has(.km-page--guest) { background-color: #f7f5f9; }

/*
 * Мир прототипа — внутри страницы курса, а не её корень: шапка и полоса
 * с ценой над ним прежние (слово Алены 1 октября 2026), и сбросы заголовков
 * `.km-guest` их не касаются. Ширина и поля — у корня `.km-page--guest`:
 * 1180 с полями 20 (на телефоне 16), то есть содержимое 1140, как `.wrap`
 * прототипа.
 */

/*
 * «О курсе» — прежнее описание из редактора, пока часть настроек пуста.
 * Абзацы и списки встают стопкой с тем же шагом 16, что и прежде у описания;
 * заголовки — шрифтом страницы. Поля темы у детей сняты: тема даёт абзацам
 * 1.6875rem снизу, и шаг складывался бы с ними.
 */
.km-guest .km-guest-prose { display: flex; flex-direction: column; gap: 16px; max-width: 680px; font-size: 16px; line-height: 1.8; color: var(--km-guest-text); }
.km-guest .km-guest-prose > * { margin: 0; }
.km-guest .km-guest-prose :where(ul, ol) { padding-left: 22px; }
.km-guest .km-guest-prose :where(ul) { list-style: disc; }
.km-guest .km-guest-prose :where(ol) { list-style: decimal; }
.km-guest .km-guest-prose :where(li + li) { margin-top: 6px; }
.km-guest .km-guest-prose :where(h2) { margin-top: 8px; font-size: 30px; }
.km-guest .km-guest-prose :where(h3, h4) { margin-top: 4px; font-size: 20px; }
.km-guest .km-guest-prose :where(strong, b) { color: var(--km-guest-ink); }
.km-guest .km-guest-prose :where(a) { color: var(--km-guest-purple); text-decoration: underline; text-underline-offset: 3px; }

/* Тема: заголовки, абзацы, ссылки, кнопки, списки — наши во всём. */
.km-guest :where(h1, h2, h3) { margin: 0; padding: 0; letter-spacing: normal; text-transform: none; color: var(--km-guest-ink); }
.km-guest :where(h1, h2) { font-family: var(--km-guest-display); font-weight: 500; line-height: 1.2; }
.km-guest :where(h3) { font-family: inherit; font-size: 17px; font-weight: 700; line-height: 1.5; }
.km-guest :where(p) { margin: 0; }
.km-guest :where(ul, ol) { margin: 0; padding: 0; }
.km-guest :where(a, a:visited) { color: inherit; text-decoration: none; background-color: transparent; }
.km-guest :where(a:hover) { color: var(--km-guest-red); }
.km-guest :where(button) { margin: 0; font: inherit; cursor: pointer; text-transform: none; letter-spacing: normal; box-shadow: none; }
.km-guest :where(a, button, summary) { transition: background .18s, color .18s, box-shadow .18s; -webkit-tap-highlight-color: transparent; }
.km-guest :where(a, button, summary):focus-visible { outline: 3px solid #897093; outline-offset: 5px; }
.km-guest :where(summary) { list-style: none; cursor: pointer; }
.km-guest :where(summary)::-webkit-details-marker { display: none; }
.km-guest :where(img) { max-width: 100%; object-fit: cover; }
.km-guest .km-guest-icon { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; flex-shrink: 0; }

/* Надстрочник, заголовки разделов. */
.km-guest .km-guest-eyebrow { display: block; margin-bottom: 13px; font-size: 12px; font-weight: 700; letter-spacing: .13em; text-transform: uppercase; line-height: 1.7; color: var(--km-guest-purple); }
.km-guest .km-guest-h2 { font-size: 34px; margin-bottom: 20px; }
.km-guest .km-guest-h3 { font-size: 17px; }
.km-guest .km-guest-lead { max-width: 680px; font-size: 17px; line-height: 1.8; color: #4e485f; }
.km-guest .km-guest-text { max-width: 680px; font-size: 16px; line-height: 1.8; }
/* «О курсе» в прототипе — обычный абзац (1.7), описания разделов — 1.8. */
.km-guest .km-guest-section--about > .km-guest-text { line-height: 1.7; }
.km-guest .km-guest-lead + .km-guest-text,
.km-guest .km-guest-text + .km-guest-text { margin-top: 14px; }

/* Кнопки (`.button`, `.secondary`). */
.km-guest a.km-guest-button,
.km-guest button.km-guest-button {
  display: inline-flex; justify-content: center; align-items: center; text-align: center;
  min-height: 46px; padding: 12px 23px; border: 1px solid transparent; border-radius: 7px;
  background: var(--km-guest-red); color: #fff; font-size: 14px; font-weight: 700; line-height: 1.5;
  box-shadow: 0 4px 12px #d5484410;
}
.km-guest a.km-guest-button:hover,
.km-guest button.km-guest-button:hover { background: var(--km-guest-red-hover); color: #fff; box-shadow: 0 5px 16px #d5484428; }
.km-guest a.km-guest-button--secondary,
.km-guest button.km-guest-button--secondary { background: #fff; border-color: #b6a0c1; color: #71557f; box-shadow: none; }
.km-guest a.km-guest-button--secondary:hover,
.km-guest button.km-guest-button--secondary:hover { background: #f2ebf7; color: #71557f; box-shadow: none; }
.km-guest .km-guest-button--full { width: 100%; }
.km-guest .km-guest-text-button { border: 0; background: none; padding: 7px 0; font-size: 14px; font-weight: 600; color: var(--km-guest-purple); text-decoration: underline; text-underline-offset: 4px; white-space: nowrap; }
.km-guest .km-guest-text-button:hover { color: var(--km-guest-red); background: none; }

/* Крошки. */
.km-guest .km-guest-crumbs { display: flex; align-items: center; gap: 13px; padding: 26px 0 20px; font-size: 12px; color: var(--km-guest-muted); }
.km-guest .km-guest-crumbs a { color: #62596d; }

/* Шапка (`.hero`). */
.km-guest .km-guest-hero { position: relative; isolation: isolate; min-height: 395px; border-radius: 18px; overflow: hidden; background: #dcefe6; }
.km-guest .km-guest-hero__image { position: absolute; inset: 0; width: 100%; height: 100%; object-position: 50% 52%; z-index: -2; }
.km-guest .km-guest-hero::after { content: ''; position: absolute; inset: 0; z-index: -1; background: linear-gradient(90deg, rgba(239, 248, 240, .93), rgba(239, 248, 240, .7) 34%, transparent 63%); }
.km-guest .km-guest-hero__content { width: 59%; padding: 37px 42px; }
.km-guest .km-guest-hero__label { color: #47666a; }
.km-guest h1.km-guest-hero__title { margin: 11px 0 17px; padding: 0 !important; font-family: var(--km-guest-display); font-size: 53px; font-weight: 500; line-height: 1.07; letter-spacing: -.025em; text-transform: uppercase; color: var(--km-guest-ink); }
.km-guest .km-guest-hero__summary { font-size: 16px; line-height: 1.65; color: #4e6062; }
.km-guest .km-guest-hero__author { display: flex; align-items: center; gap: 9px; margin: 17px 0; font-size: 12px; color: #496064; }
.km-guest .km-guest-hero__author img { width: 36px; height: 36px; border: 2px solid #fff; border-radius: 50%; object-position: center 30%; }
.km-guest .km-guest-hero__caption { position: absolute; bottom: 19px; right: 24px; padding: 5px 11px; border: 1px solid #ffffff80; border-radius: 5px; background: #ffffffe3; font-size: 12px; color: #4f5e65; }

/* Цифры (`.course-facts`). */
.km-guest .km-guest-facts { display: grid; grid-template-columns: repeat(4, 1fr); margin: 0 0 23px; padding: 24px 0; border-bottom: 1px solid var(--km-guest-line); }
.km-guest .km-guest-facts > div { padding: 0 28px; border-right: 1px solid var(--km-guest-line); }
.km-guest .km-guest-facts > div:first-child { padding-left: 12px; }
.km-guest .km-guest-facts > div:last-child { border-right: 0; }
.km-guest .km-guest-facts strong { display: block; font-size: 17px; font-weight: 700; color: var(--km-guest-ink); }
.km-guest .km-guest-facts span { font-size: 12px; color: var(--km-guest-muted); }

/* Раскладка: содержимое и карточка справа (`.page-layout`). */
.km-guest .km-guest-layout { display: grid; grid-template-columns: minmax(0, 1fr) 302px; gap: 38px; align-items: start; }
.km-guest .km-guest-layout--single { grid-template-columns: minmax(0, 1fr); }
.km-guest .km-guest-content { min-width: 0; }

/* Строка переходов (`.section-nav`): липнет под шапкой сайта. */
.km-guest .km-guest-nav { position: sticky; top: var(--km-chrome-top); z-index: 10; display: flex; justify-content: space-between; gap: 10px; padding: 8px 0 0; border-bottom: 1px solid var(--km-guest-line); background: var(--km-guest-bg); font-size: 14px; font-weight: 600; }
.km-guest a.km-guest-nav__item { display: inline-flex; align-items: center; gap: 6px; margin-bottom: -1px; padding: 14px 12px; border-bottom: 2px solid transparent; white-space: nowrap; color: #786d82; }
.km-guest a.km-guest-nav__item:hover { color: var(--km-guest-red); }
.km-guest a.km-guest-nav__item.is-active { color: var(--km-guest-ink); border-bottom-color: var(--km-guest-purple); }
.km-guest .km-guest-nav__count { display: inline-block; padding: 0 7px; border-radius: 10px; background: var(--km-guest-lavender); font-size: 11px; line-height: 1.7; color: var(--km-guest-purple); }

/* Раздел (`.content-section`). */
.km-guest .km-guest-section { padding: 39px 0; border-bottom: 1px solid var(--km-guest-line); scroll-margin-top: calc(var(--km-chrome-top) + 70px); }
.km-guest .km-guest-section__head { display: flex; align-items: center; justify-content: space-between; gap: 20px; }
.km-guest .km-guest-section__head .km-guest-h2 { margin-bottom: 13px; }
.km-guest .km-guest-section__head + .km-guest-text { margin-bottom: 25px; }

/* «Ваш путь»: три шага и «Вам сюда, если…». */
.km-guest .km-guest-steps { display: grid; gap: 24px; margin: 31px 0; }
.km-guest .km-guest-step { display: flex; align-items: flex-start; gap: 17px; }
.km-guest .km-guest-step__number { display: grid; place-items: center; min-width: 37px; height: 37px; border-radius: 50%; background: var(--km-guest-lavender); font-family: var(--km-guest-display); font-size: 17px; color: var(--km-guest-purple); }
/* ЦИФРА — ПО ВЕРХУ ПЕРВОЙ СТРОКИ (правило 2 октября 2026, `CLAUDE.md`,
   «Правила отображения»): верх «01» в кружке — на одной линии с верхом
   заголовка шага. Кружок высотой 37 держит цифру посередине, и без сдвига
   она стояла на 5,2 px ниже заголовка; на узком (заголовок 16 px) то же
   число даёт 0,2 px. Мерка — `stand.numberTops()`, допуск 2 px. */
.km-guest .km-guest-step__number { margin-top: -5.2px; }
.km-guest .km-guest-step__text { max-width: 545px; margin-top: 4px; font-size: 14px; line-height: 1.7; color: var(--km-guest-muted); }
.km-guest .km-guest-for-you { display: flex; gap: 15px; margin-top: 29px; padding: 20px; border-radius: 10px; background: #eee7f3; color: #6a5976; }
.km-guest .km-guest-for-you .km-guest-icon { margin-top: 4px; }
.km-guest .km-guest-for-you p { font-size: 14px; line-height: 1.8; }
.km-guest .km-guest-for-you strong { display: block; margin-bottom: 4px; color: #574366; }

/* Программа: вступление, модули, занятия, итог. */
.km-guest .km-guest-intro { display: flex; align-items: center; gap: 13px; margin: 25px 0 12px; padding: 18px 20px; border: 1px solid var(--km-guest-line); border-radius: 10px; background: #fff; }
.km-guest .km-guest-intro__icon { display: grid; place-items: center; width: 34px; height: 34px; border: 1px solid var(--km-guest-line); border-radius: 50%; color: var(--km-guest-purple); }
.km-guest .km-guest-intro__icon .km-guest-icon { width: 17px; height: 17px; }
.km-guest .km-guest-intro strong { display: block; font-size: 14px; color: var(--km-guest-ink); }
.km-guest .km-guest-intro div > span { font-size: 12px; color: var(--km-guest-muted); }
.km-guest .km-guest-intro__tag { margin-left: auto; padding: 3px 8px; border-radius: 4px; background: #f5eff8; font-size: 12px; white-space: nowrap; color: #82668c; }
.km-guest .km-guest-modules { display: grid; gap: 12px; }
.km-guest .km-guest-module { overflow: hidden; border: 1px solid var(--km-guest-line); border-radius: 11px; background: #fff; }
.km-guest .km-guest-module > summary { display: flex; align-items: center; gap: 18px; padding: 23px; }
.km-guest .km-guest-module > summary:hover { background: #faf7fc; }
.km-guest .km-guest-module[open] { border-color: #cbb9d4; }
.km-guest .km-guest-module[open] > summary { background: #f0e9f5; }
.km-guest .km-guest-module__number { align-self: flex-start; flex: none; width: 32px; margin-top: 2.6px; line-height: 1; font-family: var(--km-guest-display); font-size: 28px; font-weight: 500; color: #b2a1bd; }
/* НОМЕР МОДУЛЯ — КОЛОНКОЙ ПОСТОЯННОЙ ШИРИНЫ И ПО ВЕРХУ ПЕРВОЙ СТРОКИ.
   Правки Алены 2 октября 2026.

   Ширина. «01» в этом шрифте на 3 px уже «02» и «03», и текст модулей
   начинался на разных вертикалях. Колонка — 32 px: шире самой широкой
   пары до «12» (29,5 px у «06» и «09»); на узком — 28 (26,4 при 25 px).

   Высота. Верх цифры — на линии верха «МОДУЛЬ 1 · 4 ЗАНЯТИЯ»: прежде она
   висела на 8,4 px ниже. Строка цифры — в её кегль (`line-height: 1`),
   и сдвиг 2,6 px докладывает разницу высоты знаков двух шрифтов; на узком
   то же даёт 0,4 px. Тело модуля отступает ровно под текст: 23 поля
   шапки + 32 колонки + 18 промежутка = 73. */
.km-guest .km-guest-module__title { display: block; flex: 1; }
.km-guest .km-guest-module__title small { display: block; margin-bottom: 3px; font-size: 12px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: #8e729a; }
.km-guest .km-guest-module__title strong { display: block; font-family: var(--km-guest-display); font-size: 24px; font-weight: 500; line-height: 1.4; color: var(--km-guest-ink); }
.km-guest .km-guest-module__title > span { display: block; margin-top: 4px; font-size: 14px; color: var(--km-guest-muted); }
.km-guest .km-guest-plus { position: relative; display: block; flex-shrink: 0; width: 25px; height: 25px; border-radius: 50%; background: #f7f3fa; color: var(--km-guest-purple); }
.km-guest .km-guest-plus::before,
.km-guest .km-guest-plus::after { content: ''; position: absolute; top: 12px; left: 7.5px; width: 10px; height: 1.5px; background: currentColor; }
.km-guest .km-guest-plus::after { transform: rotate(90deg); transition: transform .2s; }
.km-guest details[open] > summary .km-guest-plus::after { transform: rotate(0); }
.km-guest .km-guest-plus--small { width: 21px; height: 21px; }
.km-guest .km-guest-plus--small::before,
.km-guest .km-guest-plus--small::after { top: 10px; left: 5.5px; }
.km-guest .km-guest-module__body { padding: 6px 24px 20px 73px; }
.km-guest .km-guest-lessons { list-style: none; }
/* СТРОКИ ЗАНЯТИЙ — НОМЕР И НАЗВАНИЕ ОДНОГО РАЗМЕРА, ПО ОДНОЙ БАЗОВОЙ ЛИНИИ.
   Правки Алены 2 октября 2026: сперва крупнее в 1,5 раза (название 14 → 21,
   номер 11 → 16,5, 1.387.0), затем «номер нужного размера — название того
   же размера». Размер задан ОДИН РАЗ — у строки, 16,5 px, и номер с названием
   его наследуют: два числа однажды разъехались бы. Номер — по базовой линии
   (`align-items: baseline`), а не сдвигом. «Плюс» раскрытия — по середине
   строки, у него базовой линии нет. Длительность и темы в раскрытом
   занятии — прежние (`.km-guest-lesson__body`, 13 px). */
.km-guest .km-guest-lesson { display: flex; align-items: baseline; gap: 16px; padding: 13px 0; border-bottom: 1px solid #f0ebf3; font-size: 16.5px; line-height: 1.35; color: #534d63; }
.km-guest .km-guest-lesson__number { flex: none; min-width: 29px; color: #b1a4bb; }
.km-guest .km-guest-lesson__more { flex: 1; }
.km-guest .km-guest-lesson__more > summary { display: flex; align-items: baseline; gap: 16px; }
.km-guest .km-guest-lesson__more > summary > .km-guest-plus { align-self: center; }
.km-guest .km-guest-lesson__name { flex: 1; }
.km-guest .km-guest-lesson__body { padding: 8px 0 2px 45px; font-size: 13px; line-height: 1.6; color: var(--km-guest-muted); }
.km-guest .km-guest-lesson__duration { font-weight: 600; color: var(--km-guest-purple); }
.km-guest .km-guest-lesson__topics { margin-top: 4px; padding-left: 18px; list-style: disc; }
.km-guest .km-guest-module__result { padding: 16px 0 3px; font-size: 14px; line-height: 1.8; color: var(--km-guest-muted); }
.km-guest .km-guest-module__result strong { color: var(--km-guest-purple); }
.km-guest .km-guest-module__after { margin-top: 12px; padding: 9px 12px; border-radius: 4px; background: #f8f5fa; font-size: 12px; color: #897393; }
/* ИТОГ — БЕЛОЙ КАРТОЧКОЙ, КАК «ЗНАКОМСТВО С КУРСОМ». Правка Алены 2 октября
   2026: серая строка с галкой на фоне страницы была почти не видна. Тот же
   вид, что у вступления (`.km-guest-intro`): белая карточка, круглый значок
   (галка вместо «play»), заголовок, подпись, плашка «Финал». Есть занятия —
   `details`, раскрывается, как модуль; шапка карточки — `summary`, тело —
   список занятий той же разметкой (`parts/guest-lessons.php`). */
.km-guest .km-guest-intro--end { margin: 12px 0 0; }
.km-guest details.km-guest-intro--end { display: block; padding: 0; overflow: hidden; }
.km-guest .km-guest-intro--end > summary { display: flex; align-items: center; gap: 13px; padding: 18px 20px; cursor: pointer; }
.km-guest .km-guest-intro--end > summary:hover { background: #faf7fc; }
.km-guest details.km-guest-intro--end[open] { border-color: #cbb9d4; }
.km-guest details.km-guest-intro--end[open] > summary { background: #f0e9f5; }
.km-guest .km-guest-intro--end .km-guest-intro__tag { margin-left: auto; }
.km-guest .km-guest-intro--end > summary > .km-guest-plus { margin-left: 0; }
.km-guest .km-guest-intro__body { padding: 6px 24px 20px 67px; }

/* «Как учиться». */
.km-guest .km-guest-format { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; margin: 28px 0; }
.km-guest .km-guest-format__icon { display: grid; place-items: center; width: 40px; height: 40px; margin-bottom: 14px; border-radius: 10px; background: #eee7f3; color: #9a7ea5; }
.km-guest .km-guest-format h3 { margin-bottom: 8px; font-size: 14px; }
.km-guest .km-guest-format p { font-size: 16px; line-height: 1.8; color: var(--km-guest-muted); }
.km-guest .km-guest-all-in-one { padding: 20px 23px; border: 1px solid var(--km-guest-line); border-radius: 9px; background: #fff; }
.km-guest .km-guest-all-in-one strong { font-size: 14px; color: var(--km-guest-ink); }
.km-guest .km-guest-all-in-one p { margin-top: 5px; font-size: 16px; line-height: 1.8; }

/* Ведущая. */
.km-guest .km-guest-teacher { display: grid; grid-template-columns: 180px 1fr; gap: 26px; align-items: center; }
.km-guest .km-guest-teacher--text { grid-template-columns: 1fr; }
.km-guest .km-guest-teacher__photo { width: 180px; height: 225px; border-radius: 12px; object-position: center; }
.km-guest .km-guest-teacher .km-guest-eyebrow { margin-bottom: 10px; }
.km-guest .km-guest-teacher__name { margin-bottom: 6px; font-size: 28px; }
.km-guest .km-guest-teacher__role { margin-bottom: 16px; font-size: 12px; line-height: 1.8; color: var(--km-guest-purple); }
.km-guest .km-guest-teacher__text { font-size: 16px; line-height: 1.8; }
.km-guest .km-guest-teacher__text + .km-guest-teacher__text { margin-top: 14px; }

/* Отзывы — `course-guest-reviews-1280.png`. */
.km-guest .km-guest-reviews { display: grid; gap: 16px; }
/* «ЦИТАТА НАВЕРХУ» — по макету `design/course-guest-prototype/top-quote-*.png`
   (правка Алены 2 октября 2026): без карточки, рамки и линий — цитата на фоне
   страницы, с воздухом сверху и снизу; линию над ней снимает
   `--before-quote` у раздела «О курсе». Слева — большая светло-сиреневая
   кавычка Oswald; текст — шрифт страницы, 21 px (на телефоне 18), средней
   полужирности, цветом заголовков; ширина — до 760 px по центру колонки.
   Подпись в одну строку; «Все отзывы ↓» — справа, на телефоне под подписью.
   Под курсором меняется только цвет ссылки. */
.km-guest .km-guest-section--before-quote { border-bottom: 0; }
.km-guest figure.km-guest-top-quote { display: grid; grid-template-columns: 50px minmax(0, 1fr); gap: 0 12px; max-width: 760px; margin: 0 auto; padding: 22px 0 23px; border: 0; background: none; }
.km-guest .km-guest-top-quote__mark { font-family: var(--km-guest-display); font-size: 84px; font-weight: 500; line-height: 0.82; color: #d2bddc; }
/* Столбец текста и подписи: без `min-width: 0` длинное слово распёрло бы сетку. */
.km-guest .km-guest-top-quote__body { min-width: 0; }
.km-guest blockquote.km-guest-top-quote__text { margin: 0; padding: 0; border: 0; background: none; quotes: none; font-family: inherit; font-size: 21px; font-style: normal; font-weight: 500; line-height: 1.57; color: var(--km-guest-ink); }
.km-guest blockquote.km-guest-top-quote__text::before,
.km-guest blockquote.km-guest-top-quote__text::after { content: none; }
.km-guest .km-guest-top-quote__foot { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 10px 12px; margin-top: 16px; }
.km-guest .km-guest-top-quote__who { font-size: 15px; color: var(--km-guest-muted); }
.km-guest .km-guest-top-quote__who strong { font-weight: 700; color: var(--km-guest-ink); }
.km-guest a.km-guest-top-quote__all { font-size: 15px; font-weight: 600; color: var(--km-guest-purple); text-decoration: none; white-space: nowrap; }
.km-guest a.km-guest-top-quote__all:hover { color: var(--km-guest-ink); }
/* Шапка «Отзывы участниц» — карточкой, как сами отзывы (`course-guest-reviews-1280.png`). */
.km-guest .km-guest-reviews__head,
.km-guest .km-guest-review { padding: 22px 23px; border: 1px solid var(--km-guest-line); border-radius: 11px; background: #fff; }
.km-guest .km-guest-reviews__head .km-guest-h2 { margin-bottom: 14px; font-size: 26px; }
.km-guest .km-guest-reviews__head p { font-size: 15px; line-height: 1.8; }
.km-guest .km-guest-review { display: grid; gap: 14px; }
.km-guest .km-guest-review[hidden] { display: none; }
/* КАРТОЧКА ОТЗЫВА — КОМПАКТНО, В ТОНЕ СТРАНИЦЫ (правка Алены 2 октября 2026).
   Цитата — как подзаголовок раздела (`.km-guest-h3`: шрифт текста, 17 px),
   а не как заголовок; не больше трёх строк. «В начале» и «После» — по четыре,
   «Кому рекомендую» — две; дальше многоточие. Блоки пары — по высоте своего
   текста (`align-items: start`): короткий не тянется под длинный. Раскрытая
   карточка (`.km-guest-review--open`) показывает всё полностью. */
.km-guest h3.km-guest-review__quote { font-size: 17px; font-weight: 600; line-height: 1.55; color: var(--km-guest-ink); }
.km-guest .km-guest-review__pair { display: grid; grid-template-columns: 1fr 1fr; align-items: start; gap: 12px; }
/* Один блок из пары («В начале курса» или «После курса» — вопроса в форме курса нет) —
   на всю ширину, а не половиной с пустотой справа (формы курсов, 3 октября 2026). */
.km-guest .km-guest-review__pair > .km-guest-review__box:only-child { grid-column: 1 / -1; }
.km-guest .km-guest-review__box { padding: 13px 15px; border-radius: 9px; background: #f6f2f8; }
.km-guest .km-guest-review:not(.km-guest-review--open) .km-guest-review__quote,
.km-guest .km-guest-review:not(.km-guest-review--open) .km-guest-review__box p,
.km-guest .km-guest-review:not(.km-guest-review--open) .km-guest-review__recommend p,
.km-guest blockquote.km-guest-top-quote__text { display: -webkit-box; -webkit-box-orient: vertical; overflow: hidden; }
.km-guest .km-guest-review:not(.km-guest-review--open) .km-guest-review__quote,
.km-guest blockquote.km-guest-top-quote__text { -webkit-line-clamp: 3; line-clamp: 3; }
.km-guest .km-guest-review:not(.km-guest-review--open) .km-guest-review__box p { -webkit-line-clamp: 4; line-clamp: 4; }
.km-guest .km-guest-review:not(.km-guest-review--open) .km-guest-review__recommend p { -webkit-line-clamp: 2; line-clamp: 2; }
.km-guest .km-guest-review__box--after { background: #efe7f4; }
.km-guest .km-guest-review__box span,
.km-guest .km-guest-review__recommend span,
.km-guest .km-guest-review__answer span { display: block; margin-bottom: 6px; font-size: 12px; font-weight: 700; color: #6c6275; }
.km-guest .km-guest-review__box p,
.km-guest .km-guest-review__recommend p,
.km-guest .km-guest-review__answer p { font-size: 15px; line-height: 1.7; color: var(--km-guest-text); }
.km-guest .km-guest-review__full { display: grid; gap: 14px; }
.km-guest .km-guest-review__full[hidden] { display: none; }
/* Низ карточки — сеткой: кружок, подпись, кнопка. Подпись — поле формы целиком
   (решение Алены 1 октября 2026) и бывает длинной: на телефоне кнопка уходит
   под неё, в тот же столбец, а не сжимает её в узкую колонку. */
.km-guest .km-guest-review__foot { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 4px 12px; padding-top: 14px; border-top: 1px solid var(--km-guest-line); }
.km-guest .km-guest-review__avatar { display: grid; place-items: center; flex-shrink: 0; width: 36px; height: 36px; border-radius: 50%; background: var(--km-guest-lavender); font-size: 14px; font-weight: 700; color: var(--km-guest-purple); }
.km-guest .km-guest-review__who { display: grid; min-width: 0; }
.km-guest .km-guest-review__who strong { font-size: 15px; color: var(--km-guest-ink); }
.km-guest .km-guest-review__who span { font-size: 13px; color: var(--km-guest-muted); }
/* «Читать полностью» / «Свернуть» — в стиле страницы: цвет акцента страницы,
   без красного и без подчёркивания, со стрелкой вниз и вверх (раскрыто —
   стрелка повёрнута). Под курсором меняется только цвет. */
.km-guest button.km-guest-review__more { display: inline-flex; align-items: center; gap: 6px; border: 0; padding: 7px 0; background: none; font-size: 14px; font-weight: 600; color: var(--km-guest-purple); text-decoration: none; white-space: nowrap; }
.km-guest button.km-guest-review__more:hover { color: var(--km-guest-ink); background: none; }
.km-guest button.km-guest-review__more[hidden] { display: none; }
.km-guest .km-guest-review__arrow { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.km-guest .km-guest-review--open .km-guest-review__arrow { transform: rotate(180deg); }
.km-guest .km-guest-reviews__more { justify-self: center; }

/* Вопросы. */
.km-guest .km-guest-faq .km-guest-h2 { font-size: 30px; }
.km-guest .km-guest-faq details { border-top: 1px solid var(--km-guest-line); }
.km-guest .km-guest-faq summary { display: flex; align-items: center; justify-content: space-between; gap: 18px; padding: 20px 0; font-size: 14px; font-weight: 600; color: var(--km-guest-ink); }
.km-guest .km-guest-faq summary:hover { color: var(--km-guest-purple); }
.km-guest .km-guest-faq details p { padding: 0 34px 24px 0; font-size: 16px; line-height: 1.8; color: var(--km-guest-muted); }

/* Карточка «Ваше участие» (`.sidebar`). */
.km-guest .km-guest-aside { align-self: stretch; padding-top: 8px; }
.km-guest .km-guest-aside__sticky { position: sticky; top: calc(var(--km-chrome-top) + 26px); }
.km-guest .km-guest-card { padding: 27px 24px 23px; border: 1px solid var(--km-guest-line); border-radius: 13px; background: #fff; box-shadow: 0 6px 24px #33315e05; }
.km-guest .km-guest-card .km-guest-eyebrow { margin-bottom: 12px; }
.km-guest h2.km-guest-card__title { margin-bottom: 16px; font-size: 27px; line-height: 1.3; }
.km-guest .km-guest-card__tag { display: inline-block; padding: 5px 8px; border-radius: 4px; background: #f1ebf6; font-size: 12px; white-space: nowrap; color: #806a8b; }
.km-guest .km-guest-card__price { margin-top: 22px; font-size: 32px; font-weight: 700; line-height: 1.3; letter-spacing: -.03em; color: var(--km-guest-ink); }
.km-guest .km-guest-card__price span { font-size: 24px; font-weight: 500; }
.km-guest .km-guest-card__note { margin: 4px 0 21px; font-size: 14px; color: var(--km-guest-muted); }
.km-guest .km-guest-included { display: grid; gap: 10px; margin: 22px 0; list-style: none; font-size: 14px; color: #6c6275; }
.km-guest .km-guest-included li { display: flex; align-items: baseline; gap: 9px; }
.km-guest .km-guest-included li::before { content: '✓'; font-size: 12px; color: #9a7da6; }
.km-guest .km-guest-card__account { display: flex; align-items: center; gap: 10px; padding-top: 18px; border-top: 1px solid var(--km-guest-line); font-size: 12px; line-height: 1.8; color: #998da3; }
.km-guest .km-guest-card__account .km-guest-icon { width: 16px; height: 16px; }
.km-guest .km-guest-help { display: grid; gap: 4px; margin-top: 19px; text-align: center; font-size: 14px; color: var(--km-guest-muted); }
.km-guest .km-guest-help a { font-size: 14px; color: var(--km-guest-purple); text-decoration: underline; text-underline-offset: 3px; }

/* Оплата (`.participation`). */
.km-guest .km-guest-pay { margin: 52px 0 60px; padding: 38px 60px 28px; border: 1px solid #e5dbed; border-radius: 16px; background: #eee6f3; scroll-margin-top: calc(var(--km-chrome-top) + 30px); }
.km-guest .km-guest-pay__head { margin-bottom: 29px; text-align: center; }
.km-guest .km-guest-pay__head .km-guest-eyebrow { margin-bottom: 10px; }
.km-guest .km-guest-pay__head .km-guest-h2 { margin-bottom: 12px; }
.km-guest .km-guest-pay__head p { font-size: 14px; color: #8a7893; }
.km-guest h3.km-guest-pay__tariff { max-width: 810px; margin: 22px auto 12px; font-family: var(--km-guest-display); font-size: 22px; font-weight: 500; color: var(--km-guest-ink); }
.km-guest .km-guest-prices { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; max-width: 810px; margin: 0 auto; }
.km-guest .km-guest-prices--one { grid-template-columns: minmax(0, 395px); justify-content: center; }
/* Карточка тарифа — столбцом: тело растягивается (`flex: 1`) и держит отступ
   до кнопки 22 px снизу — тот, что был у «Пробуждения чакр» под списком «что
   входит». Кнопка не прилипает к подписи в карточке без списка, а кнопки
   соседних карточек одного ряда стоят на одном уровне (правка Алены 2 октября
   2026). */
.km-guest .km-guest-price { display: flex; flex-direction: column; padding: 27px 29px; border: 1px solid #ded1e7; border-radius: 11px; background: #fff; }
.km-guest .km-guest-price__body { flex: 1 0 auto; padding-bottom: 22px; }
.km-guest .km-guest-price__label { font-size: 14px; font-weight: 600; color: var(--km-guest-purple); }
.km-guest .km-guest-price__value { margin-top: 10px; font-size: 35px; font-weight: 700; letter-spacing: -.03em; color: var(--km-guest-ink); }
.km-guest .km-guest-price__value span { font-size: 23px; font-weight: 500; }
.km-guest .km-guest-price__note { margin-top: 2px; font-size: 14px; color: var(--km-guest-muted); }
.km-guest .km-guest-price .km-guest-included { margin: 19px 0 0; }
.km-guest .km-guest-price__why { font-size: 14px; color: var(--km-guest-muted); }
.km-guest .km-guest-pay__help { margin-top: 23px; text-align: center; font-size: 14px; color: var(--km-guest-muted); }
.km-guest .km-guest-pay__help a { color: var(--km-guest-purple); text-decoration: underline; text-underline-offset: 3px; }

/* Полоса цены на телефоне (`.mobile-cta`). */
.km-guest .km-guest-mobile { display: none; }

@media (min-width: 1450px) {
  .km-page.km-page--guest { max-width: 1240px; }
  .km-guest .km-guest-hero { min-height: 412px; }
  .km-guest .km-guest-hero__content { padding: 40px 46px; }
  .km-guest .km-guest-layout { grid-template-columns: minmax(0, 1fr) 320px; gap: 48px; }
  .km-guest .km-guest-layout--single { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 1000px) {
  .km-guest .km-guest-layout { grid-template-columns: minmax(0, 1fr) 270px; gap: 24px; }
  .km-guest .km-guest-layout--single { grid-template-columns: minmax(0, 1fr); }
  .km-guest .km-guest-card { padding: 24px 20px; }
  .km-guest .km-guest-nav { gap: 0; }
  .km-guest a.km-guest-nav__item { padding: 14px 7px; }
  .km-guest .km-guest-hero__content { width: 66%; }
  .km-guest .km-guest-hero__caption { display: none; }
  .km-guest .km-guest-facts > div { padding: 0 17px; }
  .km-guest .km-guest-teacher { grid-template-columns: 140px 1fr; gap: 20px; }
  .km-guest .km-guest-teacher__photo { width: 140px; height: 210px; }
  .km-guest .km-guest-pay { padding: 36px; }
}
@media (max-width: 760px) {
  .km-guest .km-guest-crumbs { padding: 19px 0 16px; font-size: 11px; }
  .km-guest .km-guest-hero { min-height: 445px; border-radius: 12px; }
  .km-guest .km-guest-hero__image { object-position: 62% 50%; opacity: .75; }
  .km-guest .km-guest-hero::after { background: linear-gradient(90deg, rgba(239, 248, 240, .96), rgba(239, 248, 240, .7) 50%, rgba(239, 248, 240, .04)); }
  .km-guest .km-guest-hero__content { width: 100%; padding: 31px 20px 31px 25px; }
  .km-guest h1.km-guest-hero__title { margin: 15px 0 18px; font-size: 45px; }
  .km-guest .km-guest-hero__summary { max-width: 280px; }
  .km-guest .km-guest-hero__author { margin: 19px 0; }
  .km-guest .km-guest-facts { grid-template-columns: 1fr 1fr; gap: 18px 0; margin-bottom: 6px; padding: 24px 0 20px; }
  .km-guest .km-guest-facts > div { padding: 0 18px; }
  .km-guest .km-guest-facts > div:first-child { padding-left: 18px; }
  .km-guest .km-guest-facts > div:nth-child(2) { border-right: 0; }
  .km-guest .km-guest-facts strong { font-size: 16px; }
  .km-guest .km-guest-facts span { display: block; line-height: 1.6; }
  .km-guest .km-guest-layout { display: block; }
  .km-guest .km-guest-aside { display: none; }
  .km-guest .km-guest-nav { justify-content: space-between; gap: 13px; overflow-x: auto; padding-top: 4px; font-size: 13px; scrollbar-width: none; }
  .km-guest .km-guest-nav::-webkit-scrollbar { display: none; }
  .km-guest a.km-guest-nav__item { padding: 15px 3px; }
  .km-guest .km-guest-section { padding: 31px 0; }
  .km-guest .km-guest-h2 { font-size: 30px; }
  .km-guest .km-guest-lead { font-size: 16px; }
  .km-guest .km-guest-steps { gap: 23px; margin: 27px 0; }
  .km-guest .km-guest-for-you { gap: 12px; padding: 18px; }
  .km-guest .km-guest-for-you .km-guest-icon { width: 18px; }
  .km-guest .km-guest-section__head { align-items: flex-end; gap: 10px; margin-bottom: 12px; }
  .km-guest .km-guest-intro { gap: 10px; padding: 15px; }
  .km-guest .km-guest-intro div > span { display: block; }
  .km-guest .km-guest-intro__tag { display: none; }
  .km-guest .km-guest-module > summary { gap: 14px; padding: 20px 17px; }
  .km-guest .km-guest-module__number { width: 28px; font-size: 25px; }
  .km-guest .km-guest-module__title strong { font-size: 23px; }
  .km-guest .km-guest-module__title > span { max-width: 230px; }
  .km-guest .km-guest-module__body { padding: 5px 18px 18px; }
  .km-guest .km-guest-intro--end > summary { gap: 10px; padding: 15px; }
  .km-guest .km-guest-intro__body { padding: 5px 18px 18px; }
  .km-guest .km-guest-format { grid-template-columns: 1fr; gap: 17px; }
  .km-guest .km-guest-format article { display: grid; grid-template-columns: 40px 1fr; column-gap: 14px; }
  .km-guest .km-guest-format__icon { grid-row: span 2; margin-bottom: 0; }
  .km-guest .km-guest-format h3 { margin-bottom: 3px; }
  .km-guest .km-guest-step .km-guest-h3 { font-size: 16px; }
  .km-guest .km-guest-text-button { font-size: 12px; }
  .km-guest .km-guest-all-in-one { padding: 18px; }
  .km-guest .km-guest-teacher { grid-template-columns: 90px 1fr; align-items: start; gap: 18px; }
  .km-guest .km-guest-teacher__photo { width: 90px; height: 125px; }
  .km-guest .km-guest-teacher__name { font-size: 26px; }
  .km-guest .km-guest-teacher .km-guest-eyebrow { font-size: 10px; }
  .km-guest .km-guest-teacher__text { font-size: 14px; }
  .km-guest .km-guest-review__pair { grid-template-columns: 1fr; }
  .km-guest .km-guest-review { padding: 18px 17px; }
  .km-guest .km-guest-review__foot { grid-template-columns: auto minmax(0, 1fr); }
  .km-guest button.km-guest-review__more { grid-column: 2; justify-self: start; }
  /* Цитата — кеглем подзаголовка и на узком: там он 16 px (`.km-guest-step .km-guest-h3`). */
  .km-guest h3.km-guest-review__quote { font-size: 16px; }
  .km-guest figure.km-guest-top-quote { grid-template-columns: 36px minmax(0, 1fr); gap: 0 10px; padding: 31px 0 38px; }
  .km-guest .km-guest-top-quote__mark { font-size: 64px; }
  .km-guest blockquote.km-guest-top-quote__text { font-size: 18px; }
  /* На телефоне ссылка — под подписью, с края имени: тот же столбец сетки. */
  .km-guest .km-guest-top-quote__foot { grid-template-columns: auto minmax(0, 1fr); }
  .km-guest a.km-guest-top-quote__all { grid-column: 2; justify-self: start; }
  .km-guest .km-guest-faq .km-guest-h2 { font-size: 28px; }
  .km-guest .km-guest-pay { margin: 33px 0 32px; padding: 27px 18px 22px; }
  .km-guest .km-guest-pay__head .km-guest-h2 { font-size: 30px; }
  .km-guest .km-guest-prices,
  .km-guest .km-guest-prices--one { grid-template-columns: 1fr; gap: 16px; }
  .km-guest .km-guest-price { padding: 24px; }
  /*
   * КНОПКА ЧАТА CARROT — НАД ПОЛОСОЙ С ЦЕНОЙ. Слово Алены 1 октября 2026:
   * на телефоне круглая кнопка чата ложилась на «Выбрать участие».
   * Carrot ставит себе отступ сам — `#carrotquest-messenger-collapsed-container
   * { margin-bottom: 65px !important }`, своим `<style>` в странице; перебить
   * его можно только правилом сильнее (1,1,1) и тоже с `!important` —
   * ничья по силе выигрывалась бы порядком, а порядок здесь чужой.
   * Отступ — высота полосы (69) и тот же зазор 15, что у Carrot справа.
   */
  body:has(.km-guest-mobile) #carrotquest-messenger-collapsed-container { margin-bottom: 84px !important; }
  .km-guest .km-guest-mobile { position: fixed; z-index: 15; bottom: 0; left: 0; right: 0; display: flex; align-items: center; justify-content: space-between; padding: 12px 19px calc(12px + env(safe-area-inset-bottom)); border-top: 1px solid var(--km-guest-line); background: #fffffff5; box-shadow: 0 -4px 22px #33315e09; }
  .km-guest .km-guest-mobile > span { display: grid; line-height: 1.5; }
  .km-guest .km-guest-mobile strong { font-size: 17px; color: var(--km-guest-ink); }
  .km-guest .km-guest-mobile small { font-size: 12px; color: var(--km-guest-muted); }
  .km-guest .km-guest-mobile a.km-guest-button { min-height: 43px; padding: 12px 18px; font-size: 12px; }
}
@media (prefers-reduced-motion: reduce) {
  .km-guest *,
  .km-guest *::before,
  .km-guest *::after { transition: none !important; }
}

/*
 * Раздел «Продающая страница» в настройках курса. Задача Алены 1 октября 2026.
 *
 * Части — створками: раздел длинный (у «Пробуждения чакр» 35 занятий),
 * и открытым целиком он прятал бы остальные блоки настроек. У каждой
 * части справа — есть ли её раздел на странице: пустая часть раздела
 * не даёт, и сказано это словами, а не пустотой.
 *
 * Под курсором ничего не двигается: меняется только цвет.
 */
.km-gp { border: 1px solid var(--km-border); border-radius: 10px; background: var(--km-surface); }
.km-gp__head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  cursor: pointer;
  list-style: none;
  font-size: 14px;
  font-weight: 600;
  color: var(--km-text);
}
.km-gp__head::-webkit-details-marker { display: none; }
.km-gp__head::after { content: '+'; width: 14px; text-align: center; color: var(--km-text-muted); font-weight: 400; }
.km-gp[open] > .km-gp__head::after { content: '−'; }
.km-gp__head:hover { color: var(--km-accent); }
.km-gp__state { margin-left: auto; font-size: 12.5px; font-weight: 500; color: var(--km-ok); white-space: nowrap; }
.km-gp__state--off { color: var(--km-text-muted); }
.km-gp__body { padding: 14px 16px 16px; border-top: 1px solid var(--km-border-soft); }
.km-gp__node { padding: 12px 14px; border: 1px solid var(--km-border-soft); border-radius: 8px; background: var(--km-surface-alt); }
.km-gp__node-title { font-size: 14px; font-weight: 600; color: var(--km-text); }
.km-gp__lessons { border-top: 1px dashed var(--km-border); padding-top: 8px; }
.km-gp__lessons-head { cursor: pointer; font-size: 13px; font-weight: 600; color: var(--km-text-secondary); }
.km-gp__lessons-head:hover { color: var(--km-accent); }
.km-gp__lesson { padding: 12px 0 4px; border-bottom: 1px solid var(--km-border-soft); }
.km-gp__lesson:last-child { border-bottom: 0; }
.km-gp__lesson-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 16px; }
.km-gp__map { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px 18px; }
@media (max-width: 782px) {
  .km-gp__map { grid-template-columns: 1fr; }
  .km-gp__state { white-space: normal; text-align: right; }
}

/*
 * Экран «Отзывы». Задача Алены 1 октября 2026, спецификация 12.3.
 *
 * Одобренная запись отличается не только переключателем: рамка «сделано»
 * видна, когда список прокручен и переключатель далеко, — признак существует,
 * когда он отличается от соседнего случая.
 */
.km-tm-pick { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; }
.km-tm-pick .km-field { min-width: 0; flex: 1 1 360px; max-width: 560px; }
.km-tm-summary { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 8px 18px; font-size: 14px; }
.km-tm-summary p { margin: 0; }
.km-tm {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 18px 20px;
  border: 1px solid var(--km-border);
  border-radius: var(--km-radius-card);
  background: var(--km-surface);
}
/* С 2 октября 2026 показаны все записи, кроме скрытых: отмечается скрытая —
   рамкой пунктиром и приглушённым текстом; прежняя зелёная метка
   «показана» стояла бы теперь у всех. */
.km-tm--hidden { border-style: dashed; }
.km-tm--hidden .km-tm__quote,
.km-tm--hidden .km-tm__pairs { opacity: 0.55; }
.km-tm__head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; }
.km-tm__when { flex: 1 1 auto; font-size: 13px; color: var(--km-text-muted); }
/* Ручка перетаскивания — настоящая: тащит строку и стрелками двигает её
   на место вверх-вниз (`assets/js/testimonials.js`). Под курсором меняется
   только цвет. */
.km-tm__handle { display: grid; place-items: center; flex: none; width: 28px; height: 28px; padding: 0; border: 1px solid var(--km-border); border-radius: 7px; background: var(--km-surface); color: var(--km-text-muted); cursor: grab; }
.km-tm__handle:hover { color: var(--km-text); border-color: var(--km-warm-border); }
.km-tm__handle:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--km-warm-bg); }
.km-tm__handle svg { width: 16px; height: 16px; fill: currentColor; }
.km-tm__top { font-size: 14px; }
.km-tm-top { margin: 0; font-size: 14px; color: var(--km-text-secondary); }
.km-tm-order { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 16px; min-height: 28px; }
.km-tm__quote { margin: 0; font-family: var(--km-font-display); font-size: 20px; line-height: 1.4; color: var(--km-text); overflow-wrap: anywhere; }
.km-tm__pairs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px 18px; }
.km-tm__pair { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.km-tm__pair p { margin: 0; font-size: 14px; line-height: 1.6; color: var(--km-text-secondary); overflow-wrap: anywhere; }
.km-tm__all { border-top: 1px dashed var(--km-border); padding-top: 10px; }
.km-tm__all > summary { cursor: pointer; font-size: 13px; font-weight: 600; color: var(--km-text-secondary); }
.km-tm__all > summary:hover { color: var(--km-accent); }
.km-tm__all .km-tm__pair { padding-top: 10px; }
.km-tm__status { margin: 0; min-height: 20px; font-size: 13px; color: var(--km-ok); }
.km-tm__status--error { color: var(--km-danger); }
@media (max-width: 960px) {
  .km-tm__pairs { grid-template-columns: 1fr; }
}

/* ===== Закрытый эфир по регистрации (4.18) =====
 * Макет: design/closed-event-v2.html (задача Алены 5 октября 2026). Раскладка
 * и блоки — макета, оформление — гостевой страницы курса: шапка `km-hero`,
 * разделы, «О курсе», ведущая и карточка справа — её же классы `km-guest-*`,
 * размеры от неё. Своё здесь — только то, чего у гостевой нет: светлая
 * подложка шапки, плашки, блок состояния, пункты «Что будет», «Как это
 * проходит», форма в карточке.
 *
 * ШРИФТЫ — ТОКЕНАМИ, а не прототипа гостевой: тот под `.km-guest` носит
 * Manrope и Oswald (`--km-guest-display`), а здесь по слову Алены только
 * `--km-font` (Open Sans) и `--km-font-display` (Roboto Condensed). Подмена —
 * на корне страницы; стенд меряет вычисленный шрифт у всех текстов.
 *
 * Корень `.km-page.km-ce` (0,2,0): страница стоит в обвязке темы, и её
 * умолчания для `button`, `input`, `h1`–`h3` перебиваются силой, а не порядком. */
/* Корень — свой шрифт: подзаголовок шапки (`km-hero__lead`) шрифта не задаёт и наследовал бы шрифт темы. */
.km-page.km-ce { font-family: var(--km-font); }
.km-page.km-ce .km-guest { font-family: var(--km-font); }
/* Заголовки разделов — шрифтом заголовков гостевой курса (`--km-guest-display`, Oswald): решение Алены
   07.10.2026 «как у гостевой» поверх запрета 05.10 на Oswald — он действует для текста, не для заголовков разделов. */
.km-page.km-ce .km-guest :where(input, button, select, textarea) { font-family: var(--km-font); }

/* Заголовки разделов — шрифтом, размером, насыщенностью и межстрочным «Зарегистрируйтесь» в карточке
   (`.km-guest-card__title`, 27 px / 1,3), а не «Программа курса» — тот крупнее (слово Алены 07.10.2026: «слишком
   большие»). Имя ведущей — заголовок своего раздела, туда же. Держит мерка стенда `заголовок раздела … как
   «Зарегистрируйтесь»` на 1280 и 375. */
.km-page.km-ce .km-guest .km-guest-section h2.km-guest-h2 { font-size: 27px; line-height: 1.3; }
/* Поперечных полосок между разделами у эфира нет (слово Алены 07.10.2026); у гостевой курса — как были. */
.km-page.km-ce .km-guest .km-guest-section { border-bottom: 0; }
/* Вокруг плеера — по 36 px до текста выше и до заголовка «Впечатления» ниже, без дыр. 07.10.2026 было 78 («дыры»)
   и стало 24; 08.10 Алена: «чуток увеличить отступ от плеера сверху и снизу — совсем близко стало» — 36.
   Поля разделов по 39 сверху и снизу без полосок складывались в 78, плюс собственные поля блока плеера. */
.km-page.km-ce .km-guest .km-guest-section:has(+ .km-ce__player-section) { padding-bottom: 0; }
.km-page.km-ce .km-guest .km-guest-section.km-ce__player-section { padding: 36px 0; }
.km-page.km-ce .km-guest .km-ce__player-section + .km-guest-section { padding-top: 0; }
.km-page.km-ce .km-ce__player > * { margin-top: 0; margin-bottom: 0; }
/* Текст для незарегистрированных — продолжение описания: тот же шаг 16 между абзацами, что внутри `.km-guest-prose`. */
.km-page.km-ce .km-guest .km-guest-prose + .km-guest-prose { margin-top: 16px; }
/* «Впечатления об эфире» — wpDiscuz, как в библиотеке (`.km-cast-talk`): поля темы и wpDiscuz вокруг формы и
   пустого списка — наши, иначе над формой 50 px и под «0 комментариев» 70 px пустоты (боевой 07.10). Гостю
   вместо формы стоит наша строка (`EventTalk::gate`) — своя «Пожалуйста, войдите…» у wpDiscuz её повторяла.
   Вес — с `#wpdcom`, как у правил wpDiscuz. */
/*
 * «Впечатления об эфире» — заголовок и число как «Комментарии» у трансляции библиотеки
 * (`.km-cast h2.km-cast-talk__title`, `.km-cast-talk__count`): 21 px и число рядом. Слово Алены
 * 12.10.2026: «для преемственности». Вес (0,6,1) — выше заголовков разделов эфира
 * `.km-page.km-ce .km-guest .km-guest-section h2.km-guest-h2` (0,5,1, они как «Зарегистрируйтесь», 27 px)
 * и `.km-guest .km-guest-h2` с правилом для телефона: держится силой селектора, а не порядком.
 */
.km-page.km-ce .km-guest .km-guest-section h2.km-guest-h2.km-ce__talk-title { margin-bottom: 17px; font-size: 21px; line-height: 1.25; }
/* Шрифт числа — основной шрифт страницы (у трансляции это её Manrope, у эфира Open Sans): набор шрифтов эфира не расширяется. */
.km-guest .km-ce__talk-count { margin-left: 8px; font-family: var(--km-font); font-size: 14px; font-weight: 800; letter-spacing: 1.8px; color: #9a7dab; }

.km-page.km-ce .km-ce__talk #comments { margin: 0; padding: 0; }
.km-page.km-ce .km-ce__talk #wpdcom { max-width: none; margin: 0; padding: 0; }
.km-page.km-ce .km-ce__talk #wpdcom .wpd-form-head { border: 0; margin: 0; padding: 0; }
.km-page.km-ce .km-ce__talk #wpdcom .wpd-form-wrap,
.km-page.km-ce .km-ce__talk #wpdcom .wpdiscuz-textarea-wrap { padding: 0; }
.km-page.km-ce .km-ce__talk #wpdcom .wpd-thread-wrapper { margin: 0; }
.km-page.km-ce .km-ce__talk #wpdcom .wpd-thread-list:not(:has(.wpd-comment)) { padding: 0; }
.km-page.km-ce .km-ce__talk #wpdcom .wpd-login-to-comment { display: none; }
.km-page.km-ce .km-ce__talk #wpdcom .wpd-form textarea.wc_comment { min-height: 56px; padding: 14px 16px; }
/* «Править:» — с тем же отступом до содержимого, что на других страницах (`km-stack`, `--km-gap-group`):
   у эфира строка внутри `.km-guest`, а не стопки, и после регистрации отсчёт прилипал к ней. */
.km-page.km-ce .km-guest > .km-editlinks { margin: 0 0 var(--km-stack-gap, var(--km-gap-group)); }
/* «О чём эфир» — на всю левую колонку до карточки (задача Алены 05.10: без своего предела ширины,
   разрыва до карточки нет); размер и межстрочный — текста «О курсе» гостевой (`km-guest-section--about`: 16px, 1.7). */
.km-page.km-ce .km-guest .km-guest-prose { max-width: none; line-height: 1.7; }

/* ЗАГЛАВНЫХ И РАЗРЯДКИ НА СТРАНИЦЕ ЭФИРА НЕТ (задача Алены 05.10): надзаголовок, подписи разделов, плашки,
   кнопки — как написано. Классов гостевой с `uppercase` здесь несколько (`km-hero__eyebrow`,
   `km-guest-eyebrow`, значки «Идёт эфир», «Сейчас»), и снять их надо разом и наверняка: сила (0,4,0)
   повтором своего класса — сильнее любого правила гостевой и темы, без порядка таблиц.
   Держит мерка стенда «ни у одного элемента нет uppercase». */
.km-page.km-ce.km-ce.km-ce,
.km-page.km-ce.km-ce.km-ce * { text-transform: none; letter-spacing: normal; }

/* Карточка регистрации шире, чем «Ваше участие» (задача Алены 05.10): 380 на компьютере, левая колонка —
   остаток; уже 1000 и на телефоне — как у гостевой. */
@media (min-width: 1001px) {
  .km-page.km-ce .km-guest .km-guest-layout { grid-template-columns: minmax(0, 1fr) 380px; }
}

/* ШАПКА — та же, что у гостевой курса (`templates/parts/guest-hero.php`, задача Алены 07.10.2026): своих правил
   у неё нет, кроме названных отличий. Надзаголовок и название — обычными буквами (правило «без заглавных и
   разрядки» ниже снимает и прописные, и разрядку); межстрочная плотность названия — курса (−0,01em), её то же
   правило иначе сбросило бы. Название одним цветом: второй части у эфира нет. */
.km-page.km-ce.km-ce.km-ce .km-ce__hero .km-hero__title { letter-spacing: -0.01em; }
/* Надзаголовок — ровно как у шапки курса, с прописными и разрядкой (слово Алены 07.10.2026, третье): правило
   страницы «без заглавных и разрядки» ниже его не касается. Сила (0,6,0) — выше того правила (0,4,0); значения —
   те же, что у курса (`.km-hero--brand .km-hero__eyebrow` и его узкий вид ≤ 640), кроме межстрочного на телефоне
   (08.10, абзацем ниже). Держит мерка стенда «надзаголовок — как у гостевой курса» по всем свойствам. */
.km-page.km-ce.km-ce.km-ce .km-ce__hero .km-hero__eyebrow { text-transform: uppercase; letter-spacing: 0.14em; }
@media (max-width: 640px) {
  .km-page.km-ce.km-ce.km-ce .km-ce__hero .km-hero__eyebrow { letter-spacing: 0.1em; line-height: 1.5; }
}
/* ШАПКА ЭФИРА НА ТЕЛЕФОНЕ — ПО СОДЕРЖИМОМУ (слово Алены 08.10.2026: «это что за порнография» про снимок 375).
   Дыра под обложкой складывалась из трёх чужих долей, и ни одна не про эфир:
   — над названием 30 px сниппета сайта «Объединённый CSS» (`h1 { padding-top: 30px !important }` до 782 px; то же
     у занятия и каталога — правило «Чужое поле над заголовком гасится»). `!important` — ответ той же силой;
   — межстрочный 27 px темы у всего подряд: надзаголовок эфира на 375 переносится на две строки, и строки стояли
     врозь (11 px букв на 27 px строки). У курса он в одну строку — там не видно, и шапки курсов не тронуты;
   — высота тела не меньше 200 px — шапки курса, где шесть строк приезжают скриптом (`min-height: 200px` на узком).
     У эфира две строки и всё рисует сервер: прыгать нечему, и 200 оставляли пустоту над и под текстом.
   Держат мерки стенда «название: чужое поле сверху не пробивается» и «на телефоне шапка по содержимому». */
.km-page.km-ce .km-ce__hero h1.km-hero__title { padding-top: 0 !important; }
@media (max-width: 640px) {
  .km-page.km-ce .km-hero--brand.km-hero--over.km-ce__hero .km-hero__body { min-height: 0; }
}
/* Надзаголовок и название — не посередине обложки, а выше: над ними треть её высоты (слово Алены 07.10.2026; только
   у эфира, шапки курсов не тронуты). 374 — высота шапки из правила `.km-hero--brand.km-hero--over .km-hero__body`;
   поменяют её — мерка стенда «над надзаголовком треть высоты обложки» покраснеет. На телефоне обложка над текстом. */
@media (min-width: 641px) {
  .km-page.km-ce .km-hero--brand.km-hero--over.km-ce__hero .km-hero__body { justify-content: flex-start; padding-top: calc(374px / 3); }
}
/* Подложка под текстом: у тёмного вида курса её нет (`::after` снят), у эфира — лёгкая светлая слева направо, белый
   55% у левого края до нуля к середине шапки (слово Алены 07.10.2026): текст читается, картинка справа яркая.
   На телефоне текст стоит под обложкой — подложки нет. */
.km-page.km-ce .km-hero--brand.km-hero--ink.km-hero--over.km-ce__hero::after {
  content: '';
  background: linear-gradient(to right, color-mix(in srgb, #fff 55%, transparent) 0%, color-mix(in srgb, #fff 0%, transparent) 50%);
}
@media (max-width: 640px) {
  .km-page.km-ce .km-hero--brand.km-hero--ink.km-hero--over.km-ce__hero::after { content: none; }
}

/* «✎ изменить» у каждого блока — только команде (`ClosedEventPage::edit_urls()`): тихая ссылка рядом с заголовком. */
.km-page.km-ce div.km-ce__head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 14px; }
.km-page.km-ce a.km-ce__edit { flex: none; font-family: var(--km-font); font-size: 13px; font-weight: 600; line-height: 1.4; color: var(--km-text-muted); text-decoration: none; }
.km-page.km-ce a.km-ce__edit:hover,
.km-page.km-ce a.km-ce__edit:focus-visible { color: var(--km-guest-purple); text-decoration: underline; }
.km-page.km-ce .km-hero__lead a.km-ce__edit { margin-left: 6px; }

/* Блок над разделами: отсчёт, кнопки площадок, «Что дальше». */
.km-page.km-ce section.km-ce__state { display: grid; gap: 14px; margin: 0 0 8px; padding: 22px 24px; border: 1px solid var(--km-guest-line); border-radius: 13px; background: var(--km-surface); }
.km-page.km-ce section.km-ce__state--live { border-color: var(--km-live); }
.km-page.km-ce p.km-ce__state-title { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0; font-family: var(--km-font-display); font-size: 22px; font-weight: 600; line-height: 1.25; color: var(--km-guest-ink); }
.km-page.km-ce span.km-ce__live { display: inline-flex; padding: 3px 10px; border-radius: 999px; background: var(--km-live); font-family: var(--km-font); font-size: 12px; font-weight: 700; line-height: 1.4; letter-spacing: 0.04em; text-transform: uppercase; color: #fff; }
.km-page.km-ce div.km-ce__count { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.km-page.km-ce div.km-ce__count-cell { padding: 12px 6px; border-radius: 12px; background: var(--km-guest-bg); text-align: center; }
.km-page.km-ce b.km-ce__count-num { display: block; font-family: var(--km-font-display); font-size: 28px; font-weight: 700; line-height: 1.1; font-variant-numeric: tabular-nums; color: var(--km-guest-ink); }
.km-page.km-ce span.km-ce__count-word { font-size: 13px; color: var(--km-guest-muted); }
.km-page.km-ce div.km-ce__go { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.km-page.km-ce .km-ce__btn { display: flex; align-items: center; justify-content: center; margin: 0; padding: 13px 16px; border: 0; border-radius: 12px; box-shadow: none; font-family: var(--km-font); font-size: 15px; font-weight: 600; line-height: 1.3; text-transform: none; text-decoration: none; color: #fff; cursor: pointer; }
.km-page.km-ce .km-ce__btn.km-ce__btn--youtube { background: var(--km-live); }
.km-page.km-ce .km-ce__btn.km-ce__btn--kinescope { background: var(--km-brand-navy); }
.km-page.km-ce a.km-ce__btn:hover,
.km-page.km-ce a.km-ce__btn:focus { color: #fff; filter: brightness(0.92); }
.km-page.km-ce a.km-ce__btn:focus-visible { outline: 2px solid var(--km-brand-navy); outline-offset: 2px; }
.km-page.km-ce button.km-ce__btn:disabled { opacity: 0.45; cursor: not-allowed; }
.km-page.km-ce div.km-ce__player { overflow: hidden; border-radius: 12px; }
.km-page.km-ce p.km-ce__small { margin: 0; font-size: 13px; line-height: 1.5; color: var(--km-guest-muted); }
.km-page.km-ce .km-guest-card p.km-ce__small { margin-top: 10px; text-align: center; }

/* «Что будет на эфире»: номер по верху первой строки (правило отображения). */
.km-page.km-ce ol.km-ce__points { display: grid; gap: 12px; margin: 18px 0 0; padding: 0; list-style: none; }
.km-page.km-ce li.km-ce__point { display: grid; grid-template-columns: 28px minmax(0, 1fr); gap: 14px; align-items: start; margin: 0; padding: 0; }
.km-page.km-ce span.km-ce__point-n { display: grid; place-items: center; width: 28px; height: 28px; margin-top: 0; border-radius: 50%; background: var(--km-guest-lavender); font-family: var(--km-font-display); font-size: 15px; font-weight: 600; line-height: 1; color: var(--km-guest-purple); }
.km-page.km-ce span.km-ce__point-text { font-size: 16px; line-height: 1.75; color: var(--km-guest-text); }

/* «Как это проходит»: три карточки. */
.km-page.km-ce div.km-ce__how { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-top: 18px; }
.km-page.km-ce div.km-ce__how-item { display: grid; gap: 4px; align-content: start; padding: 16px 18px; border-radius: 13px; background: var(--km-guest-bg); }
.km-page.km-ce b.km-ce__how-title { font-size: 15px; font-weight: 600; line-height: 1.4; color: var(--km-guest-ink); }
.km-page.km-ce span.km-ce__how-text { font-size: 14px; line-height: 1.55; color: var(--km-guest-text); }

/* Карточка справа: регистрация, «вы зарегистрированы», «сейчас», «спасибо». */
.km-page.km-ce form.km-ce__form { display: grid; gap: 12px; margin: 0; }
.km-page.km-ce label.km-ce__field { margin: 0; }
.km-page.km-ce .km-ce__field input.km-input { width: 100%; height: auto; min-height: 0; margin: 0; box-shadow: none; }
.km-page.km-ce label.km-ce__trap { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }
.km-page.km-ce label.km-ce__check { font-size: 13px; line-height: 1.45; color: var(--km-guest-text); }
.km-page.km-ce span.km-ce__check-text a { color: var(--km-guest-purple); text-decoration: underline; text-underline-offset: 3px; }
.km-page.km-ce p.km-ce__status { margin: 0; font-size: 13px; line-height: 1.45; color: var(--km-danger); }
.km-page.km-ce p.km-ce__ok { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin: 0 0 8px; font-size: 16px; font-weight: 700; line-height: 1.35; color: var(--km-guest-ink); }
.km-page.km-ce span.km-ce__tick { display: inline-flex; flex: none; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 50%; background: var(--km-done-bg); font-size: 13px; line-height: 1; color: var(--km-ok); }
.km-page.km-ce div.km-ce__free { display: flex; justify-content: space-between; gap: 10px; margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--km-guest-line); font-size: 14px; color: var(--km-guest-muted); }
.km-page.km-ce div.km-ce__free b { color: var(--km-guest-ink); }

/* Подсказка о почте под полем (spec 4.19): ставит `assets/js/email-check.js`, классы — настройкой страницы. */
.km-page.km-ce div.km-ce__mail-hint { display: flex; flex-wrap: wrap; gap: 6px 10px; align-items: center; margin: -4px 0 0; padding: 8px 10px; border: 1px solid var(--km-guest-line); border-radius: 10px; background: var(--km-guest-bg); font-family: var(--km-font); font-size: 13px; line-height: 1.45; color: var(--km-guest-text); }
.km-page.km-ce div.km-ce__mail-hint--block { border-color: var(--km-danger); background: var(--km-surface); color: var(--km-danger); }
.km-page.km-ce span.km-ce__mail-text { flex: 1 1 180px; min-width: 0; overflow-wrap: anywhere; }
.km-page.km-ce button.km-ce__mail-fix { flex: none; margin: 0; padding: 5px 12px; border: 1px solid var(--km-guest-purple); border-radius: 8px; background: var(--km-surface); box-shadow: none; font-family: var(--km-font); font-size: 13px; font-weight: 600; line-height: 1.3; letter-spacing: normal; text-transform: none; color: var(--km-guest-purple); cursor: pointer; }
.km-page.km-ce button.km-ce__mail-fix:hover,
.km-page.km-ce button.km-ce__mail-fix:focus { border-color: var(--km-guest-ink); background: var(--km-surface); box-shadow: none; color: var(--km-guest-ink); }
.km-page.km-ce button.km-ce__mail-fix:focus-visible { outline: 2px solid var(--km-guest-purple); outline-offset: 2px; }

/* Телефон: гостевая прячет правую колонку, у эфира карточка — сразу под шапкой. */
@media (max-width: 760px) {
  .km-page.km-ce .km-guest .km-guest-layout { display: flex; flex-direction: column; gap: 18px; }
  .km-page.km-ce .km-guest aside.km-ce__aside { display: block; order: -1; padding-top: 0; }
  .km-page.km-ce .km-guest aside.km-ce__aside .km-guest-aside__sticky { position: static; }
  .km-page.km-ce div.km-ce__how,
  .km-page.km-ce div.km-ce__go { grid-template-columns: minmax(0, 1fr); }
  .km-page.km-ce section.km-ce__state { padding: 18px 16px; }
}

/*
 * Пост статьи «Ключей» в общей ленте BuddyBoss (Integration\BlogFeed, спецификация 10.3): картинка карточки — целиком,
 * в своих пропорциях. BuddyBoss растягивает картинку превью ссылки на всю ширину не ниже 340 px с обрезкой
 * (object-fit: cover) и рамкой не выше 340 px (max-height), и обложка 3:2 выходила увеличенной и срезанной — слово
 * Алены 08.10.2026: «ужасно выглядит».
 * Только у наших постов (класс ставит BlogFeed); чужие ссылки в ленте как были. Перебивается силой селектора —
 * у BuddyBoss (0,3,1) и (0,3,0), у нас на класс больше, — а не порядком таблиц.
 */
.km-feed-article .activity-link-preview-container .activity-link-preview-image .activity-link-preview-image-cover {
	min-height: 0;
	max-height: none;
}

.km-feed-article .activity-link-preview-container .activity-link-preview-image .activity-link-preview-image-cover img {
	width: 100%;
	max-width: 100%;
	min-width: 0;
	height: auto;
	min-height: 0;
	object-fit: contain;
}

/*
 * Название в карточке поста статьи — отличается от текста под ним (слово Алены 08.10.2026: «заголовок статьи такой же
 * как текст»). BuddyBoss задаёт названию только цвет, размер и насыщенность наследуются от текста поста.
 * Силой селектора: у BuddyBoss (0,3,0) и (0,3,1).
 */
.km-feed-article .activity-link-preview-container .activity-link-preview-info .activity-link-preview-title,
.km-feed-article .activity-link-preview-container .activity-link-preview-info .activity-link-preview-title a {
	font-size: 18px;
	font-weight: 700;
	line-height: 1.35;
}

/* ---------------------------------------------------------------------------
   Сообщество (4.20)
   ---------------------------------------------------------------------------
   Доски `design/feed-v2.dc.html`, `group-v3.dc.html`, `mobile-v3.dc.html`:
   их палитра — токенами здесь, а не кодами по месту. Шрифты — те же файлы
   прототипа, что у библиотеки (`KM Manrope`, `KM Oswald`).

   Кнопки — внутри `.km-hub`, во всех состояниях и с силой (0,2,1): тема
   красит любой `button` (радиус 100px, синяя заливка, белый текст на белом
   при наведении), и ничья по силе выигрывается порядком, который меняет
   первая же правка о нём не знающая. */

:root {
  --km-hub-ink: #2E2433;
  --km-hub-title: #3B2A47;
  --km-hub-muted: #766C7E;
  --km-hub-line: #EAE5EE;
  --km-hub-chip-line: #E2DBE7;
  --km-hub-chip-ink: #4A3E52;
  --km-hub-accent: #6B4C7C;
  --km-hub-soft: #EDE5F1;
  --km-hub-hover: #F3EEF6;
  --km-hub-link: #5E4270;
  --km-hub-red: #C8433A;
  --km-hub-red-deep: #A9362E;
  --km-hub-red-hover: #B23A32;
  --km-hub-seg: #EDE7F1;
  --km-hub-seg-ink: #5E5466;
  --km-hub-pin: #F1E9F5;
  --km-hub-pin-line: #E2D3EA;
  /* Закреплённый пост (доска pinned-v1): рамка темнее обычной, полоса «Закреплено» сверху. */
  --km-hub-pin-card-line: #D9C7E3;
  --km-hub-pin-strip: #F4EEF7;
  --km-hub-pin-strip-line: #EBE1F0;
  --km-hub-label: #F1EAF4;
  --km-hub-badge: #F1EDF4;
  --km-hub-line-soft: #F1EDF4;
  --km-hub-field: #FAF8FB;
  /* «Отчёт за эту неделю опубликован» — блок занятия «Ваш отчёт за неделю» (прототип `design/bloki-v1.html`). */
  --km-hub-done: #2E7D5B;
  --km-hub-done-bg: #EEF7F2;
  --km-hub-done-line: #CFE7DA;
  /* Найденное слово в поиске (доска search-v1): тёплая подсветка, как маркером. */
  --km-hub-mark: #FBE7B4;
  --km-hub-track: #ECE6F0;
  /* «Где опубликовать» (доска where-publish): выключенный переключатель и пунктир «+ Выбрать группы». */
  --km-hub-switch-off: #D9D3DE;
  --km-hub-dash: #C9B8D4;
  /* Контур кнопки «Подробнее о встрече» (образец Алены 09.10, документ 1.31). */
  --km-hub-box-line: #D3CCD6;
  --km-hub-dark: rgba(46, 36, 51, 0.55);
  --km-hub-font: 'KM Manrope', Arial, sans-serif;
  --km-hub-display: 'KM Oswald', Arial, sans-serif;
  /* Название в карточке: статья «Ключей» в ленте и встреча в «Ближайшей встрече» — одним кеглем
     (слово Алены 10.10.2026: «посмотри какой размер шрифта в названии репоста — и поставь такой же»). */
  --km-hub-card-title-size: 20px;
  --km-hub-card-title-line: 1.25;
  /* Статья «Ключей» (этап 7, доска feed-v2): заливка «Читать на «Ключах»» и знак «КМ» в шапке. */
  --km-hub-read: #E7D3E8;
  --km-hub-site-ink: #C25A2A;
  /* Гость с «Ключей» — серая иконка, как у человека без фото на «Ключах» (документ сообщества 1.71). */
  --km-hub-guest: #D5D3D7;
  --km-hub-guest-ink: #FFFFFF;
  /* Карточка трансляции, вариант В (доска broadcast-card-v4): листок календаря, «Сейчас в эфире», описание, «Уже зарегистрировались». */
  --km-hub-leaf: #F3EDF7;
  --km-hub-leaf-rec: #F1EFF3;
  --km-hub-leaf-rec-day: #6F6676;
  --km-hub-live-ink: #B23A32;
  --km-hub-cast-text: #4A3E52;
  --km-hub-proof: #5A4F61;
  /* Подсказка в поле комментария и значок смайлов рядом — одним серым (слово Алены 11.10.2026). Значение — подсказки
     темы BuddyBoss (`theme.min.css`: `textarea::placeholder { color: #c3c6c9 }`): на сайте обучения вид не меняется,
     а на «Ключах» (другая тема) подсказка и значок совпадают так же. */
  --km-hub-hint: #C3C6C9;

  /* Ярлыки тем — готовый набор (`Hub\RubricColors`); первые четыре с досок. */
  --km-hub-tag-lilac-bg: #EDE5F1; --km-hub-tag-lilac-ink: #4A3060;
  --km-hub-tag-mint-bg: #DDF2EA;  --km-hub-tag-mint-ink: #23664F;
  --km-hub-tag-sky-bg: #DFEAF7;   --km-hub-tag-sky-ink: #2F527D;
  --km-hub-tag-peach-bg: #FBE3D5; --km-hub-tag-peach-ink: #8A4A28;
  --km-hub-tag-rose-bg: #F8E1E8;  --km-hub-tag-rose-ink: #8A2F4A;
  --km-hub-tag-sand-bg: #F4EBCB;  --km-hub-tag-sand-ink: #6B5414;
  --km-hub-tag-teal-bg: #D9EEEF;  --km-hub-tag-teal-ink: #1F5E64;
  --km-hub-tag-stone-bg: #ECEDF1; --km-hub-tag-stone-ink: #464B57;

  /* «Сегодня активнее всех» («Звёзды курса» 1.28, 6.10; макет `design/reyting-segodnya-v1.dc.html`): цифра места
     и подсветка своей строки — та же, что у ближайшей встречи (`km-leafs__row--next`). */
  --km-hub-place: #9A86A8;
  --km-hub-mine: #F6F1F8;
}

/* Ярлык — одной строкой и не шире места: название темы бывает до 60 знаков (`Rubrics`), и длинное
   уводило ярлык за край экрана на 375 (стенд «Темы», 09.10.2026). Не влезшее — многоточием; поэтому
   блок, а не флекс: у флекс-контейнера многоточия не бывает. `overflow: hidden` заодно даёт ярлыку
   сжиматься в шапке поста — у элемента флекса с ним нижняя граница ширины нулевая. */
.km-hub-tag {
  display: inline-block;
  max-width: 100%;
  padding: 5px 10px;
  border-radius: 6px;
  overflow: hidden;
  font-family: var(--km-hub-font);
  font-size: 13px;
  font-weight: 700;
  line-height: 1.3;
  text-overflow: ellipsis;
  vertical-align: middle;
  white-space: nowrap;
}
.km-hub-tag--lilac { background: var(--km-hub-tag-lilac-bg); color: var(--km-hub-tag-lilac-ink); }
.km-hub-tag--mint { background: var(--km-hub-tag-mint-bg); color: var(--km-hub-tag-mint-ink); }
.km-hub-tag--sky { background: var(--km-hub-tag-sky-bg); color: var(--km-hub-tag-sky-ink); }
.km-hub-tag--peach { background: var(--km-hub-tag-peach-bg); color: var(--km-hub-tag-peach-ink); }
.km-hub-tag--rose { background: var(--km-hub-tag-rose-bg); color: var(--km-hub-tag-rose-ink); }
.km-hub-tag--sand { background: var(--km-hub-tag-sand-bg); color: var(--km-hub-tag-sand-ink); }
.km-hub-tag--teal { background: var(--km-hub-tag-teal-bg); color: var(--km-hub-tag-teal-ink); }
.km-hub-tag--stone { background: var(--km-hub-tag-stone-bg); color: var(--km-hub-tag-stone-ink); }

/* Подложки у страницы нет — прозрачная, фон даёт тема (слово Алены 8 октября 2026). */
.km-page.km-hub {
  padding-top: 32px;
  padding-bottom: 64px;
  background: transparent;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
}
/* Страница ленты шире общего предела страниц (1180): середина 604 → 684 при тех же боковых 220 и 260 (документ
   сообщества 1.61, слово Алены 10.10.2026). Профиль и прочие страницы сообщества — в прежних 1180. */
.km-page.km-hub--feed { max-width: 1260px; }
.km-hub .km-hub__inner { max-width: 1220px; margin: 0 auto; display: flex; flex-direction: column; gap: 28px; container: km-hub / inline-size; }
.km-hub .km-hub__head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 16px; margin: 0; }
.km-hub .km-hub__titles { display: flex; flex-direction: column; gap: 6px; }
.km-hub p.km-hub__eyebrow {
  margin: 0;
  font-size: 12px;
  font-weight: 700;
  line-height: 1.4;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--km-hub-muted);
}
/* «Сообщество КМ» — буквами как написано, толщина 500 (слово Алены 8 октября 2026). */
.km-hub h1.km-hub__title {
  margin: 0;
  font-family: var(--km-hub-display);
  font-size: 40px;
  font-weight: 500;
  line-height: 1.1;
  letter-spacing: normal;
  text-transform: none;
  color: var(--km-hub-title);
}
/*
 * Ряд колонок — сеткой с заданными ширинами, а не гибкой строкой (документ сообщества, «Страница открывается сразу
 * целиком»; задача Алены 13.10.2026). Гибкая строка отдавала ленте всё свободное место, и пока правая колонка не пришла
 * (браузер рисует страницу по мере прихода HTML), лента стояла во всю ширину — 972 вместо 684 — и сжималась, когда
 * колонка приходила. Сетка держит место колонки занятым с первого кадра; ширины те же, что давала строка: 220 и 260
 * (расхождение — доли пикселя). Как у плеера занятия (`.km-player`) и трансляции курса (`.km-cast-layout`).
 * Колонка в разметке стоит раньше ленты, а на экране — справа: место у каждой назначено.
 */
.km-hub .km-hub__cols { display: grid; grid-template-columns: 220px minmax(0, 1fr) 260px; flex-wrap: wrap; gap: 28px; align-items: start; }
.km-hub .km-hub__cols > .km-hub-nav { grid-column: 1; grid-row: 1; }
.km-hub .km-hub__cols > .km-hub-main { grid-column: 2; grid-row: 1; }
.km-hub .km-hub__cols > .km-hub-aside { grid-column: 3; grid-row: 1; }
/* «Участники» (доска `members-v1`): колонки справа нет, список и её место. Решает пометка ряда, которую ставит сервер
   и переключает скрипт вместе со списком, а не то, дошла ли колонка: иначе ширина ленты снова зависела бы от прихода. */
.km-hub .km-hub__cols.km-hub__cols--wide > .km-hub-main { grid-column: 2 / -1; }
.km-hub .km-hub-icon { width: 18px; height: 18px; flex: none; }

/* Колонка «Лента и группы» */
.km-hub .km-hub-nav { flex: 1 1 220px; max-width: 240px; display: flex; flex-direction: column; gap: 26px; }
.km-hub .km-hub-nav__block { display: flex; flex-direction: column; gap: 4px; }
.km-hub p.km-hub-nav__head {
  margin: 0;
  padding: 0 12px 6px;
  font-size: 12px;
  font-weight: 700;
  line-height: 1.4;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--km-hub-muted);
}
.km-hub p.km-hub-nav__note { margin: 0; padding: 0 12px; font-size: 14px; line-height: 1.5; color: var(--km-hub-muted); }
.km-hub button.km-hub-nav__item,
.km-hub button.km-hub-nav__item:focus,
.km-hub button.km-hub-nav__item:active {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 44px;
  margin: 0;
  padding: 8px 12px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  box-shadow: none;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 15px;
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: normal;
  text-align: left;
  text-transform: none;
  cursor: pointer;
}
.km-hub button.km-hub-nav__item:hover { border: 0; background: var(--km-hub-hover); box-shadow: none; color: var(--km-hub-ink); }
.km-hub button.km-hub-nav__item.km-hub-nav__item--on,
.km-hub button.km-hub-nav__item.km-hub-nav__item--on:hover { background: var(--km-hub-soft); font-weight: 700; }
.km-hub button.km-hub-nav__item:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub .km-hub-nav__label { flex: 1; min-width: 0; overflow-wrap: anywhere; }

/* Аватарка группы; без картинки — буквы названия */
.km-hub-avatar { flex: none; display: block; object-fit: cover; }
.km-hub-avatar--sm { width: 32px; height: 32px; border-radius: 8px; }
.km-hub-avatar--xs { width: 28px; height: 28px; border-radius: 7px; }
.km-hub-avatar--letters {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--km-hub-soft);
  color: var(--km-hub-link);
  font-family: var(--km-hub-font);
  font-size: 12px;
  font-weight: 700;
  line-height: 1;
}

/* Лента */
.km-hub .km-hub-main { flex: 999 1 560px; min-width: 0; display: flex; flex-direction: column; gap: 18px; }
.km-hub .km-hub-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.km-hub button.km-hub-plaque,
.km-hub button.km-hub-plaque:focus,
.km-hub button.km-hub-plaque:active {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: 100%;
  min-height: 40px;
  margin: 0;
  padding: 0 8px 0 6px;
  border: 0;
  border-radius: 10px;
  background: var(--km-hub-soft);
  box-shadow: none;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 15px;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: normal;
  text-align: left;
  text-transform: none;
  cursor: pointer;
}
.km-hub button.km-hub-plaque:hover { border: 0; background: var(--km-hub-chip-line); box-shadow: none; color: var(--km-hub-ink); }
.km-hub button.km-hub-plaque:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub .km-hub-plaque__title { min-width: 0; overflow-wrap: anywhere; }
.km-hub .km-hub-plaque__face { display: flex; flex: none; }
.km-hub .km-hub-bar[hidden] { display: none; }
.km-hub .km-hub-plaque__x { width: 24px; height: 24px; border-radius: 6px; display: flex; align-items: center; justify-content: center; flex: none; color: var(--km-hub-muted); }
.km-hub .km-hub-plaque__x .km-hub-icon { width: 14px; height: 14px; }

.km-hub .km-hub-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.km-hub button.km-hub-chip,
.km-hub button.km-hub-chip:focus,
.km-hub button.km-hub-chip:active {
  flex: none;
  height: 40px;
  margin: 0;
  padding: 0 16px;
  border: 1px solid var(--km-hub-chip-line);
  border-radius: 10px;
  background: #fff;
  box-shadow: none;
  color: var(--km-hub-chip-ink);
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: normal;
  text-align: center;
  text-transform: none;
  white-space: nowrap;
  cursor: pointer;
}
.km-hub button.km-hub-chip:hover { border-color: var(--km-hub-accent); background: #fff; box-shadow: none; color: var(--km-hub-chip-ink); }
.km-hub button.km-hub-chip[aria-pressed="true"],
.km-hub button.km-hub-chip[aria-pressed="true"]:hover { border-color: var(--km-hub-accent); background: var(--km-hub-accent); color: #fff; }
.km-hub button.km-hub-chip:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }

.km-hub p.km-hub-empty {
  margin: 0;
  padding: 18px;
  border: 1px solid var(--km-hub-line);
  border-radius: 14px;
  background: #fff;
  font-size: 15px;
  line-height: 1.5;
  color: var(--km-hub-muted);
}

/* Кнопка «Написать пост» и строка-приглашение (доски feed-v2, group-v3) */
.km-hub button.km-hub-write,
.km-hub button.km-hub-write:focus,
.km-hub button.km-hub-write:active,
.km-hub a.km-hub-write,
.km-hub a.km-hub-write:visited,
.km-hub a.km-hub-write:focus,
.km-hub a.km-hub-write:active {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 46px;
  margin: 0;
  padding: 0 22px;
  border: 0;
  border-radius: 10px;
  background: var(--km-hub-red);
  box-shadow: none;
  color: #fff;
  font-family: var(--km-hub-font);
  font-size: 15px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  cursor: pointer;
}
.km-hub button.km-hub-write:hover,
.km-hub a.km-hub-write:hover { border: 0; background: var(--km-hub-red-deep); box-shadow: none; color: #fff; }
.km-hub button.km-hub-write:focus-visible,
.km-hub a.km-hub-write:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
/* Кнопка перехода в шапке профиля (документ 1.64) — та же «Написать пост», только ссылкой: без подчёркивания. */
.km-hub a.km-hub-write { box-sizing: border-box; text-decoration: none; }
/* Белая кнопка шапки — «Настройки уведомлений» (доска notifications-v1, части 2–3). */
.km-hub a.km-hub-write.km-hub-write--plain,
.km-hub a.km-hub-write.km-hub-write--plain:visited,
.km-hub a.km-hub-write.km-hub-write--plain:focus,
.km-hub a.km-hub-write.km-hub-write--plain:active { height: 42px; padding: 0 18px; border: 1px solid var(--km-hub-chip-line); background: #fff; color: var(--km-hub-ink); font-size: 14px; }
.km-hub a.km-hub-write.km-hub-write--plain:hover { border: 1px solid var(--km-hub-chip-line); background: var(--km-hub-hover); color: var(--km-hub-ink); }
.km-hub button.km-hub-prompt,
.km-hub button.km-hub-prompt:focus,
.km-hub button.km-hub-prompt:active {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  margin: 0;
  padding: 14px 18px;
  border: 1px solid var(--km-hub-line);
  border-radius: 14px;
  background: #fff;
  box-shadow: none;
  color: var(--km-hub-muted);
  font-family: var(--km-hub-font);
  font-size: 15px;
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: normal;
  text-align: left;
  text-transform: none;
  cursor: pointer;
}
.km-hub button.km-hub-prompt:hover { border-color: var(--km-hub-chip-line); background: #fff; box-shadow: none; color: var(--km-hub-muted); }
.km-hub button.km-hub-prompt:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub .km-hub-prompt__text { flex: 1; min-width: 0; }

/* Человек — кружок: фото из профиля или инициалы */
.km-hub-person { flex: none; display: block; width: 40px; height: 40px; border-radius: 50%; object-fit: cover; }
.km-hub-person--md { width: 38px; height: 38px; }
/*
 * Фото — тоже кружок, и силой селектора, а не порядком: на «Ключах» страницу собирает Elementor, и его
 * `.elementor img { border-radius: 0 }` (0,1,1) сильнее `.km-hub-person` (0,1,0) — фото людей в «Обсуждении» стояли
 * квадратами, а серый значок и буквы (не картинки) оставались кругами (боевой «Ключей», 11.10.2026). (0,3,1) —
 * с запасом против правил тем вида `.entry-content img` и `.elementor-widget img`. Стенд «Ключей» стоит в той же
 * обвязке Elementor (`build-stand-discuss.php`).
 */
.km-hub img.km-hub-person.km-hub-person { border-radius: 50%; }
.km-hub-person--guest {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--km-hub-guest);
  color: var(--km-hub-guest-ink);
}
.km-hub-person--guest svg { width: 60%; height: 60%; }
.km-hub-person--letters {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--km-hub-soft);
  color: var(--km-hub-link);
  font-family: var(--km-hub-font);
  font-size: 13px;
  font-weight: 700;
  line-height: 1;
}

/* Поток в группе — «Вся группа / Мой поток» (доска group-v3) */
.km-hub .km-hub-seg { display: inline-flex; flex-wrap: wrap; gap: 3px; padding: 3px; border-radius: 11px; background: var(--km-hub-seg); }
.km-hub button.km-hub-seg__item,
.km-hub button.km-hub-seg__item:focus,
.km-hub button.km-hub-seg__item:active {
  height: 34px;
  margin: 0;
  padding: 0 14px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  box-shadow: none;
  color: var(--km-hub-seg-ink);
  font-family: var(--km-hub-font);
  font-size: 13px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  white-space: nowrap;
  cursor: pointer;
}
.km-hub button.km-hub-seg__item:hover { border: 0; background: rgba(255, 255, 255, 0.55); box-shadow: none; color: var(--km-hub-seg-ink); }
.km-hub button.km-hub-seg__item[aria-pressed="true"],
.km-hub button.km-hub-seg__item[aria-pressed="true"]:hover { background: #fff; color: var(--km-hub-title); box-shadow: 0 1px 3px rgba(59, 42, 71, 0.14); }
.km-hub button.km-hub-seg__item:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }

/* Темы и порядок в одной строке */
.km-hub .km-hub-tools { display: flex; align-items: flex-start; gap: 12px; }
/* Темы — одной строкой, вбок прокруткой, и на компьютере, как в профиле (документ сообщества 1.61): вторым рядом
   не переносятся, кнопка порядка остаётся справа на месте. Одно правило на ленту и профиль. */
.km-hub .km-hub-tools .km-hub-chips { flex: 1; min-width: 0; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
.km-hub .km-hub-tools .km-hub-chips::-webkit-scrollbar { display: none; }
.km-hub .km-hub-sort { position: relative; flex: none; }
.km-hub .km-hub-sort__button,
.km-hub .km-hub-menu__button {
  display: flex;
  align-items: center;
  justify-content: center;
  list-style: none;
  cursor: pointer;
}
.km-hub .km-hub-sort__button::-webkit-details-marker,
.km-hub .km-hub-menu__button::-webkit-details-marker { display: none; }
/* Своя «коробка»: `summary` наследует её от служебного слота `details` — content-box, и тема (`* { box-sizing: inherit }`)
 * делала кнопку 42 вместо 40, на 2 px выше тем рядом (та же причина, что у подсветки пунктов, 1.477.0). */
.km-hub .km-hub-sort__button { box-sizing: border-box; width: 40px; height: 40px; border: 1px solid var(--km-hub-line); border-radius: 10px; background: #fff; color: var(--km-hub-ink); }
.km-hub .km-hub-sort[open] .km-hub-sort__button { border-color: var(--km-hub-accent); }
.km-hub .km-hub-sort__button .km-hub-icon { width: 20px; height: 20px; }
.km-hub .km-hub-sort__list,
.km-hub .km-hub-menu__list {
  position: absolute;
  right: 0;
  z-index: 5;
  display: flex;
  flex-direction: column;
  padding: 6px;
  border: 1px solid var(--km-hub-line);
  border-radius: 12px;
  background: #fff;
}
.km-hub .km-hub-sort__list { top: 48px; width: 250px; box-shadow: 0 8px 24px rgba(59, 42, 71, 0.14); }
.km-hub .km-hub-menu__list { top: 40px; width: 280px; box-shadow: 0 8px 24px rgba(59, 42, 71, 0.12); }
.km-hub button.km-hub-sort__item,
.km-hub button.km-hub-sort__item:focus,
.km-hub button.km-hub-sort__item:active,
.km-hub button.km-hub-menu__item,
.km-hub button.km-hub-menu__item:focus,
.km-hub button.km-hub-menu__item:active {
  display: flex;
  align-items: center;
  gap: 10px;
  box-sizing: border-box;
  width: 100%;
  height: 44px;
  margin: 0;
  padding: 0 12px;
  border: 0;
  border-radius: 8px;
  background: none;
  box-shadow: none;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 500;
  line-height: 1;
  letter-spacing: normal;
  text-align: left;
  text-transform: none;
  cursor: pointer;
}
.km-hub button.km-hub-sort__item:hover,
.km-hub button.km-hub-menu__item:hover { border: 0; background: var(--km-hub-hover); box-shadow: none; color: var(--km-hub-ink); }
.km-hub button.km-hub-sort__item[aria-checked="true"],
.km-hub button.km-hub-sort__item[aria-checked="true"]:hover { background: var(--km-hub-pin); font-weight: 700; }
.km-hub button.km-hub-menu__item.km-hub-menu__item--danger,
.km-hub button.km-hub-menu__item.km-hub-menu__item--danger:hover { color: var(--km-danger); }
.km-hub button.km-hub-sort__item:focus-visible,
.km-hub button.km-hub-menu__item:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: -2px; }
.km-hub .km-hub-menu__line { height: 1px; margin: 4px 6px; background: var(--km-hub-line-soft); }

/* Лента и карточка поста (доски feed-v2, group-v3, mobile-v3) */
.km-hub .km-hub-feed { display: flex; flex-direction: column; gap: 18px; }
.km-hub-post { border: 1px solid var(--km-hub-line); border-radius: 14px; background: #fff; }
.km-hub .km-hub-post__body { display: flex; flex-direction: column; gap: 12px; padding: 16px 18px; }
.km-hub .km-hub-post__head { display: flex; align-items: center; gap: 12px; min-width: 0; }
.km-hub .km-hub-post__face { position: relative; flex: none; width: 40px; height: 40px; }
.km-hub .km-hub-post__avatar { display: block; width: 40px; height: 40px; border-radius: 10px; object-fit: cover; }
.km-hub .km-hub-post__avatar--letters { display: flex; align-items: center; justify-content: center; background: var(--km-hub-soft); color: var(--km-hub-link); font-size: 13px; font-weight: 700; }
.km-hub .km-hub-post__badge {
  position: absolute;
  right: -4px;
  bottom: -4px;
  width: 20px;
  height: 20px;
  border: 2px solid #fff;
  border-radius: 50%;
  object-fit: cover;
  box-sizing: content-box;
}
.km-hub .km-hub-post__badge--letters { display: flex; align-items: center; justify-content: center; background: var(--km-hub-badge); color: var(--km-hub-ink); font-size: 8px; font-weight: 700; line-height: 1; }
.km-hub .km-hub-post__who { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.km-hub .km-hub-post__place { font-size: 15px; font-weight: 700; line-height: 1.35; color: var(--km-hub-ink); overflow-wrap: anywhere; }
.km-hub .km-hub-post__meta { font-size: 13px; line-height: 1.4; color: var(--km-hub-muted); }
.km-hub .km-hub-post__author { font-weight: 600; color: var(--km-hub-link); }
.km-hub .km-hub-post__when { white-space: nowrap; }
/* Время — ссылка на пост (документ сообщества 1.11): вид как у времени, подчёркивание только под курсором. */
.km-hub a.km-hub-post__permalink,
.km-hub a.km-hub-post__permalink:visited,
.km-hub a.km-hub-post__permalink:hover,
.km-hub a.km-hub-post__permalink:focus,
.km-hub a.km-hub-post__permalink:active { color: inherit; font: inherit; text-decoration: none; box-shadow: none; }
.km-hub a.km-hub-post__permalink:hover { text-decoration: underline; }
.km-hub .km-hub-post__ago-short,
.km-hub .km-hub-post__metatag,
.km-hub .km-hub-post__tag-below { display: none; }
.km-hub .km-hub-post__tag { flex: none; max-width: 40%; overflow: hidden; text-overflow: ellipsis; }
.km-hub .km-hub-menu { position: relative; flex: none; }
.km-hub .km-hub-menu__button { width: 36px; height: 36px; border-radius: 8px; color: var(--km-hub-muted); }
.km-hub .km-hub-menu__button:hover { background: var(--km-hub-hover); }
.km-hub .km-hub-menu__button .km-hub-icon { width: 20px; height: 20px; }
.km-hub p.km-hub-post__stream { margin: 0; font-size: 14px; line-height: 1.4; color: var(--km-hub-muted); }
/* Метка команды «Отчёт к занятию 1.2» у привязанного поста участника (звёзды курса 1.20, раздел 2). */
.km-hub p.km-hub-post__report { margin: 0; font-size: 14px; font-weight: 600; line-height: 1.4; color: var(--km-hub-tag-lilac-ink); }
/* Заголовок поста и название эфира в правой колонке — толщина 400 (слово Алены 8 октября 2026). */
.km-hub h2.km-hub-post__title {
  margin: 0;
  font-family: var(--km-hub-display);
  font-size: 22px;
  font-weight: 400;
  line-height: 1.25;
  letter-spacing: normal;
  text-transform: none;
  color: var(--km-hub-title);
  overflow-wrap: anywhere;
}
.km-hub .km-hub-post__text { font-size: 15px; line-height: 1.65; color: var(--km-hub-ink); overflow-wrap: anywhere; }
/* Оформление текста поста — то, что ставит поле с панелью (документ сообщества 1.7):
   отступ отношением соседей, как в поле письма, а не полем у каждого блока. */
.km-hub .km-hub-post__text > * { margin: 0; }
.km-hub .km-hub-post__text > * + * { margin-top: 10px; }
.km-hub .km-hub-post__text h3 { padding: 0; font-family: var(--km-hub-font); font-size: 17px; font-weight: 700; line-height: 1.35; letter-spacing: normal; text-transform: none; color: var(--km-hub-title); }
.km-hub .km-hub-post__text ul,
.km-hub .km-hub-post__text ol { padding: 0 0 0 22px; }
.km-hub .km-hub-post__text ul { list-style: disc; }
.km-hub .km-hub-post__text ol { list-style: decimal; }
.km-hub .km-hub-post__text li { margin: 0; padding: 0; }
.km-hub .km-hub-post__text li + li { margin-top: 4px; }
.km-hub .km-hub-post__text strong,
.km-hub .km-hub-post__text b { font-weight: 700; }
.km-hub .km-hub-post__text em,
.km-hub .km-hub-post__text i { font-style: italic; }
.km-hub .km-hub-field__write { min-width: 0; }
.km-hub .km-hub-post__text a { color: var(--km-hub-link); text-decoration: underline; }
.km-hub .km-hub-post .km-hub-status:empty { display: none; }

/* «Подгружаем следующие посты…» и возврат к ленте */
.km-hub p.km-hub-more { display: flex; align-items: center; justify-content: center; gap: 10px; margin: 0; padding: 8px 0; font-size: 14px; color: var(--km-hub-muted); }
.km-hub p.km-hub-more[hidden] { display: none; }
.km-hub .km-hub-more__spin { width: 16px; height: 16px; border: 2px solid var(--km-hub-chip-line); border-top-color: var(--km-hub-accent); border-radius: 50%; animation: km-hub-spin 0.9s linear infinite; }
@keyframes km-hub-spin { to { transform: rotate(360deg); } }
.km-hub button.km-hub-back,
.km-hub button.km-hub-back:focus,
.km-hub button.km-hub-back:active {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 40px;
  margin: 0;
  padding: 0 14px 0 10px;
  border: 1px solid var(--km-hub-line);
  border-radius: 10px;
  background: #fff;
  box-shadow: none;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  cursor: pointer;
}
.km-hub button.km-hub-back:hover { border-color: var(--km-hub-chip-line); background: var(--km-hub-hover); box-shadow: none; color: var(--km-hub-ink); }

/* Правая колонка — «Ближайший эфир» */
.km-hub .km-hub-aside { flex: 1 1 260px; max-width: 280px; display: flex; flex-direction: column; gap: 18px; }
.km-hub .km-hub-aside[hidden] { display: none; }
/*
 * Карточка «Ближайшие встречи» (документ сообщества 1.110–1.111, доска `nearest-meetings-v1`; до 1.481.0 — «Ближайшая
 * встреча» по образцу 09.10): рамка — общая карточка колонки, строки — `km-leafs` (общие с «Расписанием» в колонке
 * трансляции курса). Поля слева и справа — 12 вместо 20 (1.111: «чтобы названию и времени хватало места в узкой
 * колонке»; ширина колонки прежняя, 260): под текст 176 px вместо 160, «Завтра, пятница · 19:00 МСК» (173) — в строку.
 */
.km-hub .km-hub-box { display: flex; flex-direction: column; gap: 16px; padding: 20px; border: 1px solid var(--km-hub-line); border-radius: 14px; background: #fff; }
.km-hub .km-hub-meet,
.km-hub .km-hub-today { gap: 14px; --km-leafs-side: 12px; padding-right: var(--km-leafs-side); padding-left: var(--km-leafs-side); }
/* «Практическое занятие 2» — в одну строку на 1280 (документ сообщества 1.112, слово Алены 12.10.2026; ширину колонки
   не трогать, только эту карточку). Не хватало 3,2 px: название 179,3 при 176,1 под текст (замер стенда 12.10). Зазор
   листок—название 12 → 8 и листок 46 → 44 дают 182,1 — запас 2,8 px на другой движок (Safari рисует шире). Листок по-
   прежнему по верхнему краю названия: высота и сдвиг сверху не менялись. Число в конце названия держится с предыдущим
   словом неразрывным пробелом (`HubAside::keep_number()`). */
.km-hub .km-hub-meet .km-leafs__row { gap: 8px; }
.km-hub .km-hub-meet .km-leafs__leaf { width: 44px; }
.km-hub p.km-hub-meet__head { margin: 0; }

/*
 * «Сегодня активнее всех» — под «Ближайшими встречами» в колонке группы курса со звёздами («Звёзды курса» 1.28–1.29,
 * 6.10; макет `design/reyting-segodnya-v1.dc.html`). **Поля — те же, что у «Ближайших встреч», и теми же правилами,
 * а не своими числами** (решение Алены 15.10.2026): коробка `km-hub-box`, бока — `--km-leafs-side` (общее правило
 * `.km-hub-meet, .km-hub-today` выше), подпись без своих полей, строки — отрицательным полем на всю ширину и своим
 * полем `--km-leafs-side` обратно, как `km-leafs__row`; между строками — как у встреч. Подпись встаёт на линию
 * «Ближайших встреч», цифра места — на линию листков, звёзды кончаются там же, где текст встреч; встреч нет — поля
 * те же. Строка: место цифрой, фото 30, имя — до двух строк, дальше многоточие; место, фото и звёзды — по середине
 * строки; своя — подложкой, как ближайшая встреча, и «Вы». Под курсором ничего не движется.
 */
.km-hub p.km-hub-today__head { margin: 0; }
.km-hub ol.km-hub-today__list { display: flex; flex-direction: column; gap: 6px; margin: 0; padding: 0; list-style: none; }
.km-hub li.km-hub-today__row { display: flex; align-items: center; gap: 8px; margin: 0 calc(-1 * var(--km-leafs-side, 0px)); padding: 8px var(--km-leafs-side, 0px); }
.km-hub li.km-hub-today__row--me { background: var(--km-hub-mine); }
.km-hub .km-hub-today__place { flex: none; width: 14px; font-size: 13px; font-weight: 800; line-height: 1; text-align: left; color: var(--km-hub-place); }
.km-hub li.km-hub-today__row--me .km-hub-today__place { color: var(--km-hub-link); }
.km-hub .km-hub-today__face { flex: none; width: 30px; height: 30px; border-radius: 50%; object-fit: cover; }
.km-hub .km-hub-today__face.km-hub-person--letters { font-size: 11px; }
.km-hub .km-hub-today__face--c1.km-hub-person--letters { background: var(--km-ava-1); color: var(--km-ava-1-ink); }
.km-hub .km-hub-today__face--c2.km-hub-person--letters { background: var(--km-ava-2); color: var(--km-ava-2-ink); }
.km-hub .km-hub-today__face--c3.km-hub-person--letters { background: var(--km-ava-3); color: var(--km-ava-3-ink); }
.km-hub .km-hub-today__face--c4.km-hub-person--letters { background: var(--km-ava-4); color: var(--km-ava-4-ink); }
.km-hub .km-hub-today__face--c5.km-hub-person--letters { background: var(--km-ava-5); color: var(--km-ava-5-ink); }
/* Сила (0,3,1), а не порядок: правило имени-кнопки ленты (`.km-hub button.km-hub-name`, `font: inherit`) стоит в таблице
   ниже, и при равной силе перебивало бы кегль — ничья по силе выигрывается порядком, а порядок меняет правка, которая
   о ней не знает. */
.km-hub .km-hub-today button.km-hub-today__name,
.km-hub .km-hub-today button.km-hub-today__name:hover,
.km-hub .km-hub-today button.km-hub-today__name:focus,
.km-hub .km-hub-today button.km-hub-today__name:active,
.km-hub .km-hub-today span.km-hub-today__name { flex: 1; min-width: 0; overflow: hidden; color: var(--km-hub-ink); font-size: 14px; font-weight: 600; line-height: 1.3; white-space: normal; text-align: left; }
/* Длинное имя — в две строки, не хватает двух — многоточие в конце второй (решение Алены 15.10.2026). Обрезка — на
   строчном куске внутри кнопки: у самой кнопки браузеры многострочную обрезку держат по-разному. */
.km-hub .km-hub-today span.km-hub-today__text { display: -webkit-box; overflow: hidden; overflow-wrap: anywhere; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; }
.km-hub .km-hub-today span.km-hub-today__name--me { font-weight: 700; }
.km-hub .km-hub-today__stars { flex: none; display: inline-flex; align-items: center; gap: 3px; color: var(--km-hub-link); font-size: 14px; font-weight: 800; line-height: 1; }
.km-hub .km-hub-today__star { flex: none; width: 15px; height: 15px; }
.km-hub a.km-hub-today__all,
.km-hub a.km-hub-today__all:visited,
.km-hub a.km-hub-today__all:focus { padding: 0; color: var(--km-hub-link); font-size: 14px; font-weight: 700; line-height: 1.4; text-decoration: none; }
.km-hub a.km-hub-today__all:hover { color: var(--km-hub-title); text-decoration: underline; text-underline-offset: 3px; }
/*
 * Карточка человека из «Сегодня активнее всех» (нажатие на имя или фото) — сразу под строкой, а не под лентой (снимок
 * боевого 15.10.2026). Скрипт кладёт окно в родителя того, на что нажали, — строку `li`; без своего положения у строки
 * окно считалось от всей страницы и уезжало вниз. Окно шире колонки (340 против 260): правым краем — по правому краю
 * колонки (строка выходит на поля карточки, `-1px` — её рамка), на средней ширине колонка стоит слева под меню — там
 * левым краем. На телефоне колонки нет, окно — снизу экрана, как везде.
 */
.km-hub li.km-hub-today__row { position: relative; }
.km-hub .km-hub-today .km-hub-pop { left: auto; right: -1px; }
@container km-hub (max-width: 1095.98px) {
  .km-hub .km-hub-today .km-hub-pop { left: -1px; right: auto; }
}

/*
 * Окно нового поста (доски composer-user, composer-admin-v4); тем же классом — окна модерации.
 * Слой — выше кнопки мессенджера Carrot Quest (у неё 2147483000, на всех страницах сайта): на снимке боевого
 * 10.10.2026 она стояла поверх затемнения и правого нижнего угла окна, где на телефоне в конце окна
 * «Опубликовать»; просмотр вложений — на слой выше. На телефоне этого хватает (снимки после выкладки 1.445.3).
 * На компьютере — нет: там окна лежат в слое темы, и кнопка с панелью администратора остаются над затемнением
 * при любом числе здесь (снимки 1280 и 800). Ничего нужного кнопка там не закрывает — окно 640 px по центру.
 */
body.km-hub-modal-open { overflow: hidden; }
.km-hub .km-hub-modal {
  position: fixed;
  inset: 0;
  z-index: 2147483001;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 40px 16px;
  background: rgba(46, 36, 51, 0.45);
  overflow-y: auto;
}
.km-hub .km-hub-modal[hidden] { display: none; }
.km-hub .km-hub-dialog { display: flex; flex-direction: column; width: 640px; max-width: 100%; border-radius: 16px; background: #fff; box-shadow: 0 12px 40px rgba(59, 42, 71, 0.18); overflow: hidden; }
.km-hub .km-hub-dialog__head { display: flex; align-items: center; gap: 12px; padding: 18px 22px; border-bottom: 1px solid var(--km-hub-line-soft); }
.km-hub h2.km-hub-dialog__title { flex: 1; margin: 0; font-family: var(--km-hub-display); font-size: 24px; font-weight: 500; line-height: 1.2; letter-spacing: normal; text-transform: none; color: var(--km-hub-title); }
.km-hub button.km-hub-dialog__close,
.km-hub button.km-hub-dialog__close:focus,
.km-hub button.km-hub-dialog__close:active {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  margin: 0;
  padding: 0;
  border: 1px solid var(--km-hub-line);
  border-radius: 10px;
  background: #fff;
  box-shadow: none;
  color: var(--km-hub-muted);
  line-height: 1;
  cursor: pointer;
}
.km-hub button.km-hub-dialog__close:hover { border-color: var(--km-hub-chip-line); background: var(--km-hub-hover); box-shadow: none; color: var(--km-hub-ink); }
.km-hub .km-hub-dialog__body { display: flex; flex-direction: column; gap: 18px; margin: 0; padding: 20px 22px; }
.km-hub .km-hub-dialog__foot { display: flex; align-items: center; justify-content: flex-end; gap: 10px; padding: 16px 22px; border-top: 1px solid var(--km-hub-line-soft); background: var(--km-hub-field); }
.km-hub .km-hub-field { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
.km-hub .km-hub-field[hidden] { display: none; }
.km-hub fieldset.km-hub-field--set { gap: 8px; margin: 0; padding: 0; border: 0; }
.km-hub .km-hub-field__label { margin: 0; padding: 0; font-size: 13px; font-weight: 700; line-height: 1.3; color: var(--km-hub-ink); }
.km-hub fieldset.km-hub-field--set > .km-hub-field__label { margin-bottom: 8px; }
.km-hub .km-hub-field__star { color: var(--km-danger); }
.km-hub .km-hub-field__input {
  box-sizing: border-box;
  width: 100%;
  height: 46px;
  margin: 0;
  padding: 0 14px;
  border: 1px solid var(--km-hub-line);
  border-radius: 10px;
  background: var(--km-hub-field);
  box-shadow: none;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 15px;
  line-height: 1.4;
}
.km-hub textarea.km-hub-field__input--text { height: auto; min-height: 140px; padding: 12px 14px; line-height: 1.6; resize: vertical; }
.km-hub .km-hub-field__input:focus { border-color: var(--km-hub-accent); outline: none; box-shadow: 0 0 0 3px var(--km-hub-soft); }
.km-hub .km-hub-field__hint { font-size: 13px; line-height: 1.5; color: var(--km-hub-muted); }
/* Подпись абзацем (окно привязки на занятии): поля абзаца страницы занятия ей не нужны. */
.km-hub p.km-hub-field__hint { margin: 0; }
.km-hub .km-hub-field__hint:empty { display: none; }
.km-hub .km-hub-field__error { font-size: 13px; line-height: 1.5; color: var(--km-danger); }
.km-hub .km-hub-field__error[hidden] { display: none; }
.km-hub .km-hub-picks { display: flex; flex-wrap: wrap; gap: 8px; }
/*
 * Тема в окне — плашкой по ширине окна: длинное название («Практики и открытия недели, которыми хочется поделиться»)
 * переносится внутри плашки, а не уезжает за край окна (стенд «Сделать постом», 13.10.2026). Сильнее общего правила
 * плашки и его состояний селектором, а не порядком.
 */
.km-hub .km-hub-picks button.km-hub-chip,
.km-hub .km-hub-picks button.km-hub-chip:focus,
.km-hub .km-hub-picks button.km-hub-chip:active { flex: 0 1 auto; max-width: 100%; height: auto; min-height: 40px; padding-top: 9px; padding-bottom: 9px; line-height: 1.3; white-space: normal; overflow-wrap: anywhere; }
.km-hub button.km-hub-button,
.km-hub button.km-hub-button:focus,
.km-hub button.km-hub-button:active {
  height: 46px;
  margin: 0;
  padding: 0 20px;
  border: 1px solid var(--km-hub-line);
  border-radius: 10px;
  background: #fff;
  box-shadow: none;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 15px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  cursor: pointer;
}
.km-hub button.km-hub-button:hover { border-color: var(--km-hub-chip-line); background: var(--km-hub-hover); box-shadow: none; color: var(--km-hub-ink); }
.km-hub button.km-hub-button.km-hub-button--primary,
.km-hub button.km-hub-button.km-hub-button--primary:focus,
.km-hub button.km-hub-button.km-hub-button--primary:active { padding: 0 24px; border-color: var(--km-hub-red); background: var(--km-hub-red); color: #fff; font-weight: 700; }
.km-hub button.km-hub-button.km-hub-button--primary:hover { border-color: var(--km-hub-red-deep); background: var(--km-hub-red-deep); color: #fff; }
.km-hub button.km-hub-button:disabled { opacity: 0.6; cursor: default; }
.km-hub button.km-hub-button:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }

/* Выбор ленты на телефоне — «Вся лента ▾» (доска mobile-v3) */
.km-hub .km-hub-pick { display: none; }
.km-hub .km-hub-pick__button {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 46px;
  padding: 0 14px;
  border: 1px solid var(--km-hub-line);
  border-radius: 12px;
  background: #fff;
  color: var(--km-hub-ink);
  font-size: 15px;
  font-weight: 700;
  line-height: 1.3;
  list-style: none;
  cursor: pointer;
}
.km-hub .km-hub-pick__button::-webkit-details-marker { display: none; }
.km-hub .km-hub-pick__label { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.km-hub .km-hub-pick[open] .km-hub-pick__button { border-color: var(--km-hub-accent); }
.km-hub .km-hub-pick__list {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-top: 6px;
  padding: 10px 6px;
  border: 1px solid var(--km-hub-line);
  border-radius: 12px;
  background: #fff;
  box-shadow: 0 8px 24px rgba(59, 42, 71, 0.14);
}

/* Вложения поста — доска media-layout («Картинки и видео в посте»), лента 608 px
   на компьютере; аудио и файл — доска feed-v2. Пропорции приходят атрибутами
   width/height у картинки и видео (данные, правило 13), раскладка — здесь. */
.km-hub .km-hub-icon--solid { stroke: none; }
.km-hub .km-hub-gallery { display: grid; gap: 4px; border-radius: 12px; overflow: hidden; }
.km-hub .km-hub-tile { position: relative; min-width: 0; min-height: 0; overflow: hidden; }
.km-hub .km-hub-tile--image { background: var(--km-hub-badge); }
.km-hub .km-hub-tile--video,
.km-hub .km-hub-tile--embed { background: var(--km-hub-ink); }
.km-hub .km-hub-tile__media { display: block; max-width: 100%; margin: 0; border: 0; border-radius: 0; box-shadow: none; }
.km-hub .km-hub-tile__size { display: none; }

/* По пропорциям: одна; две разные — рядом одной высоты, ширина каждой по её пропорциям */
.km-hub .km-hub-gallery--one-h,
.km-hub .km-hub-gallery--one-v,
.km-hub .km-hub-gallery--pair { display: flex; align-items: flex-start; }
.km-hub .km-hub-gallery--one-v { width: fit-content; max-width: 100%; }
.km-hub .km-hub-gallery--one-h .km-hub-tile { flex: 1 1 auto; }
.km-hub .km-hub-gallery--one-v .km-hub-tile,
.km-hub .km-hub-gallery--pair .km-hub-tile { flex: 0 1 auto; }
.km-hub .km-hub-gallery--one-h .km-hub-tile__media,
.km-hub .km-hub-gallery--one-h .km-hub-tile__size { display: block; width: 100%; height: auto; }
.km-hub .km-hub-gallery--one-v .km-hub-tile__media,
.km-hub .km-hub-gallery--one-v .km-hub-tile__size,
.km-hub .km-hub-gallery--pair .km-hub-tile__media,
.km-hub .km-hub-gallery--pair .km-hub-tile__size { display: block; max-width: 100%; height: auto; }

/* Заданные пропорции плиток: картинка заполняет плитку, видео — целиком */
.km-hub .km-hub-gallery--two-h .km-hub-tile__media,
.km-hub .km-hub-gallery--two-v .km-hub-tile__media,
.km-hub .km-hub-gallery--three-h .km-hub-tile__media,
.km-hub .km-hub-gallery--three-v .km-hub-tile__media,
.km-hub .km-hub-gallery--four-h .km-hub-tile__media,
.km-hub .km-hub-gallery--four-v .km-hub-tile__media { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.km-hub .km-hub-gallery .km-hub-tile--video .km-hub-tile__media { position: absolute; inset: 0; width: 100%; max-width: none; height: 100%; object-fit: contain; }
.km-hub .km-hub-gallery .km-hub-tile--embed .km-hub-tile__media,
.km-hub .km-hub-gallery .km-hub-tile__frame { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; margin: 0; border: 0; object-fit: cover; }
.km-hub .km-hub-gallery--two-h .km-hub-tile { aspect-ratio: 608 / 300; }
.km-hub .km-hub-gallery--two-v { grid-template-columns: 1fr 1fr; }
.km-hub .km-hub-gallery--two-v .km-hub-tile { aspect-ratio: 302 / 402; }
.km-hub .km-hub-gallery--three-h { grid-template-columns: 1fr 1fr; }
.km-hub .km-hub-gallery--three-h .km-hub-tile { aspect-ratio: 302 / 200; }
.km-hub .km-hub-gallery--four-h { grid-template-columns: repeat(3, 1fr); }
.km-hub .km-hub-gallery--four-h .km-hub-tile { aspect-ratio: 197 / 160; }
.km-hub .km-hub-gallery--three-h .km-hub-tile:first-child,
.km-hub .km-hub-gallery--four-h .km-hub-tile:first-child { grid-column: 1 / -1; aspect-ratio: 608 / 340; }
.km-hub .km-hub-gallery--three-v { grid-template-columns: 360fr 244fr; grid-template-rows: 1fr 1fr; aspect-ratio: 608 / 480; }
.km-hub .km-hub-gallery--four-v { grid-template-columns: 400fr 204fr; grid-template-rows: repeat(3, 1fr); aspect-ratio: 608 / 480; }
.km-hub .km-hub-gallery--three-v .km-hub-tile:first-child { grid-row: 1 / span 2; }
.km-hub .km-hub-gallery--four-v .km-hub-tile:first-child { grid-row: 1 / span 3; }
/* Одни видео — пропорции видео: 16:9 и 9:16 */
.km-hub .km-hub-gallery--video.km-hub-gallery--two-h .km-hub-tile,
.km-hub .km-hub-gallery--video.km-hub-gallery--three-h .km-hub-tile,
.km-hub .km-hub-gallery--video.km-hub-gallery--three-h .km-hub-tile:first-child,
.km-hub .km-hub-gallery--video.km-hub-gallery--four-h .km-hub-tile:first-child { aspect-ratio: 16 / 9; }
.km-hub .km-hub-gallery--video.km-hub-gallery--two-v .km-hub-tile { aspect-ratio: 9 / 16; }

/*
 * Квадратные — доска `media-squares.dc.html` (документ сообщества 1.10).
 * Размеры доски — для ленты 608 и промежутка 4: одна 480, две по 302, три —
 * 404 и две по 200, четыре — 2×2 по 302. Здесь они долями, и на узком экране
 * пропорции те же. Одна — по своим пропорциям, без обрезки; в ячейках
 * квадратная картинка обрезки не знает, прочие режутся по центру.
 */
.km-hub .km-hub-gallery--one-s { display: flex; width: calc(100% * 480 / 608); }
.km-hub .km-hub-gallery--one-s .km-hub-tile { flex: 1 1 auto; }
.km-hub .km-hub-gallery--one-s .km-hub-tile__media,
.km-hub .km-hub-gallery--one-s .km-hub-tile__size { display: block; width: 100%; height: auto; }
.km-hub .km-hub-gallery--two-s,
.km-hub .km-hub-gallery--four-s { grid-template-columns: 1fr 1fr; }
.km-hub .km-hub-gallery--two-s .km-hub-tile,
.km-hub .km-hub-gallery--four-s .km-hub-tile { aspect-ratio: 1 / 1; }
.km-hub .km-hub-gallery--three-s { grid-template-columns: 404fr 200fr; grid-template-rows: 1fr 1fr; aspect-ratio: 608 / 404; }
.km-hub .km-hub-gallery--three-s .km-hub-tile:first-child { grid-row: 1 / span 2; }
.km-hub .km-hub-gallery--two-s .km-hub-tile__media,
.km-hub .km-hub-gallery--three-s .km-hub-tile__media,
.km-hub .km-hub-gallery--four-s .km-hub-tile__media { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/* Кнопки на плитке: открыть на весь экран, смотреть, «+N» */
.km-hub button.km-hub-tile__open,
.km-hub button.km-hub-tile__open:focus,
.km-hub button.km-hub-tile__open:active,
.km-hub button.km-hub-tile__open:hover {
  display: block;
  width: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 400;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  cursor: zoom-in;
}
.km-hub .km-hub-gallery--two-h button.km-hub-tile__open,
.km-hub .km-hub-gallery--two-v button.km-hub-tile__open,
.km-hub .km-hub-gallery--three-h button.km-hub-tile__open,
.km-hub .km-hub-gallery--three-v button.km-hub-tile__open,
.km-hub .km-hub-gallery--four-h button.km-hub-tile__open,
.km-hub .km-hub-gallery--four-v button.km-hub-tile__open,
.km-hub .km-hub-gallery--two-s button.km-hub-tile__open,
.km-hub .km-hub-gallery--three-s button.km-hub-tile__open,
.km-hub .km-hub-gallery--four-s button.km-hub-tile__open { position: absolute; inset: 0; height: 100%; }
.km-hub button.km-hub-tile__open:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: -2px; }
.km-hub button.km-hub-tile__play,
.km-hub button.km-hub-tile__play:focus,
.km-hub button.km-hub-tile__play:active {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.92);
  box-shadow: none;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 400;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  cursor: pointer;
}
.km-hub button.km-hub-tile__play:hover { border: 0; background: #fff; box-shadow: none; color: var(--km-hub-accent); }
.km-hub button.km-hub-tile__play:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.km-hub .km-hub-tile__play .km-hub-icon { width: 24px; height: 24px; }
.km-hub .km-hub-tile__time,
.km-hub .km-hub-tile__label {
  position: absolute;
  padding: 3px 7px;
  border-radius: 6px;
  background: rgba(0, 0, 0, 0.45);
  color: #fff;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.3;
  pointer-events: none;
}
.km-hub .km-hub-tile__time { right: 10px; bottom: 8px; }
.km-hub .km-hub-tile__label { left: 10px; bottom: 8px; }
.km-hub .km-hub-tile--playing .km-hub-tile__play,
.km-hub .km-hub-tile--playing .km-hub-tile__time,
.km-hub .km-hub-tile--playing .km-hub-tile__label { display: none; }
.km-hub button.km-hub-tile__more,
.km-hub button.km-hub-tile__more:focus,
.km-hub button.km-hub-tile__more:active {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: var(--km-hub-dark);
  box-shadow: none;
  color: #fff;
  font-family: var(--km-hub-display);
  font-size: 28px;
  font-weight: 500;
  line-height: 1;
  letter-spacing: normal;
  cursor: pointer;
}
.km-hub button.km-hub-tile__more:hover { border: 0; background: rgba(46, 36, 51, 0.68); box-shadow: none; color: #fff; }

/* Аудио — открывается плеер (доска feed-v2) */
.km-hub .km-hub-audio { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border: 1px solid var(--km-hub-line); border-radius: 12px; background: #fff; }
.km-hub .km-hub-audio audio { display: none; }
.km-hub button.km-hub-audio__play,
.km-hub button.km-hub-audio__play:focus,
.km-hub button.km-hub-audio__play:active {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--km-hub-accent);
  box-shadow: none;
  color: #fff;
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 400;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  cursor: pointer;
}
.km-hub button.km-hub-audio__play:hover { border: 0; background: var(--km-hub-link); box-shadow: none; color: #fff; }
.km-hub button.km-hub-audio__play:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub .km-hub-audio__play .km-hub-icon { width: 16px; height: 16px; }
.km-hub .km-hub-audio__play .km-hub-icon + .km-hub-icon,
.km-hub .km-hub-audio--playing .km-hub-audio__play .km-hub-icon:first-child { display: none; }
.km-hub .km-hub-audio--playing .km-hub-audio__play .km-hub-icon + .km-hub-icon { display: block; }
.km-hub .km-hub-audio__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.km-hub .km-hub-audio__name { font-size: 14px; font-weight: 600; line-height: 1.3; overflow-wrap: anywhere; }
.km-hub progress.km-hub-audio__bar,
.km-hub progress.km-hub-attach__bar {
  display: block;
  width: 100%;
  height: 4px;
  margin: 0;
  border: 0;
  border-radius: 2px;
  background: var(--km-hub-track);
  color: var(--km-hub-accent);
  -webkit-appearance: none;
  appearance: none;
}
.km-hub progress.km-hub-audio__bar { cursor: pointer; }
.km-hub progress.km-hub-audio__bar::-webkit-progress-bar,
.km-hub progress.km-hub-attach__bar::-webkit-progress-bar { border-radius: 2px; background: var(--km-hub-track); }
.km-hub progress.km-hub-audio__bar::-webkit-progress-value,
.km-hub progress.km-hub-attach__bar::-webkit-progress-value { border-radius: 2px; background: var(--km-hub-accent); }
.km-hub progress.km-hub-audio__bar::-moz-progress-bar,
.km-hub progress.km-hub-attach__bar::-moz-progress-bar { border-radius: 2px; background: var(--km-hub-accent); }
.km-hub .km-hub-audio__time { flex: none; font-size: 13px; color: var(--km-hub-muted); font-variant-numeric: tabular-nums; }

/* Файл (доска feed-v2) и карточка ссылки */
.km-hub a.km-hub-file,
.km-hub a.km-hub-link { display: flex; align-items: center; gap: 12px; border: 1px solid var(--km-hub-line); border-radius: 12px; background: #fff; color: var(--km-hub-ink); text-decoration: none; }
.km-hub a.km-hub-file { padding: 12px 14px; }
.km-hub a.km-hub-link { align-items: stretch; overflow: hidden; }
.km-hub a.km-hub-file:hover,
.km-hub a.km-hub-link:hover { border-color: var(--km-hub-chip-line); background: var(--km-hub-hover); color: var(--km-hub-ink); text-decoration: none; }
.km-hub a.km-hub-file:focus-visible,
.km-hub a.km-hub-link:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub .km-hub-file__icon { flex: none; display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; border-radius: 10px; background: var(--km-hub-label); color: var(--km-hub-link); }
.km-hub .km-hub-file__icon .km-hub-icon { width: 20px; height: 20px; }
.km-hub a.km-hub-file > .km-hub-icon { color: var(--km-hub-muted); }
.km-hub .km-hub-file__main,
.km-hub .km-hub-link__main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.km-hub .km-hub-file__name { font-size: 14px; font-weight: 600; line-height: 1.35; overflow-wrap: anywhere; }
.km-hub .km-hub-file__meta { font-size: 13px; line-height: 1.4; color: var(--km-hub-muted); }
.km-hub .km-hub-link__image { flex: none; display: block; width: 120px; max-width: none; height: auto; min-height: 96px; margin: 0; border-radius: 0; object-fit: cover; background: var(--km-hub-badge); }
.km-hub .km-hub-link__main { gap: 3px; padding: 12px 14px; }
.km-hub .km-hub-link__site { font-size: 12px; font-weight: 600; line-height: 1.3; color: var(--km-hub-muted); overflow-wrap: anywhere; }
.km-hub .km-hub-link__title { font-size: 15px; font-weight: 700; line-height: 1.35; color: var(--km-hub-title); overflow-wrap: anywhere; }
.km-hub .km-hub-link__text { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; font-size: 13px; line-height: 1.45; color: var(--km-hub-muted); }

/* Просмотр на весь экран — «← 2 из 7 →» (доска media-layout) */
.km-hub .km-hub-viewer { position: fixed; inset: 0; z-index: 2147483002; display: flex; align-items: center; justify-content: center; padding: 64px 76px; background: rgba(20, 15, 24, 0.94); }
.km-hub .km-hub-viewer[hidden] { display: none; }
.km-hub .km-hub-viewer__stage { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; min-width: 0; min-height: 0; }
.km-hub .km-hub-viewer__stage img,
.km-hub .km-hub-viewer__stage video { display: block; width: auto; max-width: 100%; height: auto; max-height: 100%; margin: 0; border-radius: 0; box-shadow: none; object-fit: contain; }
.km-hub .km-hub-viewer__stage iframe,
.km-hub .km-hub-viewer__frame { display: block; width: 100%; max-width: 1100px; height: auto; aspect-ratio: 16 / 9; margin: 0; border: 0; }
.km-hub button.km-hub-viewer__close,
.km-hub button.km-hub-viewer__close:focus,
.km-hub button.km-hub-viewer__close:active,
.km-hub button.km-hub-viewer__nav,
.km-hub button.km-hub-viewer__nav:focus,
.km-hub button.km-hub-viewer__nav:active {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  box-shadow: none;
  color: #fff;
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 400;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  cursor: pointer;
}
.km-hub button.km-hub-viewer__close:hover,
.km-hub button.km-hub-viewer__nav:hover { border: 0; background: rgba(255, 255, 255, 0.24); box-shadow: none; color: #fff; }
.km-hub button.km-hub-viewer__close:focus-visible,
.km-hub button.km-hub-viewer__nav:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.km-hub button.km-hub-viewer__close { top: 12px; right: 12px; }
.km-hub button.km-hub-viewer__nav { top: calc(50% - 24px); }
.km-hub button.km-hub-viewer__nav--prev { left: 14px; }
.km-hub button.km-hub-viewer__nav--next { right: 14px; }
.km-hub button.km-hub-viewer__nav[hidden] { display: none; }
.km-hub .km-hub-viewer .km-hub-icon { width: 24px; height: 24px; }
.km-hub p.km-hub-viewer__count { position: absolute; left: 0; right: 0; bottom: 18px; margin: 0; text-align: center; color: rgba(255, 255, 255, 0.85); font-size: 14px; font-weight: 600; line-height: 1.3; }

/* Вложения в окне поста — кнопки «Картинки, Видео, Аудио, Файл, Ссылка» (доска composer-user) */
.km-hub .km-hub-attach { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.km-hub .km-hub-attach__tools { display: flex; flex-wrap: wrap; gap: 8px; }
.km-hub input.km-hub-attach__file { display: none; }
.km-hub button.km-hub-tool,
.km-hub button.km-hub-tool:focus,
.km-hub button.km-hub-tool:active {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 44px;
  margin: 0;
  padding: 0 14px;
  border: 1px solid var(--km-hub-line);
  border-radius: 10px;
  background: #fff;
  box-shadow: none;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 500;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  cursor: pointer;
}
.km-hub button.km-hub-tool:hover { border-color: var(--km-hub-chip-line); background: var(--km-hub-hover); box-shadow: none; color: var(--km-hub-ink); }
.km-hub button.km-hub-tool[aria-expanded="true"] { border-color: var(--km-hub-accent); background: var(--km-hub-soft); }
.km-hub button.km-hub-tool:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub .km-hub-attach__link { display: flex; gap: 8px; }
.km-hub .km-hub-attach__link[hidden] { display: none; }
.km-hub .km-hub-attach__link .km-hub-field__input { flex: 1; min-width: 0; }
.km-hub ul.km-hub-attach__list { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; list-style: none; }
.km-hub ul.km-hub-attach__list[hidden] { display: none; }
.km-hub li.km-hub-attach__item { position: relative; display: flex; align-items: center; gap: 10px; flex: 1 1 100%; min-width: 0; min-height: 52px; margin: 0; padding: 8px 46px 8px 10px; border: 1px solid var(--km-hub-line); border-radius: 10px; background: var(--km-hub-field); }
.km-hub li.km-hub-attach__item--image { flex: none; width: 96px; height: 96px; min-height: 0; padding: 0; overflow: hidden; background: var(--km-hub-badge); }
.km-hub .km-hub-attach__thumb { display: block; width: 100%; max-width: none; height: 100%; margin: 0; border-radius: 0; object-fit: cover; }
.km-hub .km-hub-attach__icon { flex: none; display: flex; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: 8px; background: var(--km-hub-label); color: var(--km-hub-link); }
.km-hub .km-hub-attach__text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.km-hub .km-hub-attach__name { overflow: hidden; font-size: 14px; font-weight: 600; line-height: 1.3; text-overflow: ellipsis; white-space: nowrap; }
.km-hub .km-hub-attach__meta { font-size: 12px; line-height: 1.3; color: var(--km-hub-muted); }
.km-hub .km-hub-attach__meta--error { color: var(--km-danger); white-space: normal; }
.km-hub button.km-hub-attach__x,
.km-hub button.km-hub-attach__x:focus,
.km-hub button.km-hub-attach__x:active {
  position: absolute;
  top: 10px;
  right: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.92);
  box-shadow: none;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 400;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  cursor: pointer;
}
.km-hub li.km-hub-attach__item--image button.km-hub-attach__x { top: 6px; right: 6px; }
.km-hub button.km-hub-attach__x:hover { border: 0; background: #fff; box-shadow: none; color: var(--km-danger); }
.km-hub button.km-hub-attach__x:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub .km-hub-attach__x .km-hub-icon { width: 14px; height: 14px; }

/* Поле с панелью в окне поста (документ сообщества 1.7) — под темой BuddyBoss её
   кнопка перебивает кнопки панели (рамка, фон и тень в :hover и :focus). Значения —
   те же, что у `.km-write__btn` в админке; держатся силой селектора, а не порядком. */
.km-hub button.km-write__btn,
.km-hub button.km-write__btn:focus,
.km-hub button.km-write__btn:active {
  min-width: 30px;
  height: auto;
  margin: 0;
  padding: 7px 9px;
  border: 1px solid transparent;
  border-radius: var(--km-radius-control);
  background: transparent;
  box-shadow: none;
  color: var(--km-text-secondary);
  font-family: inherit;
  font-size: 13px;
  font-weight: 400;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  cursor: pointer;
}
.km-hub button.km-write__btn:hover { border-color: transparent; background: var(--km-surface); box-shadow: none; color: var(--km-text); }
.km-hub button.km-write__btn[aria-pressed="true"],
.km-hub button.km-write__btn[aria-pressed="true"]:hover { border-color: var(--km-warm-border); background: var(--km-surface); color: var(--km-accent); }
.km-hub button.km-write__btn.km-write__btn--b { font-weight: 700; }
.km-hub button.km-write__btn.km-write__btn--i { font-style: italic; }
.km-hub button.km-write__btn:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 1px; }

/* Заголовок в поле поста — тем же шрифтом, что в ленте (`.km-hub-post__text h3`): человек правит то, что увидят.
   Тема ставит `h3` шрифт «Roboto Condensed» без запасного, и на телефоне он не грузится — заголовок, пришедший
   вставкой со страницы, выходил с засечками (снимок боевого 11.10.2026, документ сообщества 1.89). Силой
   селектора (0,2,1), а не порядком. Письма в админке (вне `.km-hub`) не задеты. */
.km-hub .km-write__area h3 { font-family: var(--km-hub-font); letter-spacing: normal; text-transform: none; }

.km-hub button.km-write__emoji-item,
.km-hub button.km-write__emoji-item:focus,
.km-hub button.km-write__emoji-item:active {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  margin: 0;
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--km-radius-control);
  background: transparent;
  box-shadow: none;
  color: var(--km-text);
  font-size: 20px;
  font-weight: 400;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  cursor: pointer;
}
.km-hub button.km-write__emoji-item:hover { border-color: transparent; background: var(--km-surface); box-shadow: none; color: var(--km-text); }
.km-hub button.km-write__emoji-item:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 1px; }

/* Длинный текст поста — шесть строк и «Читать далее» (документ сообщества 1.8). Свёртка показом,
   а не обрезкой разметки: списки, жирный и ссылки остаются целыми. Цвет ссылки — как у ссылок
   сообщества на досках. */
.km-hub .km-hub-post__text--folded { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 6; line-clamp: 6; overflow: hidden; }
.km-hub button.km-hub-post__more,
.km-hub button.km-hub-post__more:focus,
.km-hub button.km-hub-post__more:active {
  align-self: flex-start;
  margin: -6px 0 0;
  padding: 2px 0;
  border: 0;
  border-radius: 4px;
  background: none;
  box-shadow: none;
  color: var(--km-hub-link);
  font-family: var(--km-hub-font);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: normal;
  text-transform: none;
  cursor: pointer;
}
.km-hub button.km-hub-post__more:hover { border: 0; background: none; box-shadow: none; color: var(--km-hub-title); }
.km-hub button.km-hub-post__more:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }

/* ===== Сообщество, этап 5: закреплённые, плашка «К занятию», блок занятия, модерация =====
   Доски `feed-v2` и `mobile-v3` («Закреплено»), `post-parts-v2` (меню и «Группы поста»),
   `lesson-posts` (плашка, блок на странице занятия, окно привязки, поле «Занятие или часть»). */

/*
 * Закреплённый пост (доска pinned-v1, документ сообщества 1.19): стоит в ленте первым, целиком, как обычный;
 * сверху на карточке — полоса с булавкой и «Закреплено» справа, рамка темнее обычной. Блока над лентой нет.
 */
.km-hub-post.km-hub-post--pinned { border-color: var(--km-hub-pin-card-line); box-shadow: 0 2px 10px rgba(94, 66, 112, 0.08); }
.km-hub .km-hub-post__pin { display: flex; align-items: center; justify-content: flex-end; gap: 7px; padding: 10px 18px; border-bottom: 1px solid var(--km-hub-pin-strip-line); border-radius: 14px 14px 0 0; background: var(--km-hub-pin-strip); color: var(--km-hub-link); font-size: 13px; font-weight: 700; line-height: 1.3; }
.km-hub .km-hub-post__pin-word { display: inline-flex; align-items: center; gap: 7px; }
.km-hub .km-hub-post__pin-word .km-hub-icon { width: 16px; height: 16px; }
/* Ярлык темы в полосе — только на телефоне: там он переезжает из шапки, чтобы не добавлять строку. */
.km-hub .km-hub-post__pin-tag { display: none; }
/* «Открепить» у закреплённого — первым пунктом и заметнее остальных (доска pinned-v1). */
.km-hub button.km-hub-menu__item.km-hub-menu__item--lead,
.km-hub button.km-hub-menu__item.km-hub-menu__item--lead:hover { background: var(--km-hub-pin); color: var(--km-hub-title); font-weight: 700; }
/*
 * Правка комментария на месте (доска comment-edit, вариант А; документ сообщества 1.24): большое поле во весь
 * текст — растёт под длину (`rows` из скрипта), не ниже 168 px; под ним «Сохранить» и «Отмена» 38 px.
 */
.km-hub .km-hub-edit { display: flex; flex-direction: column; gap: 8px; margin: 2px 0 0; }
.km-hub textarea.km-hub-edit__field,
.km-hub textarea.km-hub-edit__field:focus {
  display: block;
  width: 100%;
  min-height: 168px;
  box-sizing: border-box;
  margin: 0;
  padding: 10px 12px;
  border: 1px solid var(--km-hub-accent);
  border-radius: 10px;
  background: #fff;
  box-shadow: 0 0 0 3px var(--km-hub-soft);
  outline: none;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 15px;
  line-height: 1.55;
  resize: vertical;
}
.km-hub .km-hub-edit__acts { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.km-hub .km-hub-edit button.km-hub-button.km-hub-button--sm,
.km-hub .km-hub-edit button.km-hub-button.km-hub-button--sm:focus,
.km-hub .km-hub-edit button.km-hub-button.km-hub-button--sm:active { height: 38px; padding: 0 16px; border-radius: 9px; font-size: 14px; font-weight: 700; }
.km-hub .km-hub-edit button.km-hub-button.km-hub-button--sm:not(.km-hub-button--primary) { border-color: var(--km-hub-chip-line); }
/* Счётчик комментариев закреплённого — подчёркнут: нажатие раскрывает их на месте. */
.km-hub .km-hub-post--pinned button.km-hub-act--fold .km-hub-act__word { text-decoration: underline; text-decoration-color: var(--km-hub-pin-card-line); text-underline-offset: 4px; }

/* Плашка привязки под шапкой: «К занятию · занятие · часть»; ведёт на занятие или часть. */
.km-hub a.km-hub-lesson-tag,
.km-hub a.km-hub-lesson-tag:visited,
.km-hub a.km-hub-lesson-tag:hover,
.km-hub a.km-hub-lesson-tag:focus { display: flex; align-items: center; gap: 10px; min-width: 0; padding: 10px 12px; border: 1px solid var(--km-hub-pin-line); border-radius: 10px; background: var(--km-hub-pin); color: var(--km-hub-tag-lilac-ink); font-size: 14px; font-weight: 500; line-height: 1.35; text-decoration: none; box-shadow: none; }
.km-hub a.km-hub-lesson-tag:hover { color: var(--km-hub-title); }
.km-hub a.km-hub-lesson-tag:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub .km-hub-lesson-tag .km-hub-icon { flex: none; width: 18px; height: 18px; }
.km-hub .km-hub-lesson-tag__text { min-width: 0; overflow-wrap: anywhere; }
.km-hub .km-hub-lesson-tag__word { font-weight: 700; }

/* Блок «Обсуждение в сообществе» на странице занятия: цвета и шрифт сообщества, страница — в своих. */
.km-hub.km-hub-lesson { display: flex; flex-direction: column; gap: 14px; margin-top: 8px; color: var(--km-hub-ink); font-family: var(--km-hub-font); }
.km-hub.km-hub-lesson--empty { gap: 12px; padding: 22px 24px; border-radius: 16px; background: var(--km-page); }
.km-hub .km-hub-lesson__head { display: flex; align-items: center; gap: 12px; }
.km-hub .km-hub-lesson__avatar { flex: none; width: 36px; height: 36px; margin: 0; border-radius: 9px; object-fit: cover; }
.km-hub .km-hub-lesson__avatar--letters { display: flex; align-items: center; justify-content: center; background: var(--km-hub-soft); color: var(--km-hub-link); font-size: 13px; font-weight: 700; }
.km-hub .km-hub-lesson__titles { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.km-hub h2.km-hub-lesson__title { margin: 0; font-family: var(--km-hub-display); font-size: 22px; font-weight: 500; line-height: 1.2; letter-spacing: normal; text-transform: none; color: var(--km-hub-title); }
.km-hub p.km-hub-lesson__line { margin: 0; font-size: 13px; line-height: 1.4; color: var(--km-hub-muted); }
.km-hub .km-hub-lesson__feed { display: flex; flex-direction: column; gap: 14px; }
.km-hub .km-hub-lesson__feed[hidden] { display: none; }
.km-hub.km-hub-lesson button.km-hub-lesson__more,
.km-hub.km-hub-lesson button.km-hub-lesson__more:focus,
.km-hub.km-hub-lesson button.km-hub-lesson__more:active { height: 42px; padding: 0 18px; border-color: var(--km-hub-chip-line); font-size: 14px; font-weight: 700; }
.km-hub.km-hub-lesson button.km-hub-lesson__more { align-self: flex-start; }

/*
 * Блоки занятия для группы курса (звёзды курса 1.7, раздел 6.7; прототип `design/bloki-v1.html`): карточка на стилях
 * сообщества — «Обратная связь», «Ваш отчёт за неделю», «Вопросы», «Обсуждение — коротко». Картинка группы и значки
 * стоят по верхнему краю первой строки заголовка; на телефоне плашка темы уходит на новую строку, заголовок не сжат.
 * Ссылки-кнопки — во всех состояниях, где их трогает тема: она смотрит на имя элемента, а не на наш класс.
 */
.km-hub.km-hub-cb { position: relative; margin: 0; border: 1px solid var(--km-hub-line); border-radius: 16px; background: #fff; color: var(--km-hub-ink); font-family: var(--km-hub-font); }
.km-hub .km-hub-cb__pad { display: flex; flex-direction: column; gap: 14px; padding: 20px 22px; }
.km-hub .km-hub-cb__pic { flex: none; width: 40px; height: 40px; margin: 2px 0 0; border-radius: 10px; object-fit: cover; }
.km-hub .km-hub-cb__pic--lg { width: 56px; height: 56px; margin-top: 3px; border-radius: 14px; }
.km-hub .km-hub-cb__pic--letters { display: flex; align-items: center; justify-content: center; background: var(--km-hub-soft); color: var(--km-hub-link); font-size: 15px; font-weight: 700; }
.km-hub a.km-hub-cb__btn,
.km-hub a.km-hub-cb__btn:visited,
.km-hub a.km-hub-cb__btn:focus,
.km-hub a.km-hub-cb__btn:active { display: inline-flex; align-items: center; justify-content: center; gap: 8px; height: 44px; padding: 0 20px; border: 0; border-radius: 10px; background: var(--km-hub-red); color: #fff; font-family: var(--km-hub-font); font-size: 15px; font-weight: 700; line-height: 1; text-decoration: none; white-space: nowrap; box-shadow: none; }
.km-hub a.km-hub-cb__btn:hover { background: var(--km-hub-red-hover); color: #fff; }

/* «Обратная связь» — карточка группы (вариант А). */
.km-hub h2.km-hub-cb__kick { display: flex; align-items: center; gap: 7px; margin: 0; padding: 0; color: var(--km-hub-link); font-family: var(--km-hub-font); font-size: 12px; font-weight: 700; line-height: 1.3; letter-spacing: 0.08em; text-transform: uppercase; }
.km-hub .km-hub-cb__glyph { flex: none; width: 16px; height: 16px; }
.km-hub .km-hub-cb__fbrow { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 16px; }
.km-hub .km-hub-cb__fbrow > .km-hub-cb__btn { align-self: center; }
.km-hub .km-hub-cb__mid { flex: 1; min-width: 220px; display: flex; flex-direction: column; gap: 6px; }
.km-hub .km-hub-cb__gname { color: var(--km-hub-title); font-family: var(--km-hub-display); font-size: 22px; font-weight: 500; line-height: 1.2; }
.km-hub .km-hub-cb__gtext { color: var(--km-hub-ink); font-size: 15px; line-height: 1.5; }
.km-hub .km-hub-cb__faces { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; color: var(--km-hub-muted); font-size: 13px; line-height: 1.3; }
.km-hub .km-hub-cb__count { white-space: nowrap; }
.km-hub .km-hub-cb__stack { display: flex; }
.km-hub .km-hub-cb__face { flex: none; width: 28px; height: 28px; margin: 0 0 0 -8px; border: 2px solid #fff; border-radius: 50%; object-fit: cover; }
.km-hub .km-hub-cb__face:first-child { margin-left: 0; }
.km-hub .km-hub-cb__face--letters { display: flex; align-items: center; justify-content: center; background: var(--km-hub-soft); color: var(--km-hub-link); font-size: 10px; font-weight: 700; }

/* Шапка блока: картинка группы 40 px, заголовок с подписью, плашка темы — по верхнему краю первой строки заголовка. */
.km-hub .km-hub-cb__head { display: flex; align-items: flex-start; gap: 12px; }
.km-hub .km-hub-cb__ht { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.km-hub h3.km-hub-cb__title { margin: 0; padding: 0; color: var(--km-hub-title); font-family: var(--km-hub-display); font-size: 22px; font-weight: 500; line-height: 1.2; letter-spacing: normal; text-transform: none; }
.km-hub .km-hub-cb__sub { color: var(--km-hub-muted); font-size: 13px; line-height: 1.4; }
/* Верх букв заголовка (KM Oswald 22/1.2) — на 4,7 px ниже его рамки: замер стенда 13.10.2026. Отступ прототипа (2 px)
   рассчитан на другой шрифт; картинка и плашка стоят по буквам, а не по рамке. */
.km-hub .km-hub-cb__head > .km-hub-cb__pic { margin-top: 5px; }
.km-hub .km-hub-cb__tag { flex: none; margin-top: 5px; }
.km-hub p.km-hub-cb__lead { margin: 0; color: var(--km-hub-ink); font-size: 15px; line-height: 1.6; }

/* «Ваш отчёт за неделю»: поля — разметкой окна поста (`hub-attach.php`, `.km-hub-field`), под ними кнопка и примечание. */
.km-hub .km-hub-cb__form { display: flex; flex-direction: column; gap: 12px; min-width: 0; margin: 0; }
.km-hub .km-hub-cb__form[hidden],
.km-hub .km-hub-cb__done[hidden],
.km-hub p.km-hub-cb__err[hidden] { display: none; }
.km-hub .km-hub-cb__form .km-hub-status:empty { display: none; }
.km-hub p.km-hub-cb__err { margin: 0; color: var(--km-danger); font-size: 13px; line-height: 1.5; }
.km-hub .km-hub-cb__pubrow { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 10px; }
.km-hub .km-hub-cb__pubrow .km-stars-plq { font-family: var(--km-font); }
.km-hub button.km-hub-cb__btn,
.km-hub button.km-hub-cb__btn:hover,
.km-hub button.km-hub-cb__btn:focus,
.km-hub button.km-hub-cb__btn:active { display: inline-flex; align-items: center; justify-content: center; gap: 8px; height: 46px; margin: 0; padding: 0 24px; border: 0; border-radius: 10px; background: var(--km-hub-red); box-shadow: none; color: #fff; font-family: var(--km-hub-font); font-size: 15px; font-weight: 700; line-height: 1; letter-spacing: normal; text-transform: none; white-space: nowrap; cursor: pointer; }
.km-hub button.km-hub-cb__btn:hover { background: var(--km-hub-red-hover); }
.km-hub button.km-hub-cb__btn:disabled { opacity: 0.6; cursor: default; }
.km-hub .km-hub-cb__note { margin: 0; color: var(--km-hub-muted); font-size: 13px; line-height: 1.5; }
.km-hub .km-hub-cb__grow { flex: 1; }
.km-hub .km-hub-cb__pad > .km-hub-status:empty { display: none; }
.km-hub button.km-hub-cb__btn2,
.km-hub button.km-hub-cb__btn2:hover,
.km-hub button.km-hub-cb__btn2:focus,
.km-hub button.km-hub-cb__btn2:active { display: inline-flex; align-items: center; gap: 8px; height: 42px; margin: 0; padding: 0 16px; border: 1px solid var(--km-hub-chip-line); border-radius: 10px; background: #fff; box-shadow: none; color: var(--km-hub-ink); font-family: var(--km-hub-font); font-size: 14px; font-weight: 700; line-height: 1; letter-spacing: normal; text-transform: none; white-space: nowrap; cursor: pointer; }
.km-hub button.km-hub-cb__btn2:hover { border-color: var(--km-hub-accent); }
.km-hub .km-hub-cb__row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }

/* «Вопросы»: текст поста, как в группе; поле вопроса с лицом; ветки — строками комментариев сообщества. */
.km-hub .km-hub-cb__text { color: var(--km-hub-ink); font-size: 15px; line-height: 1.6; overflow-wrap: anywhere; }
.km-hub .km-hub-cb__text > * { margin: 0; }
.km-hub .km-hub-cb__text > * + * { margin-top: 8px; }
.km-hub .km-hub-cb__ask { display: flex; align-items: flex-start; gap: 10px; margin: 0; }
.km-hub .km-hub-cb__box { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 10px; }
.km-hub textarea.km-hub-cb__in { box-sizing: border-box; width: 100%; min-height: 76px; margin: 0; padding: 12px 14px; border: 1px solid var(--km-hub-line); border-radius: 10px; background: var(--km-hub-field); color: var(--km-hub-ink); font-family: var(--km-hub-font); font-size: 15px; line-height: 1.55; resize: vertical; }
.km-hub textarea.km-hub-cb__in:focus { outline: 2px solid var(--km-hub-accent); outline-offset: 0; background: #fff; }
.km-hub .km-hub-cb__ask .km-hub-cb__note { flex: 1; min-width: 200px; }
.km-hub .km-hub-cb__list { padding-top: 14px; border-top: 1px solid var(--km-hub-line-soft); }

/* «Обсуждение — коротко»: шапка как у нынешнего, посты коротко; раскрытый — карточкой сообщества на месте. */
.km-hub.km-hub-short { display: flex; flex-direction: column; gap: 14px; margin: 0; color: var(--km-hub-ink); font-family: var(--km-hub-font); }
.km-hub .km-hub-cb__pic--sm { width: 36px; height: 36px; border-radius: 9px; }
.km-hub .km-hub-short__list { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.km-hub .km-hub-short__item[hidden],
.km-hub .km-hub-mini[hidden] { display: none; }
.km-hub button.km-hub-short__more { align-self: flex-start; }
.km-hub .km-hub-mini { display: flex; flex-direction: column; gap: 8px; padding: 14px 16px; border: 1px solid var(--km-hub-line); border-radius: 14px; background: #fff; }
.km-hub .km-hub-mini__who { display: flex; align-items: center; gap: 10px; color: var(--km-hub-muted); font-size: 13px; line-height: 1.4; }
.km-hub .km-hub-mini__name { color: var(--km-hub-ink); font-size: 14px; }
.km-hub .km-hub-mini__when { white-space: nowrap; }
.km-hub .km-hub-mini__gap { flex: 1; }
.km-hub h4.km-hub-mini__title { margin: 0; padding: 0; color: var(--km-hub-title); font-family: var(--km-hub-display); font-size: 19px; font-weight: 500; line-height: 1.25; letter-spacing: normal; text-transform: none; }
.km-hub p.km-hub-mini__text { display: -webkit-box; margin: 0; overflow: hidden; color: var(--km-hub-cast-text); font-size: 14px; line-height: 1.55; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.km-hub .km-hub-mini__meta { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; padding-top: 4px; color: var(--km-hub-proof); font-size: 13px; }
.km-hub .km-hub-mini__stat { display: inline-flex; align-items: center; gap: 6px; }
.km-hub .km-hub-mini__stat svg { flex: none; width: 18px; height: 18px; }
/* «Читать и обсудить →» и заголовок — ссылки на пост в группе (звёзды курса 1.18, 6.7, п. 3): под курсором меняется только цвет. */
.km-hub a.km-hub-mini__open,
.km-hub a.km-hub-mini__open:visited,
.km-hub a.km-hub-mini__open:focus,
.km-hub a.km-hub-mini__open:active { margin: 0 0 0 auto; padding: 0; border: 0; background: none; box-shadow: none; color: var(--km-hub-link); font-family: var(--km-hub-font); font-size: 14px; font-weight: 700; line-height: 1.4; letter-spacing: normal; text-decoration: none; text-transform: none; white-space: nowrap; }
.km-hub a.km-hub-mini__open:hover { color: var(--km-hub-title); text-decoration: none; }
.km-hub a.km-hub-mini__link,
.km-hub a.km-hub-mini__link:visited { color: inherit; text-decoration: none; }
.km-hub a.km-hub-mini__link:hover { color: var(--km-hub-link); text-decoration: none; }

/* Опубликовано: зелёная строка с «Открыть пост →» и превью последнего поста недели. */
.km-hub .km-hub-cb__done { display: flex; flex-direction: column; gap: 12px; }
.km-hub .km-hub-cb__ok { display: flex; align-items: flex-start; gap: 12px; padding: 14px 16px; border: 1px solid var(--km-hub-done-line); border-radius: 12px; background: var(--km-hub-done-bg); }
.km-hub .km-hub-cb__check { flex: none; display: flex; align-items: center; justify-content: center; width: 32px; height: 32px; border-radius: 50%; background: var(--km-hub-done); color: #fff; }
.km-hub .km-hub-cb__okt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; color: var(--km-hub-ink); font-size: 14px; line-height: 1.4; }
.km-hub .km-hub-cb__okt b { font-size: 15px; }
.km-hub .km-hub-cb__okt span { overflow: hidden; color: var(--km-hub-proof); text-overflow: ellipsis; white-space: nowrap; }
.km-hub a.km-hub-cb__link,
.km-hub a.km-hub-cb__link:visited { align-self: center; color: var(--km-hub-link); font-size: 14px; font-weight: 700; text-decoration: none; white-space: nowrap; }
.km-hub a.km-hub-cb__link:hover { color: var(--km-hub-title); }
.km-hub .km-hub-cb__mypost { display: flex; flex-direction: column; gap: 8px; padding: 14px 16px; border: 1px solid var(--km-hub-line); border-radius: 12px; background: var(--km-hub-field); }
.km-hub .km-hub-cb__who { display: flex; align-items: flex-start; gap: 10px; }
.km-hub .km-hub-cb__face--md { width: 32px; height: 32px; margin: 0; border: 0; font-size: 12px; }
.km-hub .km-hub-cb__byline { display: flex; flex-direction: column; min-width: 0; font-size: 13px; line-height: 1.4; color: var(--km-hub-muted); }
.km-hub .km-hub-cb__byline b { font-size: 14px; }
.km-hub h4.km-hub-cb__ptitle { margin: 0; padding: 0; color: var(--km-hub-title); font-family: var(--km-hub-display); font-size: 19px; font-weight: 500; line-height: 1.25; letter-spacing: normal; text-transform: none; }
.km-hub p.km-hub-cb__ptext { display: -webkit-box; margin: 0; overflow: hidden; color: var(--km-hub-cast-text); font-size: 14px; line-height: 1.55; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }

@media (max-width: 560px) {
  .km-hub .km-hub-cb__pad { padding: 16px; }
  .km-hub .km-hub-cb__fbrow .km-hub-cb__mid { flex: 1 1 calc(100% - 72px); min-width: 0; }
  .km-hub .km-hub-cb__fbrow > .km-hub-cb__btn { width: 100%; }
  .km-hub h3.km-hub-cb__title { font-size: 20px; }
  .km-hub .km-hub-cb__pubrow > .km-hub-cb__btn,
  .km-hub .km-hub-cb__row > .km-hub-cb__btn { width: 100%; }
  /* Плашка темы — на новую строку под заголовком, заголовок не сжимается. */
  .km-hub .km-hub-cb__head { flex-wrap: wrap; }
  .km-hub .km-hub-cb__head .km-hub-cb__ht { flex: 1 1 calc(100% - 64px); }
  .km-hub .km-hub-cb__head .km-hub-cb__tag { margin-left: 52px; }
  .km-hub .km-hub-mini__who { flex-wrap: wrap; row-gap: 6px; }
  .km-hub .km-hub-mini__gap { display: none; }
  .km-hub a.km-hub-mini__open { margin-left: 0; }
}


/*
 * «Где опубликовать» — доска where-publish, вариант А (документ сообщества 1.30): переключатель «Всё сообщество»
 * 40 × 24, группы плашками 34 px с крестиком, «+ Выбрать группы» пунктиром; список групп с поиском — не шире 420 px,
 * прокручивается внутри (до 200 px), окно не растягивает. Одно оформление на окно поста и «Группы поста».
 * Кнопки — во всех состояниях, где их трогает тема: она смотрит на имя элемента, а не на наш класс.
 */
.km-hub .km-hub-where { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.km-hub label.km-hub-switch { position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; margin: 0; color: var(--km-hub-ink); font-size: 15px; font-weight: 400; line-height: 1.35; cursor: pointer; }
.km-hub .km-hub-switch__input { position: absolute; width: 1px; height: 1px; margin: 0; opacity: 0; }
.km-hub .km-hub-switch__track { position: relative; flex: none; width: 40px; height: 24px; border-radius: 12px; background: var(--km-hub-switch-off); }
.km-hub .km-hub-switch__track::after { content: ''; position: absolute; left: 3px; top: 3px; width: 18px; height: 18px; border-radius: 50%; background: #fff; }
.km-hub .km-hub-switch__input:checked + .km-hub-switch__track { background: var(--km-hub-accent); }
.km-hub .km-hub-switch__input:checked + .km-hub-switch__track::after { left: 19px; }
.km-hub .km-hub-switch__input:focus-visible + .km-hub-switch__track { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub .km-hub-switch__note { color: var(--km-hub-muted); font-size: 13px; }
.km-hub .km-hub-where__groups { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.km-hub .km-hub-where__groups[hidden] { display: none; }
.km-hub .km-hub-where__label { color: var(--km-hub-chip-ink); font-size: 13px; font-weight: 700; }
.km-hub .km-hub-where__chips { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; min-width: 0; }
.km-hub .km-hub-where__chip { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; min-height: 34px; box-sizing: border-box; padding: 0 6px 0 12px; border-radius: 9px; background: var(--km-hub-soft); color: var(--km-hub-ink); font-size: 14px; font-weight: 600; line-height: 1.3; overflow-wrap: anywhere; }
.km-hub button.km-hub-where__drop,
.km-hub button.km-hub-where__drop:hover,
.km-hub button.km-hub-where__drop:focus,
.km-hub button.km-hub-where__drop:active { display: flex; align-items: center; justify-content: center; flex: none; width: 22px; height: 22px; margin: 0; padding: 0; border: 0; border-radius: 6px; background: none; box-shadow: none; color: var(--km-hub-muted); font-family: var(--km-hub-font); font-size: 13px; font-weight: 400; line-height: 1; letter-spacing: normal; text-transform: none; cursor: pointer; }
.km-hub button.km-hub-where__drop:hover { color: var(--km-hub-ink); }
.km-hub button.km-hub-where__drop:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 1px; }
.km-hub button.km-hub-where__add,
.km-hub button.km-hub-where__add:hover,
.km-hub button.km-hub-where__add:focus,
.km-hub button.km-hub-where__add:active { height: 34px; margin: 0; padding: 0 12px; border: 1px dashed var(--km-hub-dash); border-radius: 9px; background: #fff; box-shadow: none; color: var(--km-hub-link); font-family: var(--km-hub-font); font-size: 14px; font-weight: 700; line-height: 1; letter-spacing: normal; text-transform: none; cursor: pointer; }
.km-hub button.km-hub-where__add:hover { border-color: var(--km-hub-accent); }
.km-hub button.km-hub-where__add:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub .km-hub-where__panel { display: flex; flex-direction: column; gap: 4px; max-width: 420px; box-sizing: border-box; padding: 8px; border: 1px solid var(--km-hub-line); border-radius: 12px; background: #fff; box-shadow: 0 8px 24px rgba(59, 42, 71, 0.12); }
.km-hub .km-hub-where__panel[hidden] { display: none; }
.km-hub input.km-hub-where__search,
.km-hub input.km-hub-where__search:focus { width: 100%; height: 40px; box-sizing: border-box; margin: 0; padding: 0 12px; border: 1px solid var(--km-hub-line); border-radius: 9px; background: var(--km-hub-field); box-shadow: none; outline: none; color: var(--km-hub-ink); font-family: var(--km-hub-font); font-size: 14px; }
.km-hub input.km-hub-where__search:focus { border-color: var(--km-hub-accent); }
.km-hub .km-hub-where__list { display: flex; flex-direction: column; max-height: 200px; overflow-y: auto; }
.km-hub .km-hub-where__list label.km-hub-mod__row { padding: 9px 10px; border-radius: 8px; }
.km-hub .km-hub-where__list label.km-hub-mod__row:has(input:checked) { background: var(--km-hub-pin); }
.km-hub .km-hub-where__list label.km-hub-mod__row[hidden] { display: none; }
.km-hub .km-hub-where__none { margin: 0; padding: 9px 10px; color: var(--km-hub-muted); font-size: 14px; }
.km-hub .km-hub-where__none[hidden] { display: none; }

/* Окно модерации: уже окна поста; строки с флажком. */
.km-hub .km-hub-dialog--small { width: 520px; }

/*
 * Знакомство с сообществом — доска onboarding-v1 (документ сообщества 1.72): окно 420, поля 24, между блоками 16;
 * полоска шагов сверху, главная кнопка красная, «Пропустить» и «Не сейчас» — тихим словом. На телефоне — на весь
 * экран, как все окна сообщества.
 */
.km-hub .km-hub-dialog--welcome { width: 420px; border-radius: 18px; box-shadow: 0 14px 36px rgba(59, 42, 71, 0.16); }
.km-hub .km-hub-welcome__top { display: flex; align-items: center; gap: 14px; padding: 18px 18px 0 24px; }
.km-hub .km-hub-welcome__bar { display: flex; flex: 1; gap: 6px; }
.km-hub .km-hub-welcome__seg { flex: 1; height: 4px; border-radius: 2px; background: var(--km-hub-line); }
.km-hub .km-hub-welcome__seg--on { background: var(--km-hub-red); }
.km-hub .km-hub-welcome__pane { display: flex; flex-direction: column; gap: 16px; padding: 14px 24px 24px; }
.km-hub .km-hub-welcome__pane[hidden] { display: none; }
/* Пустая строка ответа места не занимает: иначе между полем и кнопками вдвое больше воздуха, чем на доске (снимок боевого 11.10). */
.km-hub .km-hub-welcome__pane .km-hub-status:empty { display: none; }
.km-hub h2.km-hub-welcome__title { margin: 0; font-family: var(--km-hub-display); font-size: 26px; font-weight: 500; line-height: 1.2; letter-spacing: normal; text-transform: none; color: var(--km-hub-title); }
.km-hub .km-hub-welcome__lead { margin: 0; font-size: 15px; line-height: 1.6; color: var(--km-hub-chip-ink); }
.km-hub .km-hub-welcome__face { display: flex; align-items: center; gap: 16px; }
.km-hub button.km-hub-welcome__photo,
.km-hub button.km-hub-welcome__photo:focus,
.km-hub button.km-hub-welcome__photo:active {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 88px;
  height: 88px;
  margin: 0;
  padding: 0;
  overflow: hidden;
  border: 1.5px dashed var(--km-hub-dash);
  border-radius: 50%;
  background: var(--km-hub-field);
  box-shadow: none;
  color: var(--km-hub-muted);
  font-family: var(--km-hub-font);
  font-size: 28px;
  font-weight: 400;
  line-height: 1;
  cursor: pointer;
}
.km-hub button.km-hub-welcome__photo:hover { border-color: var(--km-hub-accent); background: var(--km-hub-hover); color: var(--km-hub-accent); }
.km-hub button.km-hub-welcome__photo--on,
.km-hub button.km-hub-welcome__photo--on:focus,
.km-hub button.km-hub-welcome__photo--on:hover { border-style: solid; border-color: var(--km-hub-line); }
.km-hub .km-hub-welcome__photo img { display: block; width: 100%; height: 100%; object-fit: cover; }
.km-hub .km-hub-welcome__acts { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.km-hub button.km-hub-welcome__skip,
.km-hub button.km-hub-welcome__skip:focus,
.km-hub button.km-hub-welcome__skip:active {
  height: 46px;
  margin: 0;
  padding: 0 6px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  box-shadow: none;
  color: var(--km-hub-muted);
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: normal;
  text-decoration: none;
  text-transform: none;
  cursor: pointer;
}
.km-hub button.km-hub-welcome__skip:hover { background: transparent; color: var(--km-hub-ink); }
.km-hub button.km-hub-welcome__skip:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub .km-hub-welcome__post { display: flex; flex-direction: column; gap: 8px; padding: 12px; border: 1px solid var(--km-hub-chip-line); border-radius: 12px; }
.km-hub .km-hub-welcome__post:focus-within { border-color: var(--km-hub-accent); box-shadow: 0 0 0 3px var(--km-hub-soft); }
.km-hub .km-hub-welcome__where { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: 13px; color: var(--km-hub-muted); }
.km-hub .km-hub-welcome__tag { padding: 3px 8px; border-radius: 6px; font-size: 13px; font-weight: 700; }
.km-hub textarea.km-hub-welcome__text,
.km-hub textarea.km-hub-welcome__text:focus {
  width: 100%;
  min-height: 96px;
  margin: 0;
  padding: 0;
  border: 0;
  outline: none;
  background: transparent;
  box-shadow: none;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 15px;
  line-height: 1.55;
  resize: vertical;
}
.km-hub .km-hub-dialog--small .km-hub-dialog__body { gap: 14px; max-height: 60vh; overflow-y: auto; }
.km-hub .km-hub-dialog__status { padding: 0 22px; }
.km-hub .km-hub-dialog__status:empty { display: none; }
.km-hub .km-hub-mod__list { display: flex; flex-direction: column; gap: 6px; font-size: 14px; color: var(--km-hub-muted); }
.km-hub label.km-hub-mod__row { position: relative; display: flex; align-items: center; gap: 12px; margin: 0; padding: 10px 12px; border-radius: 10px; color: var(--km-hub-ink); font-size: 14px; font-weight: 400; line-height: 1.35; cursor: pointer; }
.km-hub label.km-hub-mod__row:hover { background: var(--km-hub-hover); }
.km-hub .km-hub-mod__row input { position: absolute; width: 1px; height: 1px; margin: 0; opacity: 0; }
.km-hub .km-hub-mod__box { position: relative; flex: none; box-sizing: border-box; width: 18px; height: 18px; border: 1.5px solid var(--km-hub-chip-line); border-radius: 4px; background: #fff; }
.km-hub .km-hub-mod__row input:checked + .km-hub-mod__box { border-color: var(--km-hub-accent); background: var(--km-hub-accent); }
.km-hub .km-hub-mod__row input:checked + .km-hub-mod__box::after { content: ''; position: absolute; left: 5px; top: 1.5px; width: 4px; height: 8px; border-right: 2px solid #fff; border-bottom: 2px solid #fff; transform: rotate(45deg); }
.km-hub .km-hub-mod__row input:focus-visible + .km-hub-mod__box { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub .km-hub-mod__text { flex: 1; min-width: 0; display: flex; flex-direction: column; overflow-wrap: anywhere; }

/* ===== Сообщество, этап 6: планирование (доска composer-admin-v4) ===== */

/* Строка времени у запланированного: когда выйдет; прошло, а не вышел — тревожным цветом. */
.km-hub .km-hub-post__planned { font-weight: 600; color: var(--km-hub-link); white-space: normal; }
.km-hub .km-hub-post__planned--late { color: var(--km-danger); }

/* «Запланировать» — в подвале окна слева; нажата — подложкой закрепа, как на доске. */
.km-hub .km-hub-dialog__foot button.km-hub-plan-toggle,
.km-hub .km-hub-dialog__foot button.km-hub-plan-toggle:focus,
.km-hub .km-hub-dialog__foot button.km-hub-plan-toggle:active { display: inline-flex; align-items: center; gap: 8px; margin-right: auto; padding: 0 16px; }
.km-hub .km-hub-dialog__foot button.km-hub-plan-toggle[hidden] { display: none; }
.km-hub .km-hub-dialog__foot button.km-hub-plan-toggle[aria-pressed="true"] { border-color: var(--km-hub-pin-line); background: var(--km-hub-pin); color: var(--km-hub-title); }
.km-hub .km-hub-dialog__foot button.km-hub-plan-toggle:disabled { opacity: 1; cursor: default; }
.km-hub .km-hub-plan-toggle .km-hub-icon { width: 18px; height: 18px; }

/* «Когда опубликовать»: дата, время, «мск» и строка, когда пост появится. */
.km-hub .km-hub-plan { display: flex; flex-direction: column; gap: 10px; min-width: 0; margin: 0; padding: 14px 16px; border: 1px solid var(--km-hub-pin-line); border-radius: 12px; background: var(--km-hub-pin); }
.km-hub .km-hub-plan[hidden] { display: none; }
.km-hub .km-hub-plan__title { margin: 0; font-size: 14px; font-weight: 700; color: var(--km-hub-title); }
.km-hub .km-hub-plan__row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px; }
.km-hub .km-hub-plan__cell { display: flex; flex-direction: column; gap: 6px; }
.km-hub .km-hub-plan__label { margin: 0; font-size: 13px; font-weight: 400; color: var(--km-hub-muted); }
.km-hub input.km-hub-plan__input { box-sizing: border-box; height: 46px; margin: 0; padding: 0 12px; border: 1px solid var(--km-hub-line); border-radius: 10px; background: #fff; box-shadow: none; color: var(--km-hub-ink); font-family: var(--km-hub-font); font-size: 15px; }
.km-hub input.km-hub-plan__input:focus { border-color: var(--km-hub-accent); outline: none; box-shadow: 0 0 0 3px var(--km-hub-soft); }
.km-hub .km-hub-plan__zone { display: flex; align-items: center; height: 46px; font-size: 14px; color: var(--km-hub-muted); }
.km-hub p.km-hub-plan__hint { margin: 0; font-size: 13px; line-height: 1.5; color: var(--km-hub-link); }
.km-hub.km-hub-lesson .km-hub-status:empty { display: none; }
.km-hub button.km-hub-post__more[hidden] { display: none; }

/* Под постом (этап 4) — доска feed-v2: «Поддержать · N», счётчик комментариев, «Следить». */
.km-hub .km-hub-acts { display: flex; align-items: center; gap: 6px; padding: 8px 12px; border-top: 1px solid var(--km-hub-line-soft); }
.km-hub .km-hub-acts__gap { flex: 1; }
.km-hub .km-hub-act,
.km-hub button.km-hub-act,
.km-hub button.km-hub-act:focus,
.km-hub button.km-hub-act:active {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 40px;
  margin: 0;
  padding: 0 12px;
  border: 0;
  border-radius: 8px;
  background: none;
  box-shadow: none;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 400;
  line-height: 1.2;
  letter-spacing: normal;
  text-transform: none;
  white-space: nowrap;
}
.km-hub button.km-hub-act { cursor: pointer; }
.km-hub button.km-hub-act:hover { border: 0; background: var(--km-hub-hover); box-shadow: none; color: var(--km-hub-ink); }
.km-hub button.km-hub-act:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub button.km-hub-act:disabled { opacity: 0.6; cursor: default; }
.km-hub .km-hub-act .km-hub-icon { width: 19px; height: 19px; }
.km-hub .km-hub-act__off,
.km-hub .km-hub-act__on { display: inline-flex; }
.km-hub .km-hub-act[aria-pressed="true"] .km-hub-act__off,
.km-hub .km-hub-act[aria-pressed="false"] .km-hub-act__on { display: none; }
.km-hub .km-hub-act__dot[hidden] { display: none; }
.km-hub .km-hub-act__count { font-variant-numeric: tabular-nums; }
/* Счётчик, который не кнопка: один комментарий или ни одного — раскрывать нечего. */
.km-hub .km-hub-act--still { cursor: default; }
/* Поддержал — красным и жирным; следишь — фиолетовым (доска). */
.km-hub button.km-hub-act--support[aria-pressed="true"],
.km-hub button.km-hub-act--support[aria-pressed="true"]:hover { color: var(--km-hub-red); font-weight: 700; }
.km-hub button.km-hub-act--follow[aria-pressed="true"],
.km-hub button.km-hub-act--follow[aria-pressed="true"]:hover { color: var(--km-hub-link); font-weight: 600; }
.km-hub .km-hub-act--follow .km-hub-icon { width: 18px; height: 18px; }

/* «Поддержать · N» — две кнопки одной строкой (профили, этап 2): слово поддерживает, число открывает список
   «Поддержали». Промежуток между ними — тот же, что был внутри одной кнопки. Поддержал — оба красным и жирным. */
.km-hub .km-hub-sup { position: relative; display: inline-flex; align-items: center; }
.km-hub .km-hub-sup:has(> .km-hub-act--likers:not([hidden])) > button.km-hub-act--support { padding-right: 4px; }
.km-hub .km-hub-sup > button.km-hub-act--likers,
.km-hub .km-hub-sup > button.km-hub-act--likers:focus,
.km-hub .km-hub-sup > button.km-hub-act--likers:active { padding-left: 3px; }
.km-hub .km-hub-sup > button.km-hub-act--likers[hidden] { display: none; }
.km-hub .km-hub-sup:has(> .km-hub-act--support[aria-pressed="true"]) > button.km-hub-act--likers,
.km-hub .km-hub-sup:has(> .km-hub-act--support[aria-pressed="true"]) > button.km-hub-act--likers:hover { color: var(--km-hub-red); font-weight: 700; }

/* Имя человека — кнопка карточки (профили, этап 2, доска profile-v2): вид — того места, где стоит имя;
   под курсором подчёркнуто, ничего не двигается. Фото рядом открывает то же нажатием мышью. */
.km-hub button.km-hub-name,
.km-hub button.km-hub-name:hover,
.km-hub button.km-hub-name:focus,
.km-hub button.km-hub-name:active {
  display: inline;
  max-width: 100%;
  height: auto;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  text-align: left;
  text-decoration: none;
  text-transform: none;
  vertical-align: baseline;
  cursor: pointer;
}
.km-hub button.km-hub-name:hover { text-decoration: underline; text-underline-offset: 3px; }
.km-hub button.km-hub-name:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; border-radius: 3px; }
.km-hub .km-hub-comment__head > button.km-hub-name,
.km-hub .km-hub-comment__head > button.km-hub-name:hover,
.km-hub .km-hub-comment__head > button.km-hub-name:focus,
.km-hub .km-hub-comment__head > button.km-hub-name:active { font-weight: 700; }
.km-hub .km-hub-tap { cursor: pointer; }
/* Имя — ссылкой на профиль там, где карточки человека нет («Обсуждение», 11.10.2026): вид тот же, что у кнопки;
   тема красит ссылки своим цветом во всех состояниях — объявлены все. */
.km-hub a.km-hub-name,
.km-hub a.km-hub-name:visited,
.km-hub a.km-hub-name:hover,
.km-hub a.km-hub-name:focus,
.km-hub a.km-hub-name:active { color: inherit; font-weight: inherit; text-decoration: none; box-shadow: none; }
.km-hub a.km-hub-name:hover { text-decoration: underline; text-underline-offset: 3px; }
.km-hub a.km-hub-name:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; border-radius: 3px; }
.km-hub .km-hub-comment__head > a.km-hub-name,
.km-hub .km-hub-comment__head > a.km-hub-name:visited,
.km-hub .km-hub-comment__head > a.km-hub-name:hover,
.km-hub .km-hub-comment__head > a.km-hub-name:focus,
.km-hub .km-hub-comment__head > a.km-hub-name:active { font-weight: 700; }

/* Окно поверх ленты — карточка человека и список «Поддержали» (доска profile-v2, раздел 1). На компьютере
   встаёт под тем, на что нажали: скрипт кладёт узел в шапку поста, строку имени комментария или к «Поддержать»,
   место — отсюда. На телефоне — снизу экрана (правила ниже, в разделе телефона). */
.km-hub .km-hub-post__head { position: relative; }
.km-hub .km-hub-pop {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 30;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: 14px;
  max-width: calc(100vw - 32px);
  padding: 20px;
  border: 1px solid var(--km-hub-line);
  border-radius: 16px;
  background: #fff;
  box-shadow: 0 14px 36px rgba(59, 42, 71, 0.2);
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: normal;
  text-align: left;
  text-transform: none;
  white-space: normal;
  cursor: default;
}
.km-hub .km-hub-pop:focus { outline: none; }
.km-hub .km-hub-shade { display: none; }
/* Слой окна на телефоне — у `body`, вне колонки-контейнера; своего места не занимает. */
.km-hub.km-hub-layer { display: contents; }
.km-hub button.km-hub-pop__close,
.km-hub button.km-hub-pop__close:hover,
.km-hub button.km-hub-pop__close:focus,
.km-hub button.km-hub-pop__close:active {
  position: absolute;
  top: 10px;
  right: 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: none;
  box-shadow: none;
  color: var(--km-hub-muted);
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 400;
  line-height: 1;
  cursor: pointer;
}
.km-hub button.km-hub-pop__close:hover { background: var(--km-hub-hover); color: var(--km-hub-ink); }
.km-hub button.km-hub-pop__close:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub .km-hub-pop__close .km-hub-icon { width: 18px; height: 18px; }
.km-hub p.km-hub-pop__status { margin: 0; padding-right: 32px; font-size: 14px; line-height: 1.5; color: var(--km-hub-muted); }
.km-hub p.km-hub-pop__status--error { color: var(--km-hub-red-deep); }

/* Карточка человека: фото 72, имя, «В сообществе с…», «О себе», числа, общие группы. Уровня пока нет — строки
   нет. Длинное «О себе» (из BuddyBoss бывает в тысячу знаков) — восемь строк: целиком — в профиле. */
.km-hub .km-hub-pop.km-hub-pcard { width: 340px; }
.km-hub .km-hub-pcard__top { display: flex; align-items: center; gap: 14px; padding-right: 28px; }
.km-hub .km-hub-pcard__photo { flex: none; display: block; width: 72px; height: 72px; border-radius: 50%; object-fit: cover; }
.km-hub .km-hub-pcard__photo.km-hub-person--letters { display: flex; font-size: 24px; }
.km-hub .km-hub-pcard__who { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.km-hub .km-hub-pcard__name { font-family: var(--km-hub-display); font-size: 22px; font-weight: 500; line-height: 1.2; color: var(--km-hub-title); overflow-wrap: anywhere; }
.km-hub .km-hub-pcard__since { font-size: 13px; line-height: 1.4; color: var(--km-hub-muted); }
/* «О себе» абзацами — одно правило на карточку и профиль (слово Алены 10.10.2026): между абзацами отступ
   в полстроки (0.8em при межстрочном 1.6), а не пустая строка; перенос внутри абзаца — как написан. Несколько
   пустых строк подряд сводит в один отступ сервер (`HubPeople::paragraphs()`). */
.km-hub .km-hub-about { font-size: 14px; line-height: 1.6; text-align: left; overflow-wrap: anywhere; color: var(--km-hub-ink); }
.km-hub p.km-hub-about__para { margin: 0; padding: 0; font-size: inherit; line-height: inherit; white-space: pre-line; }
.km-hub p.km-hub-about__para + p.km-hub-about__para { margin-top: 0.8em; }
.km-hub .km-hub-pcard__about {
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 8;
}
.km-hub p.km-hub-pcard__nums { display: flex; flex-wrap: wrap; gap: 4px 18px; margin: 0; font-size: 13px; line-height: 1.4; color: var(--km-hub-muted); }
.km-hub .km-hub-pcard__num { white-space: nowrap; }
.km-hub .km-hub-pcard__count { font-size: 16px; font-weight: 700; color: var(--km-hub-ink); }
.km-hub .km-hub-pcard__groups { display: flex; flex-direction: column; gap: 6px; }
.km-hub p.km-hub-pcard__label { margin: 0; font-size: 12px; font-weight: 700; line-height: 1.3; letter-spacing: 0.06em; text-transform: uppercase; color: var(--km-hub-muted); }
.km-hub .km-hub-pcard__chips { display: flex; flex-wrap: wrap; gap: 6px; }
.km-hub .km-hub-pcard__chip { max-width: 100%; box-sizing: border-box; padding: 4px 8px; border-radius: 6px; background: var(--km-hub-label); color: var(--km-hub-link); font-size: 13px; font-weight: 600; line-height: 1.35; overflow-wrap: anywhere; }

/* «Открыть профиль» в карточке человека (профили, этап 3; доска profile-v2): контурная во всю ширину карточки. */
.km-hub a.km-hub-pcard__open,
.km-hub a.km-hub-pcard__open:visited,
.km-hub a.km-hub-pcard__open:hover,
.km-hub a.km-hub-pcard__open:focus,
.km-hub a.km-hub-pcard__open:active {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 42px;
  box-sizing: border-box;
  border: 1px solid var(--km-hub-chip-line);
  border-radius: 10px;
  background: #fff;
  box-shadow: none;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  text-decoration: none;
}
.km-hub a.km-hub-pcard__open:hover { background: var(--km-hub-hover); }
/* Своя карточка — две кнопки рядом: «Открыть профиль» и «Изменить» (документ 1.56). */
.km-hub .km-hub-pcard__acts { display: flex; gap: 8px; }
.km-hub .km-hub-pcard__acts a.km-hub-pcard__open { flex: 1 1 0; min-width: 0; }
.km-hub a.km-hub-pcard__open:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }

/* «Подписаться» / «Вы подписаны» — подписка на человека (4.20; доска subscribe-v1): красная рядом с «Открыть профиль»,
   после нажатия — светло-сиреневая с галочкой. Кнопка — `button`: умолчание темы (радиус, рамка, тень, фон под курсором)
   снимается всеми состояниями сразу. Под курсором меняется только цвет. */
.km-hub button.km-hub-subscribe,
.km-hub button.km-hub-subscribe:hover,
.km-hub button.km-hub-subscribe:focus,
.km-hub button.km-hub-subscribe:active {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 42px;
  box-sizing: border-box;
  margin: 0;
  padding: 0 14px;
  border: 0;
  border-radius: 10px;
  background: var(--km-hub-red);
  box-shadow: none;
  color: #fff;
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  white-space: nowrap;
  cursor: pointer;
}
.km-hub button.km-hub-subscribe:hover { background: var(--km-hub-red-deep); }
.km-hub button.km-hub-subscribe[aria-pressed="true"],
.km-hub button.km-hub-subscribe[aria-pressed="true"]:focus,
.km-hub button.km-hub-subscribe[aria-pressed="true"]:active { background: var(--km-hub-soft); color: var(--km-hub-ink); font-weight: 800; }
.km-hub button.km-hub-subscribe[aria-pressed="true"]:hover { background: var(--km-hub-seg); color: var(--km-hub-ink); }
.km-hub button.km-hub-subscribe:disabled { opacity: 0.6; cursor: default; }
.km-hub button.km-hub-subscribe:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub .km-hub-subscribe__tick { flex: none; display: block; width: 16px; height: 16px; color: var(--km-hub-title); }
.km-hub .km-hub-pcard__acts button.km-hub-subscribe { flex: 1 1 0; min-width: 0; }
/* На странице профиля — во всю ширину карточки, под цифрами (доска, часть 2). */
.km-hub .km-hub-member__card button.km-hub-subscribe { align-self: stretch; margin-top: 6px; }
/* Строка отказа под кнопками; пустая места не занимает. */
.km-hub p.km-hub-pcard__status { margin: 0; font-size: 13px; line-height: 1.4; color: var(--km-hub-muted); }
.km-hub p.km-hub-pcard__status:empty { display: none; }
.km-hub p.km-hub-pcard__status.km-hub-status--error { color: var(--km-hub-red-deep); }

/* Профиль участника (профили, этап 3; доска profile-v2, раздел 2) — страница LMS `/treningi/profile/<имя>/`: шапка
   как у «Сообщества» (документ 1.64, `parts/hub-head.php`), слева карточка 300, справа «Посты» и «Комментарии»; уже 844 —
   друг под другом. */
.km-hub .km-hub-member { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 24px; min-width: 0; }
.km-hub .km-hub-member__side { flex: 0 0 300px; max-width: 100%; display: flex; flex-direction: column; gap: 16px; }
.km-hub .km-hub-member__main { flex: 1 1 520px; min-width: 0; display: flex; flex-direction: column; gap: 14px; }
.km-hub .km-hub-member__card { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 24px; border: 1px solid var(--km-hub-line); border-radius: 16px; background: #fff; text-align: center; }
.km-hub .km-hub-member__photo { display: block; flex: none; width: 120px; height: 120px; border-radius: 50%; object-fit: cover; }
.km-hub .km-hub-member__photo.km-hub-person--letters { display: flex; font-size: 38px; }
/* Имя в карточке — ступенью ниже заголовка шапки (документ 1.64). */
.km-hub h2.km-hub-member__name { margin: 0; padding: 0; font-family: var(--km-hub-display); font-size: 26px; font-weight: 500; line-height: 1.2; letter-spacing: normal; text-transform: none; color: var(--km-hub-title); overflow-wrap: anywhere; }
.km-hub p.km-hub-member__since { margin: 0; font-size: 13px; line-height: 1.4; color: var(--km-hub-muted); }
/* «О себе» — абзацами `.km-hub-about`, целиком; здесь только место в карточке. */
.km-hub .km-hub-member__about { align-self: stretch; }
/*
 * Награды за курсы — ряд знаков между «В сообществе с …» и «О себе» («Звёзды курса» 1.26, 6.9; макеты
 * `design/nagrady-profil-v1.dc.html`, `nagrady-telefon-v1.dc.html`, `nagrady-kartochka-v1.dc.html`). В профиле — по
 * центру, знак 38 в месте 44 под нажатие, промежуток 4, ряд переносится; во всплывающей карточке (`--card`) — прижат
 * влево, знак 32 в месте 40, промежуток 2. Знак — кнопка без ссылки: наведение меняет только подпись, сам знак
 * не двигается. Подпись — тёмная плашка над знаком со стрелкой вниз: при наведении (где наведение есть), при переходе
 * клавишей Tab (`:focus-visible`) и по нажатию (`is-open`, `community.js`). Кнопка — во всех состояниях: у темы свои
 * умолчания `button` (радиус, заливка, тень) в `:hover` и `:focus`.
 */
.km-hub .km-hub-awards { display: flex; flex-wrap: wrap; justify-content: center; gap: 4px; padding: 4px 0 2px; }
.km-hub .km-hub-awards--card { justify-content: flex-start; gap: 2px; margin: -4px 0 -4px -4px; padding: 0; }
.km-hub .km-hub-award { position: relative; display: inline-flex; }
.km-hub button.km-hub-award__btn,
.km-hub button.km-hub-award__btn:hover,
.km-hub button.km-hub-award__btn:focus,
.km-hub button.km-hub-award__btn:active { display: flex; align-items: center; justify-content: center; width: 44px; height: 44px; min-width: 0; padding: 0; border: 0; border-radius: 50%; background: none; box-shadow: none; color: inherit; cursor: default; }
.km-hub button.km-hub-award__btn:focus { outline: none; }
.km-hub button.km-hub-award__btn:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 0; }
.km-hub .km-hub-award__badge { display: block; flex: none; width: 38px; height: 38px; max-width: none; border-radius: 50%; object-fit: cover; }
.km-hub .km-hub-awards--card button.km-hub-award__btn,
.km-hub .km-hub-awards--card button.km-hub-award__btn:hover,
.km-hub .km-hub-awards--card button.km-hub-award__btn:focus,
.km-hub .km-hub-awards--card button.km-hub-award__btn:active { width: 40px; height: 40px; }
.km-hub .km-hub-awards--card .km-hub-award__badge { width: 32px; height: 32px; }
.km-hub .km-hub-award__tip {
  position: absolute;
  bottom: calc(100% + 6px);
  left: 50%;
  z-index: 5;
  box-sizing: border-box;
  width: max-content;
  max-width: 220px;
  padding: 7px 11px;
  border-radius: 8px;
  background: var(--km-hub-title);
  box-shadow: 0 6px 16px rgba(59, 42, 71, 0.25);
  color: #fff;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.4;
  text-align: center;
  white-space: normal;
  pointer-events: none;
  transform: translateX(-50%);
  display: none;
}
.km-hub .km-hub-award__tip::after { content: ""; position: absolute; top: 100%; left: 50%; margin-left: -6px; border-top: 6px solid var(--km-hub-title); border-right: 6px solid transparent; border-left: 6px solid transparent; }
.km-hub .km-hub-awards--card .km-hub-award__tip { left: 0; text-align: left; transform: none; }
.km-hub .km-hub-awards--card .km-hub-award__tip::after { left: 14px; margin-left: 0; }
/*
 * У края экрана подпись встаёт не по центру знака, а от его края — к середине (`--start` у левого края, `--end`
 * у правого), стрелка остаётся над знаком. Край меряет `community.js` в момент показа: длина названия и место знака
 * в ряду заранее неизвестны. Спрятанная подпись места не занимает (`display: none`) — иначе подпись крайнего знака
 * раздвигала бы страницу шире экрана (стенд 15.10.2026, 375: 412 px).
 */
.km-hub .km-hub-award--start .km-hub-award__tip { left: 0; text-align: left; transform: none; }
.km-hub .km-hub-award--start .km-hub-award__tip::after { left: 16px; margin-left: 0; }
.km-hub .km-hub-award--end .km-hub-award__tip { right: 0; left: auto; text-align: right; transform: none; }
.km-hub .km-hub-award--end .km-hub-award__tip::after { right: 16px; left: auto; margin-left: 0; }
.km-hub .km-hub-awards--card .km-hub-award--start .km-hub-award__tip::after { left: 14px; }
.km-hub .km-hub-awards--card .km-hub-award--end .km-hub-award__tip::after { right: 14px; }
.km-hub .km-hub-award__btn:focus-visible + .km-hub-award__tip,
.km-hub .km-hub-award.is-open .km-hub-award__tip { display: block; }
@media (hover: hover) {
  .km-hub .km-hub-award:hover .km-hub-award__tip { display: block; }
}
@media (max-width: 760px) {
  .km-hub .km-hub-award__tip { max-width: 210px; }
  .km-hub button.km-hub-award__btn,
  .km-hub button.km-hub-award__btn:hover,
  .km-hub button.km-hub-award__btn:focus,
  .km-hub button.km-hub-award__btn:active { cursor: pointer; }
}
.km-hub .km-hub-member__nums { align-self: stretch; display: flex; justify-content: center; gap: 22px; padding-top: 12px; border-top: 1px solid var(--km-hub-line-soft); font-size: 13px; line-height: 1.4; color: var(--km-hub-muted); }
.km-hub .km-hub-member__num { display: flex; flex-direction: column; }
.km-hub .km-hub-member__count { font-size: 20px; font-weight: 700; line-height: 1.3; color: var(--km-hub-ink); }
/* «Изменить профиль» на своей странице — во всю ширину карточки, как «Открыть профиль» во всплывающей. */
.km-hub .km-hub-member__edit { align-self: stretch; }
.km-hub .km-hub-member__box { display: flex; flex-direction: column; gap: 10px; padding: 18px; border: 1px solid var(--km-hub-line); border-radius: 16px; background: #fff; }
.km-hub .km-hub-member__switch { display: flex; flex-wrap: wrap; gap: 8px; }
/* Фильтры постов профиля (документ сообщества 1.57, доска my-profile-v1): группа выпадающим списком, темы — кнопки
   ленты, порядок — кнопка ленты; одной строкой: темы не переносятся, а прокручиваются вбок (на телефоне — как в ленте).
   Список группы и порядок стоят вне прокрутки — иначе их раскрытый список обрезался бы. */
.km-hub .km-hub-member__tools { align-items: center; gap: 10px; }
.km-hub .km-hub-gsel { position: relative; flex: none; }
.km-hub .km-hub-gsel__button {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 40px;
  box-sizing: border-box;
  max-width: 220px;
  padding: 0 12px 0 14px;
  border: 1px solid var(--km-hub-chip-line);
  border-radius: 10px;
  background: #fff;
  color: var(--km-hub-ink);
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  list-style: none;
  cursor: pointer;
}
.km-hub .km-hub-gsel__button::-webkit-details-marker { display: none; }
.km-hub .km-hub-gsel__label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.km-hub .km-hub-gsel__button .km-hub-icon { flex: none; width: 16px; height: 16px; }
.km-hub .km-hub-gsel[open] .km-hub-gsel__button { border-color: var(--km-hub-accent); }
/* Выбрана группа или «Только общая лента» — кнопка тонирована (доска): фильтр виден, не открывая список. */
.km-hub .km-hub-gsel--on .km-hub-gsel__button { border-color: var(--km-hub-chip-line); background: var(--km-hub-label); color: var(--km-hub-title); }
.km-hub .km-hub-gsel__list {
  position: absolute;
  top: 48px;
  left: 0;
  z-index: 6;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  width: 260px;
  max-height: 60vh;
  overflow-y: auto;
  padding: 6px;
  border: 1px solid var(--km-hub-line);
  border-radius: 12px;
  background: #fff;
  box-shadow: 0 8px 24px rgba(59, 42, 71, 0.14);
}
.km-hub button.km-hub-gsel__item,
.km-hub button.km-hub-gsel__item:focus,
.km-hub button.km-hub-gsel__item:active {
  display: flex;
  flex: none;
  align-items: center;
  width: 100%;
  min-height: 40px;
  margin: 0;
  padding: 8px 12px;
  border: 0;
  border-radius: 8px;
  background: none;
  box-shadow: none;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: normal;
  text-align: left;
  text-transform: none;
  cursor: pointer;
}
.km-hub button.km-hub-gsel__item:hover { border: 0; background: var(--km-hub-hover); box-shadow: none; color: var(--km-hub-ink); }
.km-hub button.km-hub-gsel__item[aria-selected="true"],
.km-hub button.km-hub-gsel__item[aria-selected="true"]:hover { background: var(--km-hub-pin); font-weight: 700; }
.km-hub button.km-hub-gsel__item:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: -2px; }
.km-hub p.km-hub-member__summary { margin: 0; font-size: 13px; line-height: 1.4; color: var(--km-hub-muted); }
.km-hub button.km-hub-member__tab,
.km-hub button.km-hub-member__tab:hover,
.km-hub button.km-hub-member__tab:focus,
.km-hub button.km-hub-member__tab:active {
  display: inline-flex;
  align-items: center;
  height: 38px;
  margin: 0;
  padding: 0 16px;
  border: 1px solid var(--km-hub-chip-line);
  border-radius: 9px;
  background: #fff;
  box-shadow: none;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  white-space: nowrap;
  cursor: pointer;
}
.km-hub button.km-hub-member__tab:hover { background: var(--km-hub-hover); }
/* Выбранная вкладка профиля — как выбранная группа в левой колонке ленты (`km-hub-nav__item--on`, слово Алены
   10.10.2026): тот же светло-сиреневый фон, тёмный жирный текст, без рамки. Рамка — цветом фона, а не снята:
   иначе вкладка сузилась бы на 2 px и соседи сдвигались бы при переключении. */
.km-hub button.km-hub-member__tab[aria-pressed="true"],
.km-hub button.km-hub-member__tab[aria-pressed="true"]:hover,
.km-hub button.km-hub-member__tab[aria-pressed="true"]:focus,
.km-hub button.km-hub-member__tab[aria-pressed="true"]:active { border-color: var(--km-hub-soft); background: var(--km-hub-soft); color: var(--km-hub-ink); font-weight: 700; }
.km-hub button.km-hub-member__tab:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub .km-hub-member__panel { display: flex; flex-direction: column; gap: 14px; }
.km-hub .km-hub-member__panel[hidden] { display: none; }
.km-hub .km-hub-member__list { display: flex; flex-direction: column; gap: 18px; }
.km-hub .km-hub-member__list:empty { display: none; }
.km-hub button.km-hub-member__more,
.km-hub button.km-hub-member__more:hover,
.km-hub button.km-hub-member__more:focus,
.km-hub button.km-hub-member__more:active {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  height: 42px;
  margin: 0;
  padding: 0 18px;
  border: 1px solid var(--km-hub-chip-line);
  border-radius: 10px;
  background: #fff;
  box-shadow: none;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  cursor: pointer;
}
.km-hub button.km-hub-member__more:hover { background: var(--km-hub-hover); }
.km-hub button.km-hub-member__more:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub button.km-hub-member__more:disabled { opacity: 0.6; cursor: default; }
.km-hub button.km-hub-member__more[hidden] { display: none; }

/* Комментарий во вкладке «Комментарии»: к какому посту и когда, ниже — текст, как под постом. */
.km-hub .km-hub-said { display: flex; flex-direction: column; gap: 8px; padding: 16px 18px; border: 1px solid var(--km-hub-line); border-radius: 14px; background: #fff; }
.km-hub p.km-hub-said__where { margin: 0; font-size: 13px; line-height: 1.45; color: var(--km-hub-muted); overflow-wrap: anywhere; }
.km-hub a.km-hub-said__post,
.km-hub a.km-hub-said__post:visited,
.km-hub a.km-hub-said__post:hover,
.km-hub a.km-hub-said__post:focus,
.km-hub a.km-hub-said__post:active { color: var(--km-hub-link); font-weight: 600; text-decoration: none; box-shadow: none; }
.km-hub a.km-hub-said__post:hover { text-decoration: underline; text-underline-offset: 3px; }

/* «Мой профиль» (профили, этап 4; доска profile-v2, раздел 3) — страница LMS `/treningi/my-profile/`: колонка 640,
   три карточки — «Профиль», «Почта и пароль», «Уведомления». Цвета и шрифты — сообщества: одна семья экранов.
   Кнопки и поля — с силой не меньше (0,2,1) и во всех состояниях: тема красит любой `button` и `input`. */
.km-page.km-me { padding-top: 32px; padding-bottom: 64px; background: transparent; color: var(--km-hub-ink); font-family: var(--km-hub-font); }
.km-me .km-me__inner { display: flex; flex-direction: column; gap: 18px; max-width: 640px; margin: 0 auto; }
/* Карточки настроек под шапкой (документ 1.64): шапка и строка «Править» — в `km-hub__inner`, как у «Сообщества».
   Ширина колонки — явно: у `km-hub__inner` поля `auto` и `container: inline-size`, и во флекс-колонке без неё он
   сжимался до нуля — шапка и карточки вставали полоской в 50 px. */
.km-me .km-me__inner > .km-hub__inner { width: 100%; }
.km-me .km-me__body { display: flex; flex-direction: column; gap: 18px; min-width: 0; }
.km-me h1.km-me__title { margin: 0; padding: 0; font-family: var(--km-hub-display); font-size: 32px; font-weight: 600; line-height: 1.15; letter-spacing: normal; text-transform: uppercase; color: var(--km-hub-title); }
.km-me .km-me__card { display: flex; flex-direction: column; gap: 18px; padding: 24px; border: 1px solid var(--km-hub-line); border-radius: 16px; background: #fff; }
.km-me h2.km-me__head { margin: 0; padding: 0; font-family: var(--km-hub-display); font-size: 22px; font-weight: 500; line-height: 1.2; letter-spacing: normal; text-transform: none; color: var(--km-hub-title); }
.km-me .km-me__face { display: flex; align-items: center; gap: 18px; }
.km-me .km-me__photo-box { display: block; flex: none; }
.km-me .km-me__photo { display: block; width: 96px; height: 96px; border-radius: 50%; object-fit: cover; }
.km-me .km-me__photo.km-hub-person--letters { display: flex; font-size: 30px; }
.km-me .km-me__face-side { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.km-me .km-me__acts { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.km-me .km-me__btn,
.km-me button.km-me__btn,
.km-me button.km-me__btn:hover,
.km-me button.km-me__btn:focus,
.km-me button.km-me__btn:active {
  display: inline-flex;
  align-items: center;
  box-sizing: border-box;
  height: 40px;
  margin: 0;
  padding: 0 16px;
  border: 1px solid var(--km-hub-chip-line);
  border-radius: 9px;
  background: #fff;
  box-shadow: none;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  white-space: nowrap;
  cursor: pointer;
}
.km-me .km-me__btn:hover,
.km-me button.km-me__btn:hover { background: var(--km-hub-hover); }
.km-me .km-me__face-side .km-me__btn { height: 38px; padding: 0 14px; }
.km-me input[type="file"]:focus-visible + .km-me__btn,
.km-me .km-me__btn:focus-visible,
.km-me button.km-me__btn:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-me button.km-me__btn--quiet,
.km-me button.km-me__btn--quiet:hover,
.km-me button.km-me__btn--quiet:focus,
.km-me button.km-me__btn--quiet:active { border-color: transparent; background: none; color: var(--km-hub-muted); font-weight: 600; }
.km-me button.km-me__btn--quiet:hover { color: var(--km-hub-ink); }
.km-me button.km-me__btn[hidden] { display: none; }

/* Кнопка-ссылка «Мой профиль» в личном кабинете (этап 4) — та же кнопка, что «Сменить пароль» на странице. Стоит
   на странице Elementor под темой: ссылки там красит тема, поэтому обёрткой, силой (0,2,1) и во всех состояниях;
   правило начинается с `.km-` — иначе встраиваемая таблица кабинета его не возьмёт. */
.km-me-entry { display: inline-flex; flex-wrap: wrap; gap: 8px; margin: 0; }
.km-me-entry a.km-me-link,
.km-me-entry a.km-me-link:visited,
.km-me-entry a.km-me-link:hover,
.km-me-entry a.km-me-link:focus,
.km-me-entry a.km-me-link:active {
  display: inline-flex;
  align-items: center;
  box-sizing: border-box;
  height: 40px;
  margin: 0;
  padding: 0 16px;
  border: 1px solid var(--km-hub-chip-line);
  border-radius: 9px;
  background: #fff;
  box-shadow: none;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: normal;
  text-decoration: none;
  text-transform: none;
  white-space: nowrap;
}
.km-me-entry a.km-me-link:hover { background: var(--km-hub-hover); }
.km-me-entry a.km-me-link:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
/* «Сохранить» — и кнопкой, и ссылкой: «Авторизуйтесь» у гостя на страницах профиля той же красной кнопкой (1.56). */
.km-me button.km-me__save,
.km-me button.km-me__save:hover,
.km-me button.km-me__save:focus,
.km-me button.km-me__save:active,
.km-me a.km-me__save,
.km-me a.km-me__save:visited,
.km-me a.km-me__save:hover,
.km-me a.km-me__save:focus,
.km-me a.km-me__save:active {
  display: inline-flex;
  text-decoration: none;
  align-items: center;
  box-sizing: border-box;
  height: 40px;
  margin: 0;
  padding: 0 16px;
  border: 0;
  border-radius: 9px;
  background: var(--km-hub-red);
  box-shadow: none;
  color: #fff;
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  white-space: nowrap;
  cursor: pointer;
}
.km-me button.km-me__save:hover,
.km-me a.km-me__save:hover { background: var(--km-hub-red-deep); }
.km-me button.km-me__save:focus-visible,
.km-me a.km-me__save:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-me button.km-me__save:disabled,
.km-me button.km-me__btn:disabled { opacity: 0.6; cursor: default; }
.km-me button.km-me__save--big,
.km-me button.km-me__save--big:hover,
.km-me button.km-me__save--big:focus,
.km-me button.km-me__save--big:active,
.km-me a.km-me__save--big,
.km-me a.km-me__save--big:visited,
.km-me a.km-me__save--big:hover,
.km-me a.km-me__save--big:focus,
.km-me a.km-me__save--big:active { height: 42px; padding: 0 20px; border-radius: 10px; }
.km-me form.km-me__form { display: flex; flex-direction: column; gap: 14px; margin: 0; }
.km-me form.km-me__form[hidden] { display: none; }
.km-me label.km-me__field { display: flex; flex-direction: column; gap: 6px; margin: 0; color: var(--km-hub-ink); font-size: 14px; font-weight: 700; line-height: 1.4; }
.km-me input.km-me__input,
.km-me input.km-me__input:focus,
.km-me textarea.km-me__input,
.km-me textarea.km-me__input:focus {
  box-sizing: border-box;
  width: 100%;
  height: 44px;
  margin: 0;
  padding: 0 12px;
  border: 1px solid var(--km-hub-chip-line);
  border-radius: 10px;
  background: #fff;
  box-shadow: none;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 15px;
  font-weight: 400;
  line-height: 1.4;
  outline: none;
}
.km-me textarea.km-me__area,
.km-me textarea.km-me__area:focus { height: auto; min-height: 100px; padding: 10px 12px; line-height: 1.55; resize: vertical; }
.km-me input.km-me__input:focus,
.km-me textarea.km-me__input:focus { border-color: var(--km-hub-accent); box-shadow: 0 0 0 3px var(--km-hub-soft); }
.km-me .km-me__hint { font-size: 13px; font-weight: 400; line-height: 1.5; color: var(--km-hub-muted); }
.km-me .km-me__hint--over { color: var(--km-hub-red-deep); }
.km-me p.km-me__hint { margin: 0; }
.km-me p.km-me__status { margin: 0; font-size: 13px; line-height: 1.5; color: var(--km-hub-muted); }
.km-me p.km-me__status:empty { display: none; }
.km-me p.km-me__status--error { color: var(--km-hub-red-deep); }
/* «Мои подписки» под таблицей уведомлений (подписка на человека; доска subscribe-v1, части 3 и 5): черта сверху, строки
   «фото 40 — имя — «Отписаться»». «Отписаться» — кнопка видом ссылки: тема красит любой `button`, состояния все. */
.km-me .km-me__subs { display: flex; flex-direction: column; gap: 10px; padding-top: 16px; border-top: 1px solid var(--km-hub-line); }
.km-me h3.km-me__subs-head { margin: 0; padding: 0; font-family: var(--km-hub-font); font-size: 16px; font-weight: 800; line-height: 1.3; letter-spacing: normal; text-transform: none; color: var(--km-hub-ink); }
.km-me .km-me__sub { display: flex; align-items: center; gap: 12px; min-width: 0; }
.km-me .km-me__sub-photo.km-hub-person--letters { font-size: 14px; }
.km-me .km-me__sub-name { flex: 1; min-width: 0; font-size: 15px; font-weight: 600; line-height: 1.3; color: var(--km-hub-ink); overflow-wrap: anywhere; }
.km-me button.km-me__unsub,
.km-me button.km-me__unsub:hover,
.km-me button.km-me__unsub:focus,
.km-me button.km-me__unsub:active {
  flex: none;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  color: var(--km-hub-link);
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: normal;
  text-transform: none;
  cursor: pointer;
}
.km-me button.km-me__unsub:hover { color: var(--km-hub-accent); text-decoration: underline; }
.km-me button.km-me__unsub:disabled { opacity: 0.6; cursor: default; }
.km-me button.km-me__unsub:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-me p.km-me__subs-empty { margin: 0; font-size: 14px; line-height: 1.55; color: var(--km-hub-chip-ink); }
.km-me p.km-me__note { margin: 0; padding: 10px 12px; border-radius: 10px; background: var(--km-hub-field); color: var(--km-hub-ink); font-size: 14px; line-height: 1.5; overflow-wrap: anywhere; }
.km-me p.km-me__note--warm { background: var(--km-hub-tag-peach-bg); }
.km-me p.km-me__note[hidden] { display: none; }
.km-me .km-me__group { display: flex; flex-direction: column; gap: 10px; }
.km-me .km-me__label { font-size: 14px; font-weight: 700; }
.km-me .km-me__value { font-size: 15px; overflow-wrap: anywhere; }
.km-me .km-me__line { height: 1px; background: var(--km-hub-line-soft); }
.km-me .km-me__row { display: flex; align-items: center; gap: 12px; }
.km-me .km-me__row-text { display: flex; flex: 1; flex-direction: column; gap: 2px; min-width: 0; }
.km-me .km-me__grid { display: flex; flex-direction: column; font-size: 14px; line-height: 1.4; }
.km-me .km-me__grid-row { display: grid; grid-template-columns: minmax(0, 1fr) 96px 72px; align-items: center; padding: 10px 0; border-top: 1px solid var(--km-hub-line-soft); }
/* Колонка «На телефон» (спецификация «Приложение на телефоне» 1.1, раздел 7; макет `prilozhenie-nastroyki-uvedomleniy-v2`). */
.km-me .km-me__grid--phone .km-me__grid-row { grid-template-columns: minmax(0, 1fr) 96px 72px 96px; }
.km-me .km-me__grid-row--head { padding: 0 0 4px; border-top: 0; }
.km-me .km-me__grid-row--head .km-me__grid-col { font-size: 12px; font-weight: 700; color: var(--km-hub-muted); }
.km-me .km-me__grid-name { min-width: 0; padding-right: 8px; overflow-wrap: anywhere; }
.km-me .km-me__grid-col { display: flex; justify-content: center; text-align: center; }
.km-me label.km-me__check { margin: 0; }
/*
 * Галочки уведомлений — как на доске `subscribe-v1`, часть 3 (и `profile-v2`): сливовые, с «✓» внутри (документ
 * сообщества 1.107). Общая галочка админки (`.km-check`) красит отмеченную в оранжевый и рисует «✓» вложенной
 * картинкой, которой в строке настроек нет, — на боевом выходил сплошной оранжевый квадрат. Здесь своя: «✓» —
 * знаком в `::after`, цвет — сливовый. Корень и класс строки сильнее общих правил, и порядок таблиц ей не важен.
 */
.km-me .km-me__check .km-check__box { box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; margin: 0; border: 1.5px solid #C9BFD0; border-radius: 6px; background: #fff; }
.km-me .km-me__check input:checked + .km-check__box { border-color: var(--km-hub-accent); background: var(--km-hub-accent); }
.km-me .km-me__check input:checked + .km-check__box::after { content: '✓'; color: #fff; font-family: var(--km-hub-font); font-size: 13px; font-weight: 800; line-height: 1; }
.km-me .km-me__check input:focus-visible + .km-check__box { box-shadow: 0 0 0 3px var(--km-hub-soft); }
.km-me .km-me__check:hover input:not(:checked) + .km-check__box { border-color: var(--km-hub-accent); }
.km-me .km-me__none { color: var(--km-hub-muted); }
/* Обязательное уведомление — пометкой «всегда», без галочки (документ сообщества 1.95). */
.km-me .km-me__always { font-size: 12px; font-weight: 700; color: var(--km-hub-muted); }
/* Текст приглашения войти (гость на страницах профиля, 1.56). */
.km-me p.km-me__text { margin: 0; font-size: 15px; line-height: 1.55; color: var(--km-hub-ink); }

/*
 * «Участники» (документ сообщества 1.107, «Все участники»; доска `members-v1`): на месте ленты, той же страницей.
 * Части ленты — одной обёрткой без своей коробки: она нужна скрипту, чтобы спрятать ленту одним узлом.
 */
.km-hub .km-hub-feedpart { display: contents; }
.km-hub .km-hub-feedpart[hidden] { display: none; }
.km-hub .km-hub-people { display: flex; flex-direction: column; gap: 18px; min-width: 0; }
.km-hub .km-hub-people[hidden] { display: none; }
.km-hub .km-hub-people__head { display: flex; align-items: baseline; gap: 12px; }
.km-hub h2.km-hub-people__title { margin: 0; padding: 0; font-family: var(--km-hub-display); font-size: 28px; font-weight: 500; line-height: 1.15; color: var(--km-hub-title); }
.km-hub .km-hub-people__count { font-size: 15px; color: var(--km-hub-muted); font-variant-numeric: tabular-nums; }
.km-hub .km-hub-people__tools { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.km-hub input.km-hub-people__search,
.km-hub input.km-hub-people__search:focus { flex: 1 1 260px; min-width: 0; box-sizing: border-box; height: 44px; margin: 0; padding: 0 14px; border: 1px solid var(--km-hub-chip-line); border-radius: 10px; background: #fff; box-shadow: none; color: var(--km-hub-ink); font-family: var(--km-hub-font); font-size: 15px; line-height: normal; }
.km-hub input.km-hub-people__search:focus { border-color: var(--km-hub-accent); outline: none; }
.km-hub .km-hub-people__sort { position: relative; flex: none; }
.km-hub .km-hub-sort__button.km-hub-people__sort-button { box-sizing: border-box; display: inline-flex; align-items: center; gap: 6px; width: auto; height: 44px; padding: 0 12px 0 14px; border: 1px solid var(--km-hub-chip-line); border-radius: 10px; background: #fff; color: var(--km-hub-ink); font-family: var(--km-hub-font); font-size: 14px; font-weight: 700; white-space: nowrap; }
.km-hub .km-hub-people__sort .km-hub-sort__list { top: 50px; width: 230px; }
.km-hub .km-hub-people__groups { display: flex; flex-wrap: wrap; gap: 8px; }
.km-hub .km-hub-people__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 14px; }
/* Обёртка карточки — место для всплывающего окна: оно встаёт под нажатым человеком, а не под всей сеткой (1.483.0).
   Карточка тянется на всю высоту ряда, как прежде, когда сама была ячейкой сетки. */
.km-hub .km-hub-people__item { position: relative; display: flex; flex-direction: column; min-width: 0; }
.km-hub .km-hub-people__item > button.km-hub-people__card { flex: 1 1 auto; }
.km-hub button.km-hub-people__card,
.km-hub button.km-hub-people__card:focus,
.km-hub button.km-hub-people__card:active,
.km-hub button.km-hub-people__card:hover {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  box-sizing: border-box;
  width: 100%;
  min-width: 0;
  height: auto;
  margin: 0;
  padding: 16px;
  border: 1px solid var(--km-hub-line);
  border-radius: 14px;
  background: #fff;
  box-shadow: none;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: normal;
  text-align: left;
  text-transform: none;
  cursor: pointer;
}
.km-hub button.km-hub-people__card:hover { border-color: var(--km-hub-chip-line); background: var(--km-hub-hover); }
.km-hub button.km-hub-people__card:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub .km-hub-people__photo { width: 56px; height: 56px; }
.km-hub .km-hub-people__photo.km-hub-person--letters { font-size: 18px; }
.km-hub .km-hub-people__body { display: flex; flex: 1; flex-direction: column; gap: 4px; min-width: 0; }
.km-hub .km-hub-people__name { font-size: 15px; font-weight: 700; color: var(--km-hub-ink); overflow-wrap: anywhere; }
.km-hub .km-hub-people__about { display: -webkit-box; overflow: hidden; -webkit-line-clamp: 2; -webkit-box-orient: vertical; font-size: 14px; line-height: 1.5; color: var(--km-hub-chip-ink); overflow-wrap: anywhere; }
.km-hub .km-hub-people__since { font-size: 12px; color: var(--km-hub-muted); }
.km-hub p.km-hub-people__empty { margin: 0; padding: 22px 18px; border: 1px solid var(--km-hub-line); border-radius: 14px; background: #fff; color: var(--km-hub-chip-ink); font-size: 15px; text-align: center; }
.km-hub p.km-hub-people__empty[hidden] { display: none; }
.km-hub button.km-hub-people__more,
.km-hub button.km-hub-people__more:focus,
.km-hub button.km-hub-people__more:active,
.km-hub button.km-hub-people__more:hover { align-self: center; box-sizing: border-box; height: 42px; margin: 0; padding: 0 22px; border: 1px solid var(--km-hub-chip-line); border-radius: 10px; background: #fff; box-shadow: none; color: var(--km-hub-ink); font-family: var(--km-hub-font); font-size: 14px; font-weight: 700; line-height: 1; letter-spacing: normal; text-transform: none; cursor: pointer; }
.km-hub button.km-hub-people__more:hover { border-color: var(--km-hub-accent); }
.km-hub button.km-hub-people__more[hidden] { display: none; }
@media (max-width: 760px) {
  /* Телефон (доска `members-v1`): карточки в один столбец, группы прокручиваются вбок. */
  .km-hub .km-hub-people__grid { grid-template-columns: minmax(0, 1fr); }
  .km-hub .km-hub-people__groups { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  .km-hub .km-hub-people__groups .km-hub-chip { flex: none; }
}

/* «Поддержали» — список: фото и имя, последние сверху; имя открывает карточку. */
.km-hub .km-hub-pop.km-hub-likers { gap: 12px; width: 300px; }
.km-hub p.km-hub-likers__title { margin: 0; padding-right: 32px; font-family: var(--km-hub-display); font-size: 20px; font-weight: 500; line-height: 1.2; color: var(--km-hub-title); }
.km-hub ul.km-hub-likers__list { display: flex; flex-direction: column; gap: 10px; max-height: 320px; margin: 0; padding: 0; overflow-y: auto; list-style: none; }
.km-hub li.km-hub-likers__row { display: flex; align-items: center; gap: 10px; min-width: 0; margin: 0; padding: 0; }
.km-hub .km-hub-likers__row > button.km-hub-likers__name,
.km-hub .km-hub-likers__row > button.km-hub-likers__name:hover,
.km-hub .km-hub-likers__row > button.km-hub-likers__name:focus,
.km-hub .km-hub-likers__row > button.km-hub-likers__name:active { min-width: 0; font-weight: 700; overflow-wrap: anywhere; }

/* Комментарии — доски feed-v2 и post-parts-v2: последний виден, ответы с отступом. */
.km-hub .km-hub-comments { display: flex; flex-direction: column; gap: 12px; padding: 14px 18px; border-top: 1px solid var(--km-hub-line-soft); border-radius: 0 0 14px 14px; background: var(--km-hub-field); }
.km-hub .km-hub-comment { display: flex; gap: 10px; min-width: 0; }
.km-hub .km-hub-comment[hidden] { display: none; }
.km-hub .km-hub-comment--reply { padding-left: 42px; }
.km-hub .km-hub-comment--reply2 { padding-left: 84px; }
.km-hub .km-hub-person--sm { width: 32px; height: 32px; font-size: 12px; }
.km-hub .km-hub-comment--reply .km-hub-person--sm,
.km-hub .km-hub-comment--reply2 .km-hub-person--sm { width: 28px; height: 28px; font-size: 11px; }
.km-hub .km-hub-comment__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.km-hub .km-hub-comment__head { position: relative; margin: 0; font-size: 14px; line-height: 1.4; color: var(--km-hub-ink); overflow-wrap: anywhere; }
.km-hub .km-hub-comment__name { font-weight: 700; }
.km-hub .km-hub-comment__when { font-weight: 400; color: var(--km-hub-muted); }
.km-hub .km-hub-comment__text { font-size: 14px; line-height: 1.55; color: var(--km-hub-ink); overflow-wrap: anywhere; }
.km-hub .km-hub-comment__text[hidden] { display: none; }
.km-hub .km-hub-comment__text > * { margin: 0; }
.km-hub .km-hub-comment__text > * + * { margin-top: 6px; }
.km-hub .km-hub-comment__text a { color: var(--km-hub-link); text-decoration: underline; }
.km-hub p.km-hub-comment__gone { margin: 0; font-size: 14px; font-style: italic; line-height: 1.55; color: var(--km-hub-muted); }
/* Ссылки — пунктами строки, которая переносится: каждая уходит на следующую строку целиком (доска to-post-v1, часть 6). */
.km-hub .km-hub-comment__acts { display: flex; flex-wrap: wrap; gap: 4px 14px; margin-top: 2px; }
.km-hub button.km-hub-comment__act,
.km-hub button.km-hub-comment__act:focus,
.km-hub button.km-hub-comment__act:active {
  height: auto;
  margin: 0;
  padding: 2px 0;
  border: 0;
  border-radius: 4px;
  background: none;
  box-shadow: none;
  color: var(--km-hub-muted);
  font-family: var(--km-hub-font);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: normal;
  text-transform: none;
  cursor: pointer;
}
.km-hub button.km-hub-comment__act:hover { border: 0; background: none; box-shadow: none; color: var(--km-hub-link); }
.km-hub button.km-hub-comment__act:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
/*
 * «Сделать постом» (доска to-post-v1, часть 1; документ сообщества 1.118) — последней в строке, сливовым и плотнее
 * соседних. Сильнее общего правила селектором, а не порядком (CLAUDE.md, «ничья по силе выигрывается порядком»).
 */
.km-hub .km-hub-comment__acts button.km-hub-comment__act--to-post,
.km-hub .km-hub-comment__acts button.km-hub-comment__act--to-post:hover,
.km-hub .km-hub-comment__acts button.km-hub-comment__act--to-post:focus,
.km-hub .km-hub-comment__acts button.km-hub-comment__act--to-post:active { color: var(--km-hub-link); font-weight: 800; }
/* Вынесен в отдельный пост (доска to-post-v1, часть 3): вместо текста — серая плашка со ссылкой на новый пост. */
.km-hub a.km-hub-comment__moved,
.km-hub a.km-hub-comment__moved:visited,
.km-hub a.km-hub-comment__moved:hover,
.km-hub a.km-hub-comment__moved:focus,
.km-hub a.km-hub-comment__moved:active,
.km-hub a.km-hub-post__from,
.km-hub a.km-hub-post__from:visited,
.km-hub a.km-hub-post__from:hover,
.km-hub a.km-hub-post__from:focus,
.km-hub a.km-hub-post__from:active {
  display: block;
  align-self: flex-start;
  width: fit-content;
  max-width: 100%;
  box-sizing: border-box;
  margin: 2px 0 0;
  padding: 8px 12px;
  border-radius: 8px;
  background: var(--km-hub-badge);
  box-shadow: none;
  color: var(--km-hub-muted);
  font-size: 14px;
  font-style: italic;
  font-weight: 400;
  line-height: 1.4;
  text-decoration: none;
  overflow-wrap: anywhere;
}
/* «Из комментариев к посту «…» →» над заголовком нового поста (часть 4) — тем же видом, чуть ниже ростом. */
.km-hub a.km-hub-post__from,
.km-hub a.km-hub-post__from:visited,
.km-hub a.km-hub-post__from:hover,
.km-hub a.km-hub-post__from:focus,
.km-hub a.km-hub-post__from:active { margin: 0; padding: 7px 12px; }
.km-hub a.km-hub-comment__moved:hover,
.km-hub a.km-hub-post__from:hover { color: var(--km-hub-link); }
.km-hub a.km-hub-comment__moved:focus-visible,
.km-hub a.km-hub-post__from:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
/* Окно «Сделать постом» (часть 2): автор строкой, место плашкой с «Изменить», текст комментария — цитатой, не полем. */
.km-hub .km-hub-convert__author { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; min-width: 0; font-size: 15px; line-height: 1.35; color: var(--km-hub-ink); }
.km-hub .km-hub-convert__author b { font-weight: 700; overflow-wrap: anywhere; }
.km-hub .km-hub-convert__when { color: var(--km-hub-muted); }
.km-hub .km-hub-convert__place { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; min-width: 0; }
.km-hub .km-hub-convert__chosen { display: inline-flex; align-items: center; max-width: 100%; min-height: 34px; box-sizing: border-box; padding: 0 12px; border-radius: 9px; background: var(--km-hub-soft); color: var(--km-hub-ink); font-size: 14px; font-weight: 600; line-height: 1.3; overflow-wrap: anywhere; }
.km-hub .km-hub-convert__chosen--empty { background: none; padding: 0; color: var(--km-hub-red); }
.km-hub button.km-hub-convert__change,
.km-hub button.km-hub-convert__change:hover,
.km-hub button.km-hub-convert__change:focus,
.km-hub button.km-hub-convert__change:active { height: auto; margin: 0; padding: 2px 0; border: 0; border-radius: 4px; background: none; box-shadow: none; color: var(--km-hub-link); font-family: var(--km-hub-font); font-size: 14px; font-weight: 700; line-height: 1.3; letter-spacing: normal; text-transform: none; cursor: pointer; }
.km-hub button.km-hub-convert__change:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub .km-hub-convert__place + .km-hub-where { margin-top: 12px; }
/* Выбор места свёрнут до «Изменить»; у куратора нет «Всего сообщества» — спрятанное прячется, а не перебивается `display`. */
.km-hub .km-hub-where[hidden],
.km-hub label.km-hub-switch[hidden] { display: none; }
.km-hub .km-hub-convert__quote { padding: 12px 14px; border-left: 3px solid var(--km-hub-line); border-radius: 0 8px 8px 0; background: var(--km-hub-field); font-size: 14px; line-height: 1.55; color: var(--km-hub-ink); overflow-wrap: anywhere; }
.km-hub .km-hub-convert__quote > * { margin: 0; }
.km-hub .km-hub-convert__quote > * + * { margin-top: 6px; }
.km-hub p.km-hub-comments__closed { margin: 0; font-size: 14px; color: var(--km-hub-muted); }
.km-hub .km-hub-comments .km-hub-status:empty { display: none; }
/* Строка «Написать комментарий…» — и ответ, и правка той же строкой. */
/*
 * Поле комментария и ответа — многострочное (слово Алены 09.10): в покое высотой в одну строку (42 px, как было),
 * растёт под текст числом строк из скрипта; «Отправить» — под полем, когда в нём есть текст. Лицо — по верху поля.
 * Тема подкладывает `textarea` свою высоту, поля и рамку — здесь объявлено всё, что она трогает.
 */
.km-hub form.km-hub-say { display: flex; align-items: flex-start; gap: 10px; min-width: 0; margin: 0; }
.km-hub form.km-hub-say > .km-hub-person { margin-top: 5px; }
.km-hub form.km-hub-say--inline { padding-left: 42px; }
.km-hub .km-hub-comment__main form.km-hub-say--inline { padding-left: 0; }
.km-hub .km-hub-say__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 8px; }
.km-hub textarea.km-hub-say__input,
.km-hub textarea.km-hub-say__input:hover {
  display: block;
  width: 100%;
  min-width: 0;
  height: auto;
  min-height: 42px;
  max-height: none;
  box-sizing: border-box;
  margin: 0;
  padding: 10px 14px;
  border: 1px solid var(--km-hub-line);
  border-radius: 10px;
  background: #fff;
  box-shadow: none;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 14px;
  line-height: 1.45;
  overflow: hidden;
  resize: none;
}
.km-hub textarea.km-hub-say__input:focus { border-color: var(--km-hub-accent); outline: none; box-shadow: 0 0 0 3px var(--km-hub-soft); }
.km-hub textarea.km-hub-say__input:disabled { opacity: 0.6; }
.km-hub .km-hub-say__acts { display: flex; align-items: center; gap: 8px; }
.km-hub .km-hub-say__acts[hidden] { display: none; }
.km-hub .km-hub-say button.km-hub-button.km-hub-button--sm,
.km-hub .km-hub-say button.km-hub-button.km-hub-button--sm:focus,
.km-hub .km-hub-say button.km-hub-button.km-hub-button--sm:active { height: 38px; padding: 0 16px; border-radius: 9px; font-size: 14px; font-weight: 700; }

/*
 * Смайлы в поле комментария — сообщества и «Обсуждения» (слово Алены 11.10.2026). Кнопка — в поле справа снизу;
 * панель — как всплывающие меню сообщества (`km-hub-menu__list`): белая карточка, рамка, скругление 12, тень; под
 * курсором и открытое — бледно-сиреневым (выбранное — без тёмной заливки). Панель прижата к правому краю поля и не
 * шире экрана без полей — на телефоне за экран не выходит; у нижнего края окна — вверх (`--up`, решает скрипт).
 * Под курсором меняется только цвет.
 */
.km-hub .km-hub-typing { position: relative; min-width: 0; }
/*
 * Подсказка — в одну строку: справа в поле место под кнопку смайлов (44 px), и в узком поле (карточка трансляции
 * на 375 — 157 px текста при 165 px подсказки) она переносилась на вторую строку, которую поле в одну строку
 * обрезало посередине букв (снимок боевого 11.10.2026). Не влезла — срезается хвост, строка одна.
 */
.km-hub textarea.km-hub-say__input::placeholder,
.km-hub textarea.km-hub-edit__field::placeholder { color: var(--km-hub-hint); opacity: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.km-hub .km-hub-typing > textarea.km-hub-say__input,
.km-hub .km-hub-typing > textarea.km-hub-say__input:hover,
.km-hub .km-hub-typing > textarea.km-hub-say__input:focus,
.km-hub .km-hub-typing > textarea.km-hub-edit__field,
.km-hub .km-hub-typing > textarea.km-hub-edit__field:focus { padding-right: 44px; }
.km-hub .km-hub-typing > button.km-hub-emoji,
.km-hub .km-hub-typing > button.km-hub-emoji:hover,
.km-hub .km-hub-typing > button.km-hub-emoji:focus,
.km-hub .km-hub-typing > button.km-hub-emoji:active {
  position: absolute;
  right: 6px;
  bottom: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  min-width: 0;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  box-shadow: none;
  color: var(--km-hub-hint);
  font-family: inherit;
  font-size: 14px;
  font-weight: 400;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  cursor: pointer;
}
/* Значок — как в строке действий: 19 px, контур (на телефоне 18 — ниже); под курсором темнее, у открытой панели —
   на бледно-сиреневом кружке, как выбранное. Двигается только цвет. */
.km-hub .km-hub-typing > button.km-hub-emoji .km-hub-icon { width: 19px; height: 19px; }
.km-hub .km-hub-typing > button.km-hub-emoji.km-hub-emoji:hover { background: none; color: var(--km-hub-muted); }
.km-hub .km-hub-typing > button.km-hub-emoji.km-hub-emoji[aria-expanded="true"] { background: var(--km-hub-soft); color: var(--km-hub-muted); }
.km-hub .km-hub-typing > button.km-hub-emoji:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 1px; }
.km-hub .km-hub-emoji-panel {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 6;
  box-sizing: border-box;
  display: grid;
  grid-template-columns: repeat(auto-fill, 34px);
  justify-content: center;
  gap: 2px;
  width: 300px;
  max-width: calc(100vw - 32px);
  padding: 6px;
  border: 1px solid var(--km-hub-line);
  border-radius: 12px;
  background: #fff;
  box-shadow: 0 8px 24px rgba(59, 42, 71, 0.12);
}
.km-hub .km-hub-emoji-panel.km-hub-emoji-panel--up { top: auto; bottom: calc(100% + 6px); }
/*
 * Узкое поле на телефоне (карточка трансляции на 375 — правый край поля в 74 px от края экрана): панель в 300 px,
 * прижатая к правому краю поля, вставала к самому краю экрана. Уже — по 7 смайлов в ряд, ещё уже — по 6; какая
 * нужна, решает скрипт по месту слева (поле экрана 16 px).
 */
.km-hub .km-hub-emoji-panel.km-hub-emoji-panel--narrow { width: 264px; }
.km-hub .km-hub-emoji-panel.km-hub-emoji-panel--narrowest { width: 228px; }
.km-hub .km-hub-emoji-panel > button.km-hub-emoji-panel__item,
.km-hub .km-hub-emoji-panel > button.km-hub-emoji-panel__item:hover,
.km-hub .km-hub-emoji-panel > button.km-hub-emoji-panel__item:focus,
.km-hub .km-hub-emoji-panel > button.km-hub-emoji-panel__item:active {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  min-width: 0;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: none;
  box-shadow: none;
  color: inherit;
  font-family: inherit;
  font-size: 20px;
  font-weight: 400;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  cursor: pointer;
}
.km-hub .km-hub-emoji-panel > button.km-hub-emoji-panel__item.km-hub-emoji-panel__item:hover,
.km-hub .km-hub-emoji-panel > button.km-hub-emoji-panel__item.km-hub-emoji-panel__item:focus-visible { background: var(--km-hub-hover); }
.km-hub .km-hub-emoji-panel > button.km-hub-emoji-panel__item:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: -2px; }

/*
 * «Обсуждение» — комментарии страницы, сменяющие wpDiscuz (план принят Аленой 11.10.2026; вид — «как комментарии
 * в сообществе», п. 12). Строка, поле и кнопки — классы комментариев сообщества выше; здесь только рамка блока:
 * карточкой, как пост, поле сверху, ветки новые сверху, «Загрузить ещё» под ними.
 */
.km-hub.km-hub-discuss { display: flex; flex-direction: column; gap: 14px; margin: 0; padding: 20px 22px; border: 1px solid var(--km-hub-line); border-radius: 14px; background: #fff; color: var(--km-hub-ink); font-family: var(--km-hub-font); }
.km-hub h2.km-hub-discuss__title { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; margin: 0; font-family: var(--km-hub-display); font-size: 24px; font-weight: 500; line-height: 1.2; letter-spacing: normal; text-transform: none; color: var(--km-hub-title); }
.km-hub .km-hub-discuss__count { font-family: var(--km-hub-font); font-size: 15px; font-weight: 600; line-height: 1.2; color: var(--km-hub-muted); }
.km-hub .km-hub-discuss__count[hidden] { display: none; }
.km-hub .km-hub-discuss__list { display: flex; flex-direction: column; gap: 18px; min-width: 0; }
.km-hub .km-hub-discuss__thread { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.km-hub p.km-hub-discuss__empty { margin: 0; font-size: 14px; line-height: 1.5; color: var(--km-hub-muted); }
.km-hub p.km-hub-discuss__empty[hidden] { display: none; }
.km-hub button.km-hub-discuss__more { align-self: flex-start; }
.km-hub button.km-hub-discuss__more[hidden] { display: none; }
.km-hub.km-hub-discuss .km-hub-status:empty { display: none; }
/* Внутри чужой карточки (трансляция, закрытый эфир): заголовок и рамку даёт она. */
.km-hub.km-hub-discuss--bare { padding: 0; border: 0; border-radius: 0; background: none; }

/*
 * Закреп и картинки в комментариях («Сообщество» 1.128; доска «Комментарии: закреп и картинки — вариант 1»,
 * `design/kommentarii-zakrep-v1.dc.html`, `-telefon-v1`, `-lenta-v1`). Строка и поле — общие у сообщества
 * и «Обсуждения», поэтому и вид один.
 *
 * Закреплённый стоит первым, в светло-сиреневой рамке; «Закреплено» с булавкой (знак закреплённого поста) — в строке
 * имени справа, на телефоне — отдельной строкой над именем, справа. Цвета: на страницах трансляций и занятий —
 * доски, в сообществе — закреплённого поста (`--km-hub-pin-strip`, `--km-hub-pin-strip-line`, `--km-hub-link`).
 * «Закрепить» и «Открепить» — последними в строке, сливовым и плотнее соседних, как «Сделать постом».
 */
:root {
  --km-hub-comment-pin: #F7F2F9;
  --km-hub-comment-pin-line: #E6DAEE;
  --km-hub-comment-pin-ink: #6B4C7C;
  /* Значок картинки, когда картинок уже четыре: погасший — светлее обычного серого (доска: #D4CEDA). */
  --km-hub-comment-pic-off: #D4CEDA;
}
.km-hub .km-hub-post { --km-hub-comment-pin: var(--km-hub-pin-strip); --km-hub-comment-pin-line: var(--km-hub-pin-strip-line); --km-hub-comment-pin-ink: var(--km-hub-link); }
/* Рамка — у ветки: закреплённый и ответы под ним (доска); в ленте под постом — плотнее (доска «Лента сообщества»). */
.km-hub .km-hub-discuss__thread.km-hub-discuss__thread--pinned { margin: 0 -18px; padding: 16px 18px; border: 1px solid var(--km-hub-comment-pin-line); border-radius: 12px; background: var(--km-hub-comment-pin); }
.km-hub .km-hub-post .km-hub-discuss__thread.km-hub-discuss__thread--pinned { margin: 0 -8px; padding: 12px 10px; }
.km-hub .km-hub-comment__pin,
.km-hub .km-hub-discuss__pinned { display: inline-flex; align-items: center; gap: 6px; color: var(--km-hub-comment-pin-ink); font-size: 13px; font-weight: 700; line-height: 1.4; }
.km-hub .km-hub-comment__pin { float: right; margin: 0 0 0 12px; }
.km-hub .km-hub-comment__pin .km-hub-icon,
.km-hub .km-hub-discuss__pinned .km-hub-icon { width: 14px; height: 14px; }
/* Строка «Закреплено» над именем — только на телефоне; на компьютере она в строке имени справа. */
.km-hub .km-hub-discuss__pinned { display: none; }
.km-hub .km-hub-comment__acts button.km-hub-comment__act--pin,
.km-hub .km-hub-comment__acts button.km-hub-comment__act--pin:hover,
.km-hub .km-hub-comment__acts button.km-hub-comment__act--pin:focus,
.km-hub .km-hub-comment__acts button.km-hub-comment__act--pin:active { color: var(--km-hub-comment-pin-ink); font-weight: 800; }

/*
 * Картинки комментария — под текстом в ряд: высота 140 px (на телефоне 110), ширина по пропорциям, без обрезки
 * и искажения; не влезли — на следующую строку. Нажатие — просмотр на весь экран (`hub-viewer.js`).
 */
.km-hub .km-hub-comment__pics { display: flex; flex-wrap: wrap; gap: 6px; min-width: 0; padding-top: 4px; }
.km-hub button.km-hub-comment__pic,
.km-hub button.km-hub-comment__pic:hover,
.km-hub button.km-hub-comment__pic:focus,
.km-hub button.km-hub-comment__pic:active {
  display: block;
  flex: none;
  max-width: 100%;
  height: auto;
  min-height: 0;
  margin: 0;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--km-hub-line);
  border-radius: 10px;
  background: none;
  box-shadow: none;
  line-height: 0;
  cursor: zoom-in;
}
.km-hub button.km-hub-comment__pic:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub .km-hub-comment__pic img { display: block; width: auto; max-width: 100%; height: 140px; margin: 0; border-radius: 0; box-shadow: none; object-fit: contain; }

/*
 * Поле: значок картинки — рядом со смайликом, той же кнопкой (`km-hub-emoji`: размер и цвет — смайлика), левее
 * на её ширину; на четвёртой картинке гаснет. Картинки до отправки — под текстом внутри поля миниатюрами 64×64,
 * у каждой тёмный кружок с крестиком — убрать: полоса миниатюр продолжает рамку поля вниз (`--filled`).
 */
.km-hub .km-hub-typing.km-hub-typing--pics > textarea.km-hub-say__input,
.km-hub .km-hub-typing.km-hub-typing--pics > textarea.km-hub-say__input:hover,
.km-hub .km-hub-typing.km-hub-typing--pics > textarea.km-hub-say__input:focus,
.km-hub .km-hub-typing.km-hub-typing--pics > textarea.km-hub-edit__field,
.km-hub .km-hub-typing.km-hub-typing--pics > textarea.km-hub-edit__field:focus { padding-right: 76px; }
.km-hub .km-hub-typing > button.km-hub-emoji.km-hub-emoji--pic,
.km-hub .km-hub-typing > button.km-hub-emoji.km-hub-emoji--pic:hover,
.km-hub .km-hub-typing > button.km-hub-emoji.km-hub-emoji--pic:focus,
.km-hub .km-hub-typing > button.km-hub-emoji.km-hub-emoji--pic:active { right: 38px; }
.km-hub .km-hub-typing > button.km-hub-emoji.km-hub-emoji--pic.km-hub-emoji--pic:disabled,
.km-hub .km-hub-typing > button.km-hub-emoji.km-hub-emoji--pic.km-hub-emoji--pic:disabled:hover { background: none; color: var(--km-hub-comment-pic-off); cursor: default; }
.km-hub .km-hub-typing.km-hub-typing--filled > textarea.km-hub-say__input,
.km-hub .km-hub-typing.km-hub-typing--filled > textarea.km-hub-say__input:hover,
.km-hub .km-hub-typing.km-hub-typing--filled > textarea.km-hub-say__input:focus,
.km-hub .km-hub-typing.km-hub-typing--filled > textarea.km-hub-edit__field,
.km-hub .km-hub-typing.km-hub-typing--filled > textarea.km-hub-edit__field:focus { border-bottom-color: transparent; border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.km-hub .km-hub-say__pics { display: flex; flex-wrap: wrap; gap: 10px; min-width: 0; margin-top: -8px; padding: 4px 14px 12px; border: 1px solid var(--km-hub-line); border-top: 0; border-radius: 0 0 10px 10px; background: #fff; }
.km-hub .km-hub-say__pics[hidden] { display: none; }
.km-hub .km-hub-edit .km-hub-say__pics { border-color: var(--km-hub-accent); }
.km-hub .km-hub-say__pic { position: relative; flex: none; width: 64px; height: 64px; }
.km-hub .km-hub-say__pic img { display: block; width: 64px; height: 64px; box-sizing: border-box; margin: 0; border: 1px solid var(--km-hub-line); border-radius: 8px; object-fit: cover; }
/* Пока грузится — бледнее: «Отправить» ждёт, пока все дойдут до сервера. */
.km-hub .km-hub-say__pic.km-hub-say__pic--wait img { opacity: 0.5; }
.km-hub button.km-hub-say__unpic,
.km-hub button.km-hub-say__unpic:hover,
.km-hub button.km-hub-say__unpic:focus,
.km-hub button.km-hub-say__unpic:active {
  position: absolute;
  top: -8px;
  right: -8px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  min-width: 0;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 2px solid #fff;
  border-radius: 50%;
  background: var(--km-hub-title);
  box-shadow: none;
  color: #fff;
  line-height: 1;
  cursor: pointer;
}
.km-hub button.km-hub-say__unpic:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 1px; }
.km-hub button.km-hub-say__unpic .km-hub-icon { width: 10px; height: 10px; stroke-width: 3.2; }
/* Файл тянут в поле — рамка поля светлеет: сюда можно бросить. */
.km-hub .km-hub-typing.km-hub-typing--drop > textarea.km-hub-say__input,
.km-hub .km-hub-typing.km-hub-typing--drop > textarea.km-hub-edit__field { border-color: var(--km-hub-accent); background: var(--km-hub-hover); }

@media (max-width: 760px) {
  .km-hub .km-hub-discuss__thread.km-hub-discuss__thread--pinned,
  .km-hub .km-hub-post .km-hub-discuss__thread.km-hub-discuss__thread--pinned { gap: 8px; margin: 0 -8px; padding: 12px 8px 14px; }
  .km-hub .km-hub-comment__pin { display: none; }
  .km-hub .km-hub-discuss__pinned { display: flex; justify-content: flex-end; font-size: 12px; }
  .km-hub .km-hub-discuss__pinned .km-hub-icon { width: 13px; height: 13px; }
  .km-hub .km-hub-comment__pic img { height: 110px; }
}
/*
 * Вход на месте поля «Обсуждения» (слово Алены 11.10.2026) — штатная форма WordPress `wp_login_form()`
 * (`p.login-username`, `p.login-password`, `input.input`, `p.login-submit`, `input.button-primary`) в наших полях:
 * подписи сверху, поля — как поле комментария, «Войти» — основная кнопка сообщества. Тема сайта красит поля и кнопки
 * сама, поэтому здесь объявлено всё, что она трогает. Под курсором меняется только цвет.
 */
.km-hub .km-hub-login { display: flex; flex-direction: column; gap: 10px; max-width: 420px; min-width: 0; }
.km-hub .km-hub-login form { display: flex; flex-direction: column; gap: 12px; margin: 0; padding: 0; }
.km-hub .km-hub-login form p { margin: 0; padding: 0; }
.km-hub .km-hub-login form label { display: block; margin: 0 0 6px; font-family: var(--km-hub-font); font-size: 13px; font-weight: 600; line-height: 1.3; color: var(--km-hub-muted); }
.km-hub .km-hub-login input.input,
.km-hub .km-hub-login input.input:hover,
.km-hub .km-hub-login input.input:focus {
  display: block;
  width: 100%;
  min-width: 0;
  height: 42px;
  box-sizing: border-box;
  margin: 0;
  padding: 0 14px;
  border: 1px solid var(--km-hub-line);
  border-radius: 10px;
  background: #fff;
  box-shadow: none;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 14px;
  line-height: 40px;
}
.km-hub .km-hub-login input.input:focus { border-color: var(--km-hub-accent); outline: none; box-shadow: 0 0 0 3px var(--km-hub-soft); }
.km-hub .km-hub-login input.button-primary,
.km-hub .km-hub-login input.button-primary:focus,
.km-hub .km-hub-login input.button-primary:active {
  height: 38px;
  margin: 0;
  padding: 0 22px;
  border: 1px solid var(--km-hub-red);
  border-radius: 9px;
  background: var(--km-hub-red);
  box-shadow: none;
  color: #fff;
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  text-shadow: none;
  cursor: pointer;
}
.km-hub .km-hub-login input.button-primary:hover { border-color: var(--km-hub-red-deep); background: var(--km-hub-red-deep); color: #fff; box-shadow: none; }
.km-hub .km-hub-login input.button-primary:disabled { opacity: 0.6; cursor: default; }
.km-hub .km-hub-login input.button-primary:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
/*
 * Окно «Войдите» гостю сообщества (документ сообщества 1.92, «Гость в сообществе»): та же форма, что у поля
 * комментария «Ключей» (`.km-hub-login` выше), в окне сообщества (`.km-hub-modal`, как у знакомства). Узкое: в нём
 * только форма. Ссылки «Забыли пароль?» и «Зарегистрироваться» — строкой под формой.
 */
.km-hub .km-hub-dialog--login { width: 440px; }
.km-hub .km-hub-dialog--login .km-hub-login { max-width: none; }
.km-hub p.km-hub-login__lead { margin: 0; font-family: var(--km-hub-font); font-size: 15px; line-height: 1.5; color: var(--km-hub-ink); }
.km-hub .km-hub-login__links { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 20px; }
.km-hub a.km-hub-login__lost,
.km-hub a.km-hub-login__lost:visited { align-self: flex-start; font-family: var(--km-hub-font); font-size: 13px; color: var(--km-hub-muted); text-decoration: underline; }
.km-hub a.km-hub-login__lost:hover { color: var(--km-hub-ink); }
/*
 * На компьютере (слово Алены 11.10.2026) — две строки: «Почта или логин» и «Пароль» рядом, в колонках одинаковой
 * ширины; под ними «Войти» и рядом «Забыли пароль?»; ошибка — под ними. На телефоне — столбиком, как выше.
 * Разметка штатная и одна на оба вида: форма `wp_login_form()`, а ссылка и строка ошибки — после неё, вне формы
 * (`discuss.php`). Чтобы ссылка встала в строку кнопки, форма здесь — `display: contents`: её абзацы становятся
 * рядами общего блока, а строка ошибки уходит в конец порядком. Отправку, поля и подписи это не трогает — форма
 * остаётся формой, меняется только раскладка.
 */
@media (min-width: 761px) {
  .km-hub .km-hub-login { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 12px 16px; max-width: 600px; }
  .km-hub .km-hub-login form { display: contents; }
  .km-hub .km-hub-login p.login-username,
  .km-hub .km-hub-login p.login-password { flex: 1 1 calc(50% - 9px); min-width: 0; }
  .km-hub .km-hub-login .km-hub-status { order: 1; flex: 1 1 100%; }
  .km-hub a.km-hub-login__lost,
  .km-hub a.km-hub-login__lost:visited { align-self: center; }
}
@media (max-width: 760px) {
  .km-hub.km-hub-discuss { padding: 16px 14px; }
  .km-hub.km-hub-discuss--bare { padding: 0; }
  .km-hub h2.km-hub-discuss__title { font-size: 22px; }
}

/* Пост по ссылке — та же страница; «Вся лента» — обратно, на месте. */
.km-hub .km-hub-single { display: flex; }
.km-hub button.km-hub-back,
.km-hub button.km-hub-back:focus,
.km-hub button.km-hub-back:active {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 40px;
  margin: 0;
  padding: 0 14px 0 10px;
  border: 1px solid var(--km-hub-line);
  border-radius: 10px;
  background: #fff;
  box-shadow: none;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  cursor: pointer;
}
.km-hub button.km-hub-back:hover { border-color: var(--km-hub-chip-line); background: var(--km-hub-hover); box-shadow: none; color: var(--km-hub-ink); }
.km-hub button.km-hub-back:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }

/* Средняя ширина (окно примерно 760–1136 px; слово Алены 8 октября 2026: «частые размеры экрана»).
   Трём колонкам нужно 220 + 560 + 260 и два промежутка — 1096 px страницы; уже — правая колонка
   уезжала под бесконечную ленту и пропадала. Здесь «Ближайший эфир» встаёт в левую колонку под
   группами. Мерится ширина самой страницы сообщества, а не окна: тема даёт свои поля. Телефон
   (до 760) возвращает свою раскладку ниже. */
@container km-hub (max-width: 1095.98px) {
  .km-hub .km-hub__cols { display: grid; grid-template-columns: 220px minmax(0, 1fr); grid-template-rows: auto 1fr; gap: 26px 28px; align-items: start; }
  .km-hub .km-hub__cols > .km-hub-nav { grid-column: 1; grid-row: 1; max-width: none; }
  .km-hub .km-hub__cols > .km-hub-main { grid-column: 2; grid-row: 1 / span 2; }
  .km-hub .km-hub__cols > .km-hub-aside { grid-column: 1; grid-row: 2; max-width: none; }
}

@media (max-width: 760px) {
  /* Сверху под шапкой — 16, как поля по бокам (правки Алены 15.10.2026 после проверки на iPhone: страницы нижнего меню). */
  .km-page.km-hub { padding-top: 16px; padding-bottom: 40px; }
  /* Плашка на телефоне та же; длинное название — многоточием (доска lesson-posts). */
  .km-hub .km-hub-lesson-tag__text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; overflow-wrap: normal; }
  .km-hub.km-hub-lesson--empty { padding: 18px 16px; }
  /* Подвал окна на телефоне: «Запланировать» — своей строкой, иначе три кнопки не помещаются (этап 6). */
  .km-hub .km-hub-dialog__foot { flex-wrap: wrap; }
  .km-hub .km-hub-dialog__foot button.km-hub-plan-toggle,
  .km-hub .km-hub-dialog__foot button.km-hub-plan-toggle:focus,
  .km-hub .km-hub-dialog__foot button.km-hub-plan-toggle:active { flex: 1 1 100%; justify-content: center; margin-right: 0; }
  .km-hub .km-hub__inner { gap: 14px; }
  .km-hub p.km-hub__eyebrow { display: none; }
  .km-hub h1.km-hub__title { font-size: 28px; }
  .km-hub .km-hub__cols { display: flex; gap: 14px; }
  .km-hub .km-hub-nav { display: none; }
  .km-hub .km-hub-aside { display: none; }
  .km-hub .km-hub__head { flex-wrap: nowrap; align-items: center; }
  .km-hub .km-hub__titles { flex: 1; min-width: 0; }
  .km-hub button.km-hub-write,
  .km-hub button.km-hub-write:focus,
  .km-hub button.km-hub-write:active,
  .km-hub a.km-hub-write,
  .km-hub a.km-hub-write:visited,
  .km-hub a.km-hub-write:focus,
  .km-hub a.km-hub-write:active { justify-content: center; width: 46px; padding: 0; border-radius: 12px; }
  .km-hub .km-hub-write__label { display: none; }
  .km-hub .km-hub__head.km-hub__head--stack { flex-wrap: wrap; }
  .km-hub .km-hub__head--stack .km-hub__titles { flex: 1 1 100%; }
  .km-hub a.km-hub-write.km-hub-write--plain,
  .km-hub a.km-hub-write.km-hub-write--plain:visited,
  .km-hub a.km-hub-write.km-hub-write--plain:focus,
  .km-hub a.km-hub-write.km-hub-write--plain:active,
  .km-hub a.km-hub-write.km-hub-write--plain:hover { width: 100%; height: 42px; padding: 0 18px; border-radius: 10px; }
  .km-hub .km-hub-write--plain .km-hub-write__label { display: inline; }
  .km-hub .km-hub-write .km-hub-icon { width: 20px; height: 20px; }
  .km-hub button.km-hub-prompt { display: none; }
  .km-hub .km-hub-tools { align-items: center; gap: 8px; }
  .km-hub .km-hub-post__body { gap: 10px; padding: 14px; }
  .km-hub .km-hub-post__place,
  .km-hub .km-hub-post__meta { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* Строка трансляции «Трансляция · поток «…»» переносится на вторую строку, а не обрезается (задача Алены 11.10). */
  .km-hub .km-hub-post__meta.km-hub-post__meta--wrap { white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere; }
  .km-hub .km-hub-post__tag,
  .km-hub .km-hub-post__ago { display: none; }
  .km-hub .km-hub-post__ago-short,
  .km-hub .km-hub-post__metatag { display: inline; }
  .km-hub .km-hub-post__tag-below { display: inline-block; align-self: flex-start; padding: 4px 9px; font-size: 12px; }
  /* Закреплённый на телефоне: в полосе слева тема, справа «Закреплено»; в шапке темы тогда нет (доска pinned-v1). */
  .km-hub .km-hub-post__pin { justify-content: space-between; padding: 9px 14px; }
  .km-hub .km-hub-post__pin-tag { display: inline-block; min-width: 0; max-width: 60%; padding: 3px 8px; overflow: hidden; font-size: 12px; text-overflow: ellipsis; white-space: nowrap; }
  .km-hub .km-hub-post--pinned .km-hub-post__metatag,
  .km-hub .km-hub-post--pinned .km-hub-post__tag-below { display: none; }
  .km-hub h2.km-hub-post__title { font-size: 20px; }
  .km-hub .km-hub-menu__button { width: 40px; height: 40px; margin-right: -8px; }
  .km-hub .km-hub-menu__list { width: 240px; }
  .km-hub .km-hub-modal { padding: 0; }
  .km-hub .km-hub-dialog { min-height: 100%; border-radius: 0; }
  .km-hub .km-hub-dialog--welcome { width: 100%; border-radius: 0; box-shadow: none; }
  .km-hub .km-hub-welcome__top { padding: 16px 16px 0; }
  .km-hub .km-hub-welcome__pane { padding: 14px 16px 24px; }
  .km-hub .km-hub-dialog__head,
  .km-hub .km-hub-dialog__body,
  .km-hub .km-hub-dialog__foot { padding-left: 16px; padding-right: 16px; }
  .km-hub .km-hub-main { flex-basis: 100%; gap: 14px; }
  .km-hub .km-hub-pick { display: block; }
  /* Темы — в строку и вбок (документ сообщества: «на телефоне фильтр прокручивается вбок»). */
  .km-hub .km-hub-chips { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  .km-hub .km-hub-chips::-webkit-scrollbar { display: none; }
  .km-hub button.km-hub-chip,
  .km-hub button.km-hub-chip:focus,
  .km-hub button.km-hub-chip:active { height: 38px; padding: 0 14px; }
  .km-hub .km-hub-gallery { border-radius: 10px; }
  .km-hub .km-hub-viewer { padding: 56px 8px 64px; }
  .km-hub button.km-hub-viewer__nav { top: auto; bottom: 8px; }
  .km-hub button.km-hub-viewer__nav--prev { left: 8px; }
  .km-hub button.km-hub-viewer__nav--next { right: 8px; }
  .km-hub p.km-hub-viewer__count { bottom: 22px; }
  .km-hub .km-hub-link__image { width: 88px; min-height: 88px; }
  .km-hub button.km-hub-tool,
  .km-hub button.km-hub-tool:focus,
  .km-hub button.km-hub-tool:active { padding: 0 12px; }
  /* Телефон (доска mobile-v3): под постом — знаки и числа, без слов. */
  .km-hub .km-hub-acts { padding: 4px 6px; }
  .km-hub .km-hub-act,
  .km-hub button.km-hub-act,
  .km-hub button.km-hub-act:focus,
  .km-hub button.km-hub-act:active { gap: 6px; height: 44px; padding: 0 10px; }
  .km-hub .km-hub-act__word,
  .km-hub .km-hub-act__dot,
  .km-hub .km-hub-act__dot[hidden] { display: none; }
  .km-hub .km-hub-act--follow { justify-content: center; width: 44px; padding: 0; }
  .km-hub .km-hub-act .km-hub-icon { width: 18px; height: 18px; }
  .km-hub .km-hub-typing > button.km-hub-emoji .km-hub-icon { width: 18px; height: 18px; }
  /* «Мой профиль» на телефоне: карточки уже, колонки галочек — уже. */
  .km-page.km-me { padding-top: 18px; padding-bottom: 40px; }
  .km-me h1.km-me__title { font-size: 28px; }
  /* Профиль на телефоне: кнопка группы уже — темам остаётся место для прокрутки вбок. */
  .km-hub .km-hub-gsel__button { max-width: 150px; }
  .km-me .km-me__card { padding: 20px 16px; }
  .km-me .km-me__grid-row { grid-template-columns: minmax(0, 1fr) 84px 56px; }
  .km-me .km-me__grid--phone .km-me__grid-row { grid-template-columns: minmax(0, 1fr) 74px 48px 62px; }
  .km-me .km-me__grid--phone .km-me__grid-row--head .km-me__grid-col { font-size: 11px; line-height: 1.25; }
  /* Профиль участника на телефоне: карточка сверху во всю ширину, посты под ней (доска profile-v2). */
  .km-hub .km-hub-member__side { flex-basis: 100%; }
  .km-hub .km-hub-member__card { padding: 20px 16px; }
  /* Имя в шапке поста — одной строкой, не влезшее — многоточием у самой кнопки (у кнопки свой блок). */
  .km-hub .km-hub-post__place > button.km-hub-name,
  .km-hub .km-hub-post__place > button.km-hub-name:hover,
  .km-hub .km-hub-post__place > button.km-hub-name:focus,
  .km-hub .km-hub-post__place > button.km-hub-name:active { display: inline-block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: top; }
  /*
   * Карточка и «Поддержали» на телефоне — снизу экрана (документ 1.49), поверх затемнения; слой — у `body`.
   * Слой — выше кнопки мессенджера Carrot Quest (у неё 2147483000, снимок боевого 10.10.2026): иначе она
   * стоит поверх затемнения и закрывает правый нижний угол карточки.
   */
  .km-hub .km-hub-shade { display: block; position: fixed; inset: 0; z-index: 2147483001; background: var(--km-hub-dark); }
  .km-hub .km-hub-pop.km-hub-pcard,
  .km-hub .km-hub-pop.km-hub-likers {
    position: fixed;
    top: auto;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 2147483002;
    width: auto;
    max-width: none;
    max-height: 85vh;
    overflow-y: auto;
    padding: 22px 16px calc(22px + env(safe-area-inset-bottom));
    border-width: 1px 0 0;
    border-radius: 16px 16px 0 0;
  }
  .km-hub ul.km-hub-likers__list { max-height: none; overflow: visible; }
  /* Карточка с «Подписаться» на телефоне — кнопки друг под другом, по 46 (доска subscribe-v1, «Телефон»). */
  .km-hub .km-hub-pcard__acts.km-hub-pcard__acts--subscribe { flex-direction: column; }
  .km-hub .km-hub-pcard__acts--subscribe a.km-hub-pcard__open,
  .km-hub .km-hub-pcard__acts--subscribe a.km-hub-pcard__open:hover,
  .km-hub .km-hub-pcard__acts--subscribe a.km-hub-pcard__open:focus,
  .km-hub .km-hub-pcard__acts--subscribe button.km-hub-subscribe,
  .km-hub .km-hub-pcard__acts--subscribe button.km-hub-subscribe:hover,
  .km-hub .km-hub-pcard__acts--subscribe button.km-hub-subscribe:focus { flex: none; height: 46px; }
  .km-hub .km-hub-comments { padding: 12px 14px; }
  .km-hub .km-hub-person--sm { width: 28px; height: 28px; font-size: 11px; }
  .km-hub .km-hub-comment--reply { padding-left: 30px; }
  .km-hub .km-hub-comment--reply2 { padding-left: 60px; }
  .km-hub form.km-hub-say--inline { padding-left: 30px; }
}

/* ===== Сообщество, этап 7: статьи «Ключей» (доски feed-v2, mobile-v3) =====
   В шапке — «Статья с «Ключей Мастерства»» со знаком «КМ»; вместо текста — карточка: обложка 16:9 на всю
   ширину карточки (не 16:9 — обрезка сверху и снизу, без сплющивания), название, анонс. На компьютере карточка
   той же долей поста, что на доске, — 560 из 608 (с 1.451.0 долей, а не числом: середина ленты шире), на телефоне —
   во всю ширину, без анонса. Название — толщиной 400, как заголовок поста (слово
   Алены 08.10; на доске 500 у обоих). */
.km-hub .km-hub-person--site { background: var(--km-hub-label); color: var(--km-hub-site-ink); }
.km-hub .km-hub-article { display: flex; flex-direction: column; width: calc(100% * 560 / 608); max-width: 100%; overflow: hidden; border: 1px solid var(--km-hub-line); border-radius: 12px; background: #fff; }
.km-hub img.km-hub-article__cover { display: block; width: 100%; max-width: none; height: auto; aspect-ratio: 16 / 9; margin: 0; border: 0; border-radius: 0; object-fit: cover; object-position: center; }
/* Трансляция — своей карточкой ниже (`km-hub-cast`, вариант В); плашки на картинке (вариант А) больше нет. */
.km-hub .km-hub-article__pic { position: relative; }
.km-hub .km-hub-article__text { display: flex; flex-direction: column; gap: 6px; padding: 14px 16px 16px; }
.km-hub h2.km-hub-article__title { margin: 0; font-family: var(--km-hub-display); font-size: var(--km-hub-card-title-size); font-weight: 400; line-height: var(--km-hub-card-title-line); letter-spacing: normal; text-transform: none; color: var(--km-hub-title); overflow-wrap: anywhere; }
.km-hub p.km-hub-article__excerpt { margin: 0; font-size: 15px; line-height: 1.6; color: var(--km-hub-ink); overflow-wrap: anywhere; }
.km-hub .km-hub-article__foot { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.km-hub a.km-hub-read,
.km-hub a.km-hub-read:visited,
.km-hub a.km-hub-read:hover,
.km-hub a.km-hub-read:focus { display: inline-flex; align-items: center; justify-content: center; gap: 8px; height: 42px; padding: 0 18px; border: 0; border-radius: 10px; background: var(--km-hub-read); box-shadow: none; color: var(--km-hub-tag-lilac-ink); font-family: var(--km-hub-font); font-size: 14px; font-weight: 700; line-height: 1; text-decoration: none; }
.km-hub a.km-hub-read:hover { color: var(--km-hub-title); }
.km-hub a.km-hub-read:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub .km-hub-read .km-hub-icon { width: 16px; height: 16px; stroke-width: 2; }
.km-hub .km-hub-article__caption { font-size: 14px; line-height: 1.4; color: var(--km-hub-muted); }
.km-hub .km-hub-act--save .km-hub-icon { width: 18px; height: 18px; }
.km-hub button.km-hub-act--save[aria-pressed="true"],
.km-hub button.km-hub-act--save[aria-pressed="true"]:hover { color: var(--km-hub-link); font-weight: 600; }
@media (max-width: 760px) {
  .km-hub .km-hub-article { width: 100%; border-radius: 10px; }
  .km-hub .km-hub-article__text { padding: 12px 14px 14px; }
  .km-hub h2.km-hub-article__title { font-size: 19px; }
  .km-hub p.km-hub-article__excerpt { display: none; }
  .km-hub .km-hub-article__foot { flex-direction: column; align-items: stretch; gap: 10px; }
  .km-hub a.km-hub-read,
  .km-hub a.km-hub-read:visited,
  .km-hub a.km-hub-read:hover,
  .km-hub a.km-hub-read:focus { height: 46px; font-size: 15px; }
  .km-hub .km-hub-read .km-hub-icon { display: none; }
  .km-hub .km-hub-article__caption { font-size: 13px; text-align: center; }
  .km-hub .km-hub-act--save { justify-content: center; width: 44px; padding: 0; }
}

/*
 * Карточка трансляции — вариант В (доска broadcast-card-v4; документ сообщества 1.100, пп. 13–14) — для всех
 * трансляций в ленте: курса, библиотеки, закрытых. Рамка — та же, что у статьи (`km-hub-article`). Картинка чистая;
 * под ней листок календаря (число и месяц), справа название, под ним день недели и время; во время трансляции
 * листок красный и «Сейчас в эфире», после — серый и «Запись трансляции». Листок — **по верхнему краю названия**
 * (слово Алены 12.10.2026; на доске — по середине): верх листка — на верху букв, а не на верху строки названия.
 * До 1.481.1 ряд стоял по верху, и листок был выше букв на 4,9 px (23 px Oswald при межстрочном 1.2) — нашла общая
 * мерка `stand.numberTops()`, когда стала искать места сама; отсюда сдвиг 5 px, на телефоне (19 px) — 4. Ниже — две строки краткого описания с многоточием. Ярлык темы
 * на компьютере — в шапке поста, на телефоне — на картинке справа сверху (`__tag`). У закрытой — красная
 * «Зарегистрироваться» и «Уже зарегистрировались N человек», зарегистрированному — «Перейти к трансляции».
 */
.km-hub .km-hub-cast__pic { position: relative; }
.km-hub .km-hub-cast__tag { display: none; }
.km-hub .km-hub-cast__row { display: flex; align-items: flex-start; gap: 14px; padding: 14px 16px 10px; }
.km-hub .km-hub-cast__leaf { flex: none; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px; box-sizing: border-box; width: 60px; height: 60px; margin-top: 5px; border-radius: 12px; background: var(--km-hub-leaf); }
.km-hub .km-hub-cast__day { font-family: var(--km-hub-display); font-size: 26px; font-weight: 600; line-height: 1; color: var(--km-hub-title); }
.km-hub .km-hub-cast__month { font-size: 12px; font-weight: 700; line-height: 1.2; letter-spacing: 0.04em; text-transform: uppercase; color: var(--km-hub-link); }
.km-hub .km-hub-cast__leaf--live { background: var(--km-hub-red); }
.km-hub .km-hub-cast__leaf--live .km-hub-cast__day,
.km-hub .km-hub-cast__leaf--live .km-hub-cast__month { color: #fff; }
.km-hub .km-hub-cast__leaf--rec { background: var(--km-hub-leaf-rec); }
.km-hub .km-hub-cast__leaf--rec .km-hub-cast__day { color: var(--km-hub-leaf-rec-day); }
.km-hub .km-hub-cast__leaf--rec .km-hub-cast__month { color: var(--km-hub-muted); }
.km-hub .km-hub-cast__col { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.km-hub h2.km-hub-cast__title { margin: 0; font-family: var(--km-hub-display); font-size: 23px; font-weight: 400; line-height: 1.2; letter-spacing: normal; text-transform: none; color: var(--km-hub-title); overflow-wrap: anywhere; }
.km-hub .km-hub-cast__when { font-size: 14px; font-weight: 600; line-height: 1.4; color: var(--km-hub-link); }
.km-hub .km-hub-cast__when--live { font-weight: 700; color: var(--km-hub-live-ink); }
.km-hub .km-hub-cast__when--rec { color: var(--km-hub-muted); }
.km-hub .km-hub-cast__about { padding: 0 16px 14px; }
.km-hub p.km-hub-cast__text { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; margin: 0; padding: 0; overflow: hidden; font-size: 14px; line-height: 1.5; color: var(--km-hub-cast-text); overflow-wrap: anywhere; }
.km-hub .km-hub-cast__cta { display: flex; flex-wrap: wrap; align-items: center; gap: 14px; }
.km-hub a.km-hub-cast__watch,
.km-hub a.km-hub-cast__watch:visited,
.km-hub a.km-hub-cast__watch:hover,
.km-hub a.km-hub-cast__watch:focus { display: inline-flex; align-items: center; justify-content: center; gap: 8px; box-sizing: border-box; height: 44px; padding: 0 18px; border: 0; border-radius: 12px; background: var(--km-hub-soft); box-shadow: none; color: var(--km-hub-title); font-family: var(--km-hub-font); font-size: 15px; font-weight: 700; line-height: 1; text-decoration: none; }
.km-hub .km-hub-cast__watch .km-hub-icon { width: 18px; height: 18px; stroke-width: 2; }
.km-hub a.km-hub-cast__register,
.km-hub a.km-hub-cast__register:visited,
.km-hub a.km-hub-cast__register:focus,
.km-hub button.km-hub-cast__register,
.km-hub button.km-hub-cast__register:focus { display: inline-flex; align-items: center; justify-content: center; gap: 8px; box-sizing: border-box; height: 44px; padding: 0 20px; border: 0; border-radius: 12px; background: var(--km-hub-red); box-shadow: none; color: #fff; font-family: var(--km-hub-font); font-size: 15px; font-weight: 700; line-height: 1; text-decoration: none; cursor: pointer; }
.km-hub a.km-hub-cast__register:hover,
.km-hub button.km-hub-cast__register:hover { background: var(--km-hub-red-deep); color: #fff; }
.km-hub button.km-hub-cast__register:disabled { cursor: progress; opacity: 0.7; }
.km-hub .km-hub-cast__proof { font-size: 14px; line-height: 1.4; color: var(--km-hub-proof); }
.km-hub .km-hub-cast__shut { font-size: 15px; font-weight: 700; line-height: 1.4; color: var(--km-hub-muted); }
/* Вместо поля комментария закрытой трансляции: строка и «Зарегистрироваться» (документ сообщества 1.100, п. 14). */
.km-hub .km-hub-gate { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; }
.km-hub p.km-hub-gate__text { margin: 0; font-size: 14px; line-height: 1.4; color: var(--km-hub-muted); }
.km-hub a.km-hub-gate__button,
.km-hub a.km-hub-gate__button:visited,
.km-hub a.km-hub-gate__button:focus,
.km-hub button.km-hub-gate__button,
.km-hub button.km-hub-gate__button:focus { display: inline-flex; align-items: center; height: 36px; padding: 0 14px; border: 0; border-radius: 10px; background: var(--km-hub-red); box-shadow: none; color: #fff; font-family: var(--km-hub-font); font-size: 14px; font-weight: 700; line-height: 1; text-decoration: none; cursor: pointer; }
.km-hub a.km-hub-gate__button:hover,
.km-hub button.km-hub-gate__button:hover { background: var(--km-hub-red-deep); color: #fff; }
@media (max-width: 760px) {
  .km-hub .km-hub-cast__tag { position: absolute; top: 10px; right: 10px; display: inline-flex; align-items: center; box-sizing: border-box; max-width: calc(100% - 20px); height: 26px; padding: 0 10px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.14); font-size: 12px; }
  .km-hub .km-hub-cast__row { gap: 12px; padding: 12px; }
  .km-hub .km-hub-cast__leaf { width: 52px; height: 52px; margin-top: 4px; }
  .km-hub .km-hub-cast__day { font-size: 22px; }
  .km-hub h2.km-hub-cast__title { font-size: 19px; }
  .km-hub .km-hub-cast__when { font-size: 13px; }
  .km-hub .km-hub-cast__about { padding: 0 12px 12px; }
  .km-hub p.km-hub-cast__text { font-size: 13px; }
  .km-hub .km-hub-cast__cta { flex-direction: column; align-items: stretch; gap: 10px; }
  .km-hub a.km-hub-cast__watch,
  .km-hub a.km-hub-cast__register,
  .km-hub button.km-hub-cast__register { width: 100%; }
  .km-hub .km-hub-cast__proof { font-size: 13px; text-align: center; }
  .km-hub .km-hub-cast__shut { text-align: center; }
}

/*
 * «Мои трансляции» «Моего профиля» (документ сообщества 1.59–1.63, доска my-profile-tabs-v2); «Мои курсы» — блок
 * кабинета, его цвета профиля ниже (`km-dashboard--profile`, документ 1.66). Видны только хозяину — замок на вкладке. Выбранная серия и переключатель записей — светло-сиреневые, как выбранная
 * вкладка профиля (документ 1.60), а не тёмные, как на доске. Ссылки-кнопки — `a`: тема красит ссылки, поэтому
 * у каждой свои `:visited`, `:hover`, `:focus`.
 */
.km-hub .km-hub-member__tab--own { gap: 6px; }
.km-hub .km-hub-member__lock { display: inline-flex; color: var(--km-hub-muted); }
.km-hub .km-hub-member__lock .km-hub-icon { width: 13px; height: 13px; stroke-width: 2; }
.km-hub .km-mine { display: flex; flex-direction: column; gap: 26px; min-width: 0; }
.km-hub .km-mine-sec { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.km-hub .km-mine p.km-hub-status:empty { display: none; }
.km-hub p.km-mine-head { margin: 0; font-size: 12px; font-weight: 700; line-height: 1.3; letter-spacing: 0.08em; text-transform: uppercase; color: var(--km-hub-muted); }
.km-hub .km-mine-tag { align-self: flex-start; max-width: 100%; box-sizing: border-box; padding: 4px 8px; border-radius: 6px; background: var(--km-hub-label); color: var(--km-hub-link); font-size: 12px; font-weight: 700; line-height: 1.3; overflow-wrap: anywhere; }
.km-hub .km-mine-live { align-self: flex-start; display: inline-flex; align-items: center; gap: 6px; padding: 4px 8px; border-radius: 6px; background: var(--km-hub-red); color: #fff; font-size: 12px; font-weight: 700; line-height: 1.3; }

.km-hub p.km-mine-none { margin: 0; font-size: 14px; line-height: 1.5; color: var(--km-hub-muted); }

/* Кнопка-ссылка «Смотреть» у идущего эфира — красная, как «Написать пост» */
.km-hub a.km-mine-btn,
.km-hub a.km-mine-btn:visited,
.km-hub a.km-mine-btn:hover,
.km-hub a.km-mine-btn:focus {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  height: 44px;
  padding: 0 22px;
  border: 1px solid var(--km-hub-red);
  border-radius: 10px;
  background: var(--km-hub-red);
  box-shadow: none;
  color: #fff;
  font-family: var(--km-hub-font);
  font-size: 15px;
  font-weight: 700;
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
}
.km-hub a.km-mine-btn:hover { border-color: var(--km-hub-red-deep); background: var(--km-hub-red-deep); }
.km-hub a.km-mine-btn--small,
.km-hub a.km-mine-btn--small:visited,
.km-hub a.km-mine-btn--small:hover,
.km-hub a.km-mine-btn--small:focus { height: 34px; padding: 0 14px; font-size: 13px; }
.km-hub a.km-mine-btn:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub a.km-mine-link,
.km-hub a.km-mine-link:visited,
.km-hub a.km-mine-link:focus { color: var(--km-hub-link); font-size: 13px; font-weight: 700; line-height: 1.3; text-decoration: none; }
.km-hub a.km-mine-link:hover { color: var(--km-hub-title); text-decoration: underline; }
.km-hub a.km-mine-link--all { align-self: flex-start; font-size: 14px; }
.km-hub a.km-mine-btn--line,
.km-hub a.km-mine-btn--line:visited,
.km-hub a.km-mine-btn--line:focus { border-color: var(--km-hub-chip-line); background: #fff; color: var(--km-hub-ink); }
.km-hub a.km-mine-btn--line:hover { border-color: var(--km-hub-chip-line); background: var(--km-hub-hover); color: var(--km-hub-ink); }

/* «Продолжить» на «Мои курсы» (документ 1.68) — обложка слева, на телефоне сверху; под ней блок кабинета */
.km-hub .km-mine-slot > .km-mine { margin-bottom: 12px; }
.km-hub .km-mine-slot:empty,
.km-hub p.km-mine-fail:empty { display: none; }
.km-hub .km-mine-progress { display: flex; align-items: center; gap: 12px; min-width: 0; }
.km-hub progress.km-mine-progress__bar { flex: 1; background: var(--km-hub-track); }
.km-hub progress.km-mine-progress__bar::-webkit-progress-bar { background: var(--km-hub-track); }
.km-hub progress.km-mine-progress__bar::-webkit-progress-value { background: var(--km-hub-accent); }
.km-hub progress.km-mine-progress__bar::-moz-progress-bar { background: var(--km-hub-accent); }
.km-hub .km-mine-progress__words { flex: none; font-size: 13px; font-weight: 700; color: var(--km-hub-ink); white-space: nowrap; }
/* Без `overflow: hidden`: он обрезал бы список «В календарь», открытый поверх; углы обложки скруглены ей самой. */
.km-hub .km-mine-go { display: flex; min-width: 0; border: 1px solid var(--km-hub-line); border-radius: 14px; background: #fff; }
.km-hub a.km-mine-go__cover { flex: 0 0 37%; display: block; min-height: 220px; border-radius: 13px 0 0 13px; background: var(--km-hub-soft); overflow: hidden; }
.km-hub .km-mine-go__img { display: block; width: 100%; height: 100%; object-fit: cover; }
.km-hub .km-mine-go__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 12px; padding: 20px 24px; }
.km-hub h3.km-mine-go__title { margin: 0; font-family: var(--km-hub-display); font-size: 26px; font-weight: 400; line-height: 1.2; color: var(--km-hub-title); overflow-wrap: anywhere; }
.km-hub p.km-mine-go__where { margin: 0; font-size: 14px; line-height: 1.45; color: var(--km-hub-muted); overflow-wrap: anywhere; }
.km-hub b.km-mine-go__spot { color: var(--km-hub-ink); font-weight: 700; }
.km-hub .km-mine-go__acts { display: flex; flex-wrap: wrap; gap: 10px; }
.km-hub .km-mine-air { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; padding-top: 12px; border-top: 1px solid var(--km-hub-line); font-size: 14px; line-height: 1.4; color: var(--km-hub-ink); }
.km-hub .km-mine-air__dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--km-hub-red); }
.km-hub .km-mine-air__text { flex: 1 1 200px; min-width: 0; overflow-wrap: anywhere; }
.km-hub b.km-mine-air__label { font-weight: 700; }

/*
 * «В календарь» — кнопка и список Google / Яндекс поверх содержимого, как выпадающие списки ленты (выбор группы,
 * порядок): ничего не раздвигает. У правого края открывается влево, внизу — вверх (`km-mine-cal--left`, `--up`,
 * ставит `community.js`, меряя край экрана и край прокручиваемой полосы «Скоро» на телефоне). Закрывается нажатием
 * мимо, по Esc и после выбора. Обводка — только при переходе клавишей Tab, как у кнопок сообщества.
 */
.km-hub .km-mine-cal { position: relative; }
.km-hub summary.km-mine-cal__button { display: inline-flex; align-items: center; height: 30px; color: var(--km-hub-link); font-size: 13px; font-weight: 700; line-height: 1; list-style: none; cursor: pointer; white-space: nowrap; }
.km-hub summary.km-mine-cal__button::-webkit-details-marker { display: none; }
.km-hub summary.km-mine-cal__button:hover { color: var(--km-hub-title); }
.km-hub summary.km-mine-cal__button:focus { outline: none; }
.km-hub summary.km-mine-cal__button:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; border-radius: 6px; }
.km-hub[data-lms-hub-pointer] summary.km-mine-cal__button:focus-visible { outline: none; }
.km-hub .km-mine-cal__list { position: absolute; z-index: 20; top: calc(100% + 6px); left: 0; display: flex; flex-direction: column; min-width: 150px; padding: 6px; border: 1px solid var(--km-hub-line); border-radius: 10px; background: #fff; box-shadow: 0 8px 24px rgba(46, 36, 51, 0.12); }
.km-hub a.km-mine-cal__item,
.km-hub a.km-mine-cal__item:visited,
.km-hub a.km-mine-cal__item:focus { display: block; padding: 8px 10px; border-radius: 7px; color: var(--km-hub-ink); font-size: 14px; font-weight: 600; line-height: 1.2; text-decoration: none; }
.km-hub a.km-mine-cal__item:hover { background: var(--km-hub-hover); color: var(--km-hub-ink); }
.km-hub .km-mine-cal--left .km-mine-cal__list { left: auto; right: 0; }
.km-hub .km-mine-cal--up .km-mine-cal__list { top: auto; bottom: calc(100% + 6px); }

/* Отбор по серии — светло-сиреневый выбранный */
.km-hub .km-mine-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.km-hub button.km-mine-chip,
.km-hub button.km-mine-chip:hover,
.km-hub button.km-mine-chip:focus,
.km-hub button.km-mine-chip:active {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 36px;
  margin: 0;
  padding: 0 14px;
  border: 1px solid var(--km-hub-chip-line);
  border-radius: 9px;
  background: #fff;
  box-shadow: none;
  color: var(--km-hub-chip-ink);
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  white-space: nowrap;
  cursor: pointer;
}
.km-hub button.km-mine-chip:hover { background: var(--km-hub-hover); }
.km-hub button.km-mine-chip[aria-pressed="true"],
.km-hub button.km-mine-chip[aria-pressed="true"]:hover,
.km-hub button.km-mine-chip[aria-pressed="true"]:focus,
.km-hub button.km-mine-chip[aria-pressed="true"]:active { border-color: var(--km-hub-soft); background: var(--km-hub-soft); color: var(--km-hub-ink); font-weight: 700; }
.km-hub button.km-mine-chip:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub .km-mine-chip__n { color: var(--km-hub-muted); font-weight: 600; font-variant-numeric: tabular-nums; }

/* «Скоро» — карточки рядом; на телефоне прокрутка вбок */
.km-hub .km-mine-soon { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 14px; }
.km-hub .km-mine-soon__card { display: flex; flex-direction: column; gap: 6px; min-width: 0; padding: 16px; border: 1px solid var(--km-hub-line); border-radius: 14px; background: #fff; }
.km-hub .km-mine-soon__card--live { border-color: var(--km-hub-red); }
.km-hub p.km-mine-soon__date { display: flex; align-items: flex-start; gap: 8px; margin: 0; color: var(--km-hub-red); }
.km-hub .km-mine-soon__day { font-family: var(--km-hub-display); font-size: 30px; font-weight: 500; line-height: 1; }
.km-hub .km-mine-soon__month { font-size: 13px; font-weight: 700; line-height: 1.3; }
.km-hub h3.km-mine-soon__title { margin: 0; font-family: var(--km-hub-font); font-size: 16px; font-weight: 700; line-height: 1.3; color: var(--km-hub-ink); overflow-wrap: anywhere; }
.km-hub p.km-mine-soon__time { margin: 0; font-size: 13px; color: var(--km-hub-muted); }
.km-hub p.km-mine-soon__locked { margin: 0; font-size: 13px; line-height: 1.4; color: var(--km-hub-muted); }
.km-hub .km-mine-soon__acts { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 16px; margin-top: auto; padding-top: 6px; }

/* «Записи» — переключатель и строки */
.km-hub .km-mine-rec-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px 16px; }
.km-hub .km-mine-seg { display: inline-flex; flex-wrap: wrap; gap: 4px; padding: 3px; border: 1px solid var(--km-hub-line); border-radius: 11px; background: #fff; }
.km-hub button.km-mine-seg__item,
.km-hub button.km-mine-seg__item:hover,
.km-hub button.km-mine-seg__item:focus,
.km-hub button.km-mine-seg__item:active {
  height: 32px;
  margin: 0;
  padding: 0 12px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  box-shadow: none;
  color: var(--km-hub-seg-ink);
  font-family: var(--km-hub-font);
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  white-space: nowrap;
  cursor: pointer;
}
.km-hub button.km-mine-seg__item:hover { background: var(--km-hub-hover); }
.km-hub button.km-mine-seg__item[aria-pressed="true"],
.km-hub button.km-mine-seg__item[aria-pressed="true"]:hover,
.km-hub button.km-mine-seg__item[aria-pressed="true"]:focus,
.km-hub button.km-mine-seg__item[aria-pressed="true"]:active { background: var(--km-hub-soft); color: var(--km-hub-ink); font-weight: 700; }
.km-hub button.km-mine-seg__item:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub .km-mine-recs { display: flex; flex-direction: column; border: 1px solid var(--km-hub-line); border-radius: 14px; background: #fff; overflow: hidden; }
.km-hub .km-mine-rec { display: flex; align-items: center; gap: 14px; min-width: 0; padding: 12px 16px; }
.km-hub .km-mine-rec + .km-mine-rec { border-top: 1px solid var(--km-hub-line-soft); }
.km-hub a.km-mine-rec__cover { flex: none; display: block; width: 96px; height: 56px; border-radius: 8px; background: var(--km-hub-soft); overflow: hidden; }
.km-hub .km-mine-rec__img { display: block; width: 100%; height: 100%; object-fit: cover; }
.km-hub .km-mine-rec__copy { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.km-hub a.km-mine-rec__title,
.km-hub a.km-mine-rec__title:visited,
.km-hub a.km-mine-rec__title:focus { color: var(--km-hub-ink); font-size: 15px; font-weight: 700; line-height: 1.3; text-decoration: none; overflow-wrap: anywhere; }
.km-hub a.km-mine-rec__title:hover { color: var(--km-hub-link); text-decoration: underline; }
.km-hub .km-mine-rec__line { font-size: 13px; line-height: 1.4; color: var(--km-hub-muted); overflow-wrap: anywhere; }
.km-hub .km-mine-rec__state { flex: none; font-size: 13px; font-weight: 700; color: var(--km-hub-red); white-space: nowrap; }
.km-hub .km-mine-rec__state--done { color: var(--km-done); }
.km-hub button.km-mine-heart,
.km-hub button.km-mine-heart:hover,
.km-hub button.km-mine-heart:focus,
.km-hub button.km-mine-heart:active { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px; margin: 0; padding: 0; border: 0; border-radius: 50%; background: transparent; box-shadow: none; color: var(--km-hub-muted); cursor: pointer; }
.km-hub button.km-mine-heart:hover { background: var(--km-hub-hover); }
.km-hub button.km-mine-heart .km-lb-i { width: 18px; height: 18px; stroke-width: 2; }
.km-hub button.km-mine-heart[aria-pressed="true"] { color: var(--km-hub-red); }
.km-hub button.km-mine-heart[aria-pressed="true"] .km-lb-i { fill: currentColor; }
.km-hub button.km-mine-heart:disabled { opacity: 0.5; cursor: default; }
.km-hub button.km-mine-heart:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub button.km-mine-more,
.km-hub button.km-mine-more:hover,
.km-hub button.km-mine-more:focus,
.km-hub button.km-mine-more:active { align-self: flex-start; height: 34px; margin: 0; padding: 0; border: 0; background: transparent; box-shadow: none; color: var(--km-hub-link); font-family: var(--km-hub-font); font-size: 14px; font-weight: 700; line-height: 1; letter-spacing: normal; text-transform: none; cursor: pointer; }
.km-hub button.km-mine-more:hover { color: var(--km-hub-title); text-decoration: underline; }
.km-hub button.km-mine-more:disabled { opacity: 0.6; cursor: default; }
.km-hub button.km-mine-more:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }

/* «Избранное» — три карточки */
.km-hub .km-mine-favs { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 14px; }
.km-hub a.km-mine-fav,
.km-hub a.km-mine-fav:visited,
.km-hub a.km-mine-fav:focus { display: flex; flex-direction: column; min-width: 0; padding-bottom: 12px; box-sizing: border-box; border: 1px solid var(--km-hub-line); border-radius: 14px; background: #fff; overflow: hidden; color: var(--km-hub-ink); text-decoration: none; }
.km-hub a.km-mine-fav:hover { border-color: var(--km-hub-chip-line); color: var(--km-hub-ink); }
.km-hub a.km-mine-fav:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub .km-mine-fav__cover { display: block; height: 96px; background: var(--km-hub-soft); }
.km-hub .km-mine-fav__img { display: block; width: 100%; height: 100%; object-fit: cover; }
.km-hub .km-mine-fav__title { padding: 12px 14px 0; font-size: 15px; font-weight: 700; line-height: 1.3; overflow-wrap: anywhere; }
.km-hub .km-mine-fav__text { padding: 4px 14px 0; font-size: 13px; line-height: 1.4; color: var(--km-hub-muted); overflow-wrap: anywhere; }
@media (max-width: 760px) {
  .km-hub .km-mine-go { flex-direction: column; }
  .km-hub a.km-mine-go__cover { flex: none; min-height: 0; height: 180px; border-radius: 13px 13px 0 0; }
  .km-hub .km-mine-go__body { padding: 16px; }
  .km-hub h3.km-mine-go__title { font-size: 22px; }
  .km-hub .km-mine-go__acts a.km-mine-btn { flex: 1 1 auto; }
  .km-hub .km-mine-favs { grid-template-columns: 1fr; }
  .km-hub .km-mine-soon { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; padding-bottom: 2px; }
  .km-hub .km-mine-soon::-webkit-scrollbar { display: none; }
  .km-hub .km-mine-soon__card { flex: 0 0 78%; scroll-snap-align: start; }
  .km-hub .km-mine-chips { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  .km-hub .km-mine-chips::-webkit-scrollbar { display: none; }
  .km-hub .km-mine-rec { flex-wrap: wrap; gap: 8px 12px; padding: 12px; }
  .km-hub a.km-mine-rec__cover { width: 80px; height: 46px; }
  .km-hub .km-mine-rec__copy { flex-basis: calc(100% - 92px); }
  .km-hub .km-mine-rec__state { margin-left: 92px; flex: 1; }
}

/*
 * Блок «Мои курсы» кабинета во вкладке «Мои курсы» «Моего профиля» (документ сообщества 1.65–1.66): тот же блок,
 * перекрашенный здесь; с 1.518.0 в тех же цветах и страница «Мои курсы» (`km-dashboard--page`, ниже — тем же классом). Кнопки «Продолжить» и «Начать» — красные, как «Написать
 * пост»; выбранная вкладка типа — бледно-сиреневая, как выбранная группа ленты (`km-hub-nav__item--on`); полоса
 * прогресса, плашка типа на обложке и обводка фокуса — цветами профиля. Зелёное «пройдено» остаётся зелёным.
 * Карточки и подписи — как в кабинете. Состояния кнопок перечислены все: у темы свои умолчания `:hover` и `:focus`.
 */
.km-hub .km-dashboard--profile .km-tabs { gap: 6px; margin: 0; border-bottom: 0; }
.km-hub .km-dashboard--profile .km-tab,
.km-hub .km-dashboard--profile .km-tab:hover,
.km-hub .km-dashboard--profile .km-tab:focus,
.km-hub .km-dashboard--profile .km-tab:active { padding: 9px 12px; border: 0; border-radius: 10px; background: transparent; color: var(--km-hub-muted); }
.km-hub .km-dashboard--profile .km-tab:hover { background: var(--km-hub-hover); color: var(--km-hub-ink); }
.km-hub .km-dashboard--profile .km-tab.is-active,
.km-hub .km-dashboard--profile .km-tab.is-active:hover,
.km-hub .km-dashboard--profile .km-tab.is-active:focus,
.km-hub .km-dashboard--profile .km-tab.is-active:active { background: var(--km-hub-soft); color: var(--km-hub-ink); }
.km-hub .km-dashboard--profile .km-tab:focus { outline: none; }
.km-hub .km-dashboard--profile .km-tab:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
/*
 * Обводка вкладок профиля и вкладок типа — только при переходе клавишей Tab (документ 1.68): после нажатия мышью или
 * пальцем рамки нет. `:focus-visible` браузеры решают по-разному (Safari ставит его и после нажатия), поэтому способ
 * ввода помнит `community.js` (`data-lms-hub-pointer` у корня), и по нему рамка снимается.
 */
.km-hub button.km-hub-member__tab:focus:not(:focus-visible) { outline: none; }
.km-hub[data-lms-hub-pointer] button.km-hub-member__tab:focus-visible,
.km-hub[data-lms-hub-pointer] .km-dashboard--profile .km-tab:focus-visible { outline: none; }
.km-hub .km-dashboard--profile .km-btn--primary,
.km-hub .km-dashboard--profile .km-btn--primary:visited,
.km-hub .km-dashboard--profile .km-btn--primary:focus,
.km-hub .km-dashboard--profile .km-btn--primary:active { background: var(--km-hub-red); color: #fff; }
.km-hub .km-dashboard--profile .km-btn--primary:hover { background: var(--km-hub-red-deep); color: #fff; }
.km-hub .km-dashboard--profile .km-btn:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hub .km-dashboard--profile .km-progress__bar { background: var(--km-hub-track); }
.km-hub .km-dashboard--profile .km-progress__bar::-webkit-progress-bar { background: var(--km-hub-track); }
.km-hub .km-dashboard--profile .km-progress__bar:not(.km-progress__bar--done)::-webkit-progress-value { background: var(--km-hub-accent); }
.km-hub .km-dashboard--profile .km-progress__bar:not(.km-progress__bar--done)::-moz-progress-bar { background: var(--km-hub-accent); }
.km-hub .km-dashboard--profile .km-cover__badge:not(.km-cover__badge--done) { color: var(--km-hub-link); }
.km-hub .km-dashboard--profile .km-empty:hover { border-color: var(--km-hub-chip-line); }

/*
 * Нижняя полоса карточки кабинета — срок и кнопка (`km-course-card__foot`, `assets/js/dashboard.js`). Узел есть
 * всегда, а вид у него только на странице «Мои курсы» (ниже): везде ещё — и во вкладке «Мои курсы» «Моего
 * профиля» — его нет в раскладке вовсе, срок и кнопка остаются детьми тела карточки, ритм тела тот же до пикселя.
 */
.km-course-card__foot { display: contents; }

/*
 * Страница «Мои курсы» (`[lms_dashboard]` на «Моих курсах», «Мои курсы · LMS» и в «Кабинете») — образец Алены
 * 15 октября 2026. Цвета, шрифты, кнопки и полоса — правила вкладки профиля выше: `km-dashboard--profile` стоит
 * на `km-dashboard__main` внутри корня `km-hub`, третьего вида нет. Здесь — только то, что образец рисует сверх
 * вкладки профиля: шапка «Сообщества» (`parts/hub-head.php`) — без строки «N программ в кабинете» (слово Алены 15.10), вкладки
 * плашками с рамкой и числом, черта под ними, рамка карточки, нижняя полоса со сроком и кнопкой, стрелка на кнопке.
 * Всё под `.km-hub.km-dashboard--page` — у вкладки профиля этого класса нет, и её ничто здесь не задевает.
 *
 * НОЛЬ СВЕРХУ — решение Алены 15 сентября 2026 (`.km-page.km-dashboard`, выше): блок начинается вровень с меню
 * «Кабинета». `.km-page.km-hub` той же силы даёт 32 и стоит в файле ниже — держится нолём силой (0,3,0), а не порядком.
 */
.km-page.km-hub.km-dashboard--page { padding-top: 0; }
/*
 * Колонка — во всю ширину корня. Корень кабинета — сетка (`.km-dashboard`), а у `km-hub__inner` свои поля `auto`
 * и `container: inline-size`: в сетке такая колонка сжимается до самого узкого слова (стенд 15.10.2026 — «Мои»
 * и «курсы» в две строки). Та же беда и та же мера, что у «Настроек профиля» (`.km-me__inner > .km-hub__inner`).
 */
/* Промежуток под шапкой — общий у «Сообщества» (28, на телефоне 14): строки «N программ в кабинете» больше нет. */
.km-hub.km-dashboard--page > .km-hub__inner { width: 100%; }
/* Строки «Править: …» у кабинета нет (spec 12.3: своего объекта нет); пустой узел шапки места не занимает. */
.km-hub.km-dashboard--page .km-hub__inner > [data-lms-hub-editline]:not(:has(*)) { display: none; }
.km-hub.km-dashboard--page .km-dashboard--profile.km-dashboard__main { gap: 24px; }

/* Вкладки — плашками: рамка, число рядом; выбранная — сиреневая, число в белом квадрате. Наведение — только цвет. */
.km-hub.km-dashboard--page .km-dashboard--profile .km-tabs { gap: 8px; padding-bottom: 20px; border-bottom: 1px solid var(--km-hub-line); }
.km-hub.km-dashboard--page .km-dashboard--profile .km-tab,
.km-hub.km-dashboard--page .km-dashboard--profile .km-tab:hover,
.km-hub.km-dashboard--page .km-dashboard--profile .km-tab:focus,
.km-hub.km-dashboard--page .km-dashboard--profile .km-tab:active {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 38px;
  padding: 0 16px;
  border: 1px solid var(--km-hub-chip-line);
  border-radius: 8px;
  background: var(--km-surface);
  color: var(--km-hub-chip-ink);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: normal;
  text-transform: none;
  white-space: nowrap;
}
.km-hub.km-dashboard--page .km-dashboard--profile .km-tab:hover { background: var(--km-hub-hover); }
.km-hub.km-dashboard--page .km-dashboard--profile .km-tab.is-active,
.km-hub.km-dashboard--page .km-dashboard--profile .km-tab.is-active:hover,
.km-hub.km-dashboard--page .km-dashboard--profile .km-tab.is-active:focus,
.km-hub.km-dashboard--page .km-dashboard--profile .km-tab.is-active:active { background: var(--km-hub-soft); color: var(--km-hub-title); font-weight: 600; }
.km-hub.km-dashboard--page .km-dashboard--profile .km-tab__count { margin: 0; opacity: 1; font-size: 12px; font-weight: 500; color: var(--km-hub-muted); }
.km-hub.km-dashboard--page .km-dashboard--profile .km-tab.is-active .km-tab__count { padding: 2px 7px; border-radius: 5px; background: var(--km-surface); color: var(--km-hub-title); font-weight: 700; }

/* Сетка — промежуток 24, как на образце; дорожка — та же «не больше трёх», пересчитанная под 24 (две по 24 = 48). */
.km-hub.km-dashboard--page .km-grid-cards.km-grid-cards--own {
  gap: 24px;
  grid-template-columns: repeat(auto-fill, minmax(max(272px, calc((100% - 48px) / 3)), 1fr));
}
.km-hub.km-dashboard--page .km-course-card { border-color: var(--km-hub-line); }
/* Карточка «Продолжить» на странице «Мои курсы» (`continue="1"`, решение Алены 15.10.2026) — та же, что во вкладке
 * профиля; своё у неё одно: во всю ширину блока обложка шире, и картинка своей пропорцией вытягивала карточку выше
 * текста (436 при тексте 260 на 1280). Здесь высоту задаёт текст (не меньше 220), обложка его заполняет; на телефоне —
 * 180, как в профиле. Вкладку профиля правило не задевает: у неё нет `km-dashboard--page`. */
.km-hub.km-dashboard--page a.km-mine-go__cover { position: relative; }
.km-hub.km-dashboard--page .km-mine-go__img { position: absolute; inset: 0; }

/* Нижняя полоса: светлая подложка под чертой, во всю ширину карточки — поля тела (18 по бокам и снизу) снимаются. */
.km-hub.km-dashboard--page .km-course-card__foot {
  display: flex;
  flex-direction: column;
  gap: var(--km-gap-label);
  margin: calc(var(--km-gap-group) - var(--km-gap-label)) -18px -18px;
  padding: 14px 18px 18px;
  border-top: 1px solid var(--km-hub-line);
  background: var(--km-hub-field);
}
.km-hub.km-dashboard--page .km-course-card__foot > .km-course-card__group { margin-top: 0; }
/* Стрелка — знаком справа на кнопке, слово по-прежнему по середине; цвет — цветом слова. */
.km-hub.km-dashboard--page .km-course-card__foot .km-btn { position: relative; }
.km-hub.km-dashboard--page .km-course-card__foot .km-btn::after {
  content: "";
  position: absolute;
  top: 50%;
  right: 16px;
  width: 16px;
  height: 16px;
  margin-top: -8px;
  background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E") center / 16px 16px no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E") center / 16px 16px no-repeat;
}

/* Экраны админки сообщества — «Группы» и «Темы» (4.20). Макета нет: карточки
   и поля дизайн-системы, ярлыки тем — те же классы, что в ленте. */
.km-hub-admin { max-width: 960px; }
.km-hub-avatar--md { width: 40px; height: 40px; border-radius: 10px; }
.km-hub-avatar--lg { width: 56px; height: 56px; border-radius: 12px; font-size: 16px; }
.km-hub-status { margin: 0; min-height: 20px; font-size: 13px; color: var(--km-ok); }
.km-hub-status--error { color: var(--km-danger); }
.km-hub-card {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 16px 18px;
  border: 1px solid var(--km-border);
  border-radius: 12px;
  background: var(--km-surface);
}
.km-hub-card__head { display: flex; align-items: center; gap: 12px; min-width: 0; }
.km-hub-card__text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.km-hub-card__title { font-size: 16px; font-weight: 700; color: var(--km-text); overflow-wrap: anywhere; }
.km-hub-card__meta { font-size: 13px; line-height: 1.5; color: var(--km-text-secondary); overflow-wrap: anywhere; }
.km-hub-card__body { border-top: 1px solid var(--km-border-soft); padding-top: 14px; }
.km-hub-card--open { border-color: var(--km-warm-border); }
.km-hub-new { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; }
.km-hub-new > .km-hub-card { align-self: stretch; }
.km-hub-gform { display: flex; flex-direction: column; gap: 16px; }
.km-hub-gform__avatar { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.km-hub-gform__preview { display: flex; }
.km-hub-gform__courses { margin: 0; padding: 0; border: 0; min-width: 0; }
.km-hub-gform__list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px 16px;
  max-height: 260px;
  overflow-y: auto;
  padding: 10px 12px;
  border: 1px solid var(--km-border);
  border-radius: 8px;
}
.km-hub-gform__address { display: flex; align-items: center; gap: 6px; min-width: 0; }
.km-hub-gform__base { flex: none; max-width: 60%; font-size: 14px; color: var(--km-text-secondary); overflow-wrap: anywhere; }
.km-hub-gform__address .km-input { flex: 1; min-width: 0; }
.km-hub-gform__links { margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.km-hub-gform__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.km-hub-gform__delete { margin-left: auto; }
.km-hub-rnew { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px 12px; }
.km-hub-rnew .km-field { flex: 1 1 320px; }
.km-hub-rnew .km-hub-status { flex-basis: 100%; }
.km-hub-rform { display: flex; flex-direction: column; gap: 14px; }
.km-hub-rform fieldset.km-field { margin: 0; padding: 0; border: 0; min-width: 0; }
.km-hub-swatches { display: flex; flex-wrap: wrap; gap: 8px; }
.km-hub-swatch { position: relative; display: inline-flex; cursor: pointer; }
.km-hub-swatch input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.km-hub-swatch .km-hub-tag { border: 2px solid transparent; }
.km-hub-swatch input:checked + .km-hub-tag { border-color: currentColor; }
.km-hub-swatch input:focus-visible + .km-hub-tag { outline: 2px solid var(--km-accent); outline-offset: 2px; }
.km-hub-rdelete { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
.km-hub-rdelete__box { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px; padding: 12px; border: 1px solid var(--km-danger-border); border-radius: 8px; background: var(--km-danger-bg); }
@media (max-width: 782px) {
  .km-hub-gform__list { grid-template-columns: 1fr; }
  .km-hub-gform__address { flex-wrap: wrap; }
  .km-hub-gform__base { max-width: 100%; }
}


/* --- Сквозной поиск (документ сообщества 1.86, доска design/search-v1.dc.html) ------------------------------------
   Лупа в шапке (`SearchLayer::button()`), окно поверх страницы (`parts/search-overlay.php`), страница результатов
   (`search.php`). Окно и лупа стоят и на страницах темы, куда приходит урезанная таблица (только `:root` и `.km-`),
   поэтому всё здесь — классами `.km-`; кнопки и поле — с силой против умолчаний темы для `button` и `input`.
   Под курсором меняется только цвет. */

.km-search-lock { overflow: hidden; }

.km-search-open.km-search-open.km-search-open,
.km-search-open.km-search-open.km-search-open:hover,
.km-search-open.km-search-open.km-search-open:focus,
.km-search-open.km-search-open.km-search-open:active {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  box-shadow: none;
  color: inherit;
  cursor: pointer;
  vertical-align: middle;
  flex: none;
}
.km-search-open.km-search-open.km-search-open:hover,
.km-search-open.km-search-open.km-search-open[aria-expanded="true"] { background: var(--km-hub-soft); color: var(--km-hub-title); }
.km-search-open.km-search-open.km-search-open:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-search-open .km-hub-icon { width: 20px; height: 20px; }

.km-hub.km-search {
  position: fixed;
  inset: 0;
  z-index: 2147483002;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 72px 16px 24px;
  background: rgba(46, 36, 51, 0.35);
  font-family: var(--km-hub-font);
  color: var(--km-hub-ink);
}
.km-hub.km-search[hidden] { display: none; }
.km-search__panel {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 900px;
  max-width: 100%;
  max-height: calc(100vh - 96px);
  overflow-y: auto;
  padding: 16px 18px;
  border-radius: 16px;
  background: #fff;
  box-shadow: 0 16px 48px rgba(59, 42, 71, 0.22);
}
/* Части панели не сжимаются: найденного больше экрана — прокручивается панель, а вкладки и поле остаются целыми
   (на телефоне строка вкладок с прокруткой сжималась до нуля — снимок боевого 11.10.2026, под входом). */
.km-search__panel > * { flex-shrink: 0; }
.km-search__bar { display: flex; align-items: center; gap: 8px; margin: 0; padding: 0; }
.km-search__field {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 1;
  min-width: 0;
  height: 50px;
  padding: 0 14px;
  border: 1px solid var(--km-hub-line);
  border-radius: 12px;
  background: #fff;
  color: var(--km-hub-muted);
}
.km-search__field:focus-within { border-color: var(--km-hub-accent); box-shadow: 0 0 0 3px var(--km-hub-soft); }
.km-search__field > .km-hub-icon { flex: none; width: 18px; height: 18px; }
.km-search__input.km-search__input,
.km-search__input.km-search__input:hover,
.km-search__input.km-search__input:focus {
  flex: 1;
  min-width: 0;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  outline: none;
  font-family: var(--km-hub-font);
  font-size: 17px;
  line-height: 1.3;
  color: var(--km-hub-ink);
  -webkit-appearance: none;
  appearance: none;
}
.km-search__input::-webkit-search-cancel-button { display: none; }
.km-search__input::placeholder { color: var(--km-hub-muted); }
.km-search__esc {
  flex: none;
  padding: 1px 6px;
  border: 1px solid var(--km-hub-line);
  border-radius: 6px;
  background: var(--km-hub-field);
  font-family: var(--km-hub-font);
  font-size: 11px;
  line-height: 1.5;
  color: var(--km-hub-muted);
}
.km-search__clear.km-search__clear,
.km-search__back.km-search__back,
.km-search__clear.km-search__clear:hover,
.km-search__back.km-search__back:hover,
.km-search__clear.km-search__clear:focus,
.km-search__back.km-search__back:focus {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 32px;
  height: 32px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  box-shadow: none;
  color: var(--km-hub-muted);
  cursor: pointer;
}
.km-search__clear.km-search__clear:hover,
.km-search__back.km-search__back:hover { color: var(--km-hub-title); background: var(--km-hub-hover); }
.km-search__clear.km-search__clear[hidden] { display: none; }
.km-search__back.km-search__back { display: none; }
.km-search__clear .km-hub-icon,
.km-search__back .km-hub-icon { width: 18px; height: 18px; }

.km-search__tabs { display: flex; flex-wrap: wrap; gap: 4px; }
.km-search__tabs[hidden] { display: none; }
.km-search__tab.km-search__tab,
.km-search__tab.km-search__tab:hover,
.km-search__tab.km-search__tab:focus {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  margin: 0;
  padding: 7px 12px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  box-shadow: none;
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--km-hub-title);
  cursor: pointer;
  white-space: nowrap;
}
.km-search__tab.km-search__tab:hover { background: var(--km-hub-hover); }
.km-search__tab.km-search__tab[aria-pressed="true"] { background: var(--km-hub-soft); }
.km-search__count { font-size: 13px; font-weight: 500; color: var(--km-hub-muted); }
.km-search__count:empty { display: none; }
.km-search__status { margin: 0; font-size: 13px; line-height: 1.4; color: var(--km-hub-muted); }
.km-search__status:empty { display: none; }

.km-search__groups { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 4px 28px; }
.km-search__col { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.km-search__group { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.km-search__group-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 0 6px; }
.km-search .km-search__group-title {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 0;
  font-family: var(--km-hub-font);
  font-size: 12px;
  font-weight: 700;
  line-height: 1.4;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--km-hub-chip-ink);
}
.km-search__more.km-search__more,
.km-search__more.km-search__more:hover,
.km-search__more.km-search__more:focus {
  margin: 0;
  padding: 2px 4px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  box-shadow: none;
  font-family: var(--km-hub-font);
  font-size: 13px;
  font-weight: 700;
  color: var(--km-hub-title);
  cursor: pointer;
}
.km-search__more.km-search__more:hover { color: var(--km-hub-accent); }
.km-search__rows { margin: 0; padding: 0; list-style: none; }
.km-search__rows > li { margin: 0; padding: 0; }
.km-search__row,
.km-search__row:visited {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 8px 6px;
  border-radius: 10px;
  color: var(--km-hub-ink);
  text-decoration: none;
}
.km-search__row:hover { background: var(--km-hub-hover); color: var(--km-hub-ink); }
.km-search__row:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 1px; }
.km-search__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 8px;
  background: var(--km-hub-badge);
  color: var(--km-hub-accent);
}
.km-search__icon .km-hub-icon { width: 16px; height: 16px; }
.km-search__row-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.km-search__row-title { font-size: 15px; font-weight: 600; line-height: 1.35; color: var(--km-hub-ink); overflow-wrap: anywhere; }
.km-search__row-where { font-size: 13px; line-height: 1.35; color: var(--km-hub-muted); overflow-wrap: anywhere; }
.km-search__mark { padding: 0 1px; border-radius: 3px; background: var(--km-hub-mark); color: inherit; }

/* Тело окна — место ответа маршрута: группы или список вкладки. */
.km-search__body { min-width: 0; }
.km-search__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding-top: 12px;
  border-top: 1px solid var(--km-hub-line);
}
.km-search__foot[hidden] { display: none; }
.km-search__hint { font-size: 13px; color: var(--km-hub-muted); }
.km-search__all.km-search__all,
.km-search__all.km-search__all:hover,
.km-search__all.km-search__all:focus {
  margin: 0;
  padding: 4px 6px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  box-shadow: none;
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 700;
  color: var(--km-hub-title);
  cursor: pointer;
}
.km-search__all.km-search__all:hover { color: var(--km-hub-accent); }

.km-search__empty { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 40px 16px; text-align: center; }
.km-search__empty[hidden] { display: none; }
.km-search__empty-icon { display: inline-flex; align-items: center; justify-content: center; width: 56px; height: 56px; border-radius: 50%; background: var(--km-hub-soft); color: var(--km-hub-accent); }
.km-search__empty-icon .km-hub-icon { width: 24px; height: 24px; }
.km-search__empty-title { margin: 0; font-family: var(--km-hub-font); font-size: 18px; font-weight: 700; color: var(--km-hub-ink); }
.km-search__empty-hint { max-width: 340px; margin: 0; font-size: 14px; line-height: 1.5; color: var(--km-hub-muted); }

.km-search__list { margin: 0; padding: 0; list-style: none; }
.km-search__list[hidden] { display: none; }
.km-search__item { display: flex; gap: 14px; margin: 0; padding: 16px 18px; border-top: 1px solid var(--km-hub-line-soft); }
.km-search__item:first-child { border-top: 0; }
.km-search__list--pop .km-search__item { padding: 12px 6px; }
.km-search__item-body { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.km-search__lead { margin: 0; font-size: 12.5px; line-height: 1.4; color: var(--km-hub-muted); overflow-wrap: anywhere; }
.km-search__item-title,
.km-search__item-title:visited { font-size: 16px; font-weight: 700; line-height: 1.35; color: var(--km-hub-ink); text-decoration: none; overflow-wrap: anywhere; }
.km-search__item-title:hover { color: var(--km-hub-accent); }
.km-search__excerpt { margin: 0; font-size: 14px; line-height: 1.55; color: var(--km-hub-ink); overflow-wrap: anywhere; }
.km-search__meta { margin: 0; font-size: 12.5px; line-height: 1.4; color: var(--km-hub-muted); }

.km-hub.km-search-page .km-search-page__inner { display: flex; flex-direction: column; gap: 16px; max-width: 860px; margin: 0 auto; }
.km-search-page .km-search__toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.km-search-page .km-search__list { border: 1px solid var(--km-hub-line); border-radius: 14px; background: #fff; }
.km-search__next-wrap { display: flex; justify-content: center; }
.km-search__next[hidden] { display: none; }
.km-search__sort { position: relative; }
.km-search__sort[hidden] { display: none; }
.km-search__sort-button { list-style: none; font-size: 14px; font-weight: 600; color: var(--km-hub-title); cursor: pointer; }
.km-search__sort-button::-webkit-details-marker { display: none; }
.km-search__sort-button::after { content: " ▾"; font-size: 11px; color: var(--km-hub-muted); }
.km-search__sort-menu { position: absolute; top: calc(100% + 6px); right: 0; z-index: 5; display: flex; flex-direction: column; min-width: 210px; padding: 6px; border: 1px solid var(--km-hub-line); border-radius: 12px; background: #fff; box-shadow: 0 10px 30px rgba(59, 42, 71, 0.14); }
.km-search__sort-item.km-search__sort-item,
.km-search__sort-item.km-search__sort-item:hover,
.km-search__sort-item.km-search__sort-item:focus {
  margin: 0;
  padding: 8px 10px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  box-shadow: none;
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 500;
  text-align: left;
  color: var(--km-hub-ink);
  cursor: pointer;
}
.km-search__sort-item.km-search__sort-item:hover,
.km-search__sort-item.km-search__sort-item[aria-checked="true"] { background: var(--km-hub-soft); }

.km-hub .km-hub-comment--found { margin: -6px; padding: 6px; border-radius: 12px; background: var(--km-hub-pin); }

@media (max-width: 640px) {
  .km-hub.km-search { padding: 0; background: #fff; }
  .km-search__panel { width: 100%; height: 100%; max-height: none; padding: 10px 12px 16px; border-radius: 0; box-shadow: none; }
  .km-search__back.km-search__back { display: inline-flex; }
  .km-search__esc { display: none; }
  .km-search__field { height: 46px; background: var(--km-hub-field); border-color: transparent; }
  .km-search__tabs { flex-wrap: nowrap; overflow-x: auto; margin: 0 -12px; padding: 0 12px; scrollbar-width: none; }
  .km-search__tabs::-webkit-scrollbar { display: none; }
  .km-search__groups { grid-template-columns: minmax(0, 1fr); }
  .km-search__hint { display: none; }
  .km-search-page .km-search__item { padding: 14px 12px; }
}

/* ===== Вход и регистрация (документ сообщества 1.93; доска design/auth-v6.dc.html) =====
   Свой документ без темы (`templates/auth.php`): ни шапки, ни меню, ни таблиц темы — только эта. Палитра и шрифты —
   сообщества (`--km-hub-*`, KM Manrope и KM Oswald). Компьютер (от 960): экран пополам — картинка «Лавандовый рассвет»
   со светлой дымкой и тёмным текстом слева, форма справа. Уже — без картинки, узкая строка с логотипом и «← На сайт»;
   форма регистрации с подсказкой про согласие и кнопкой помещается на 320×568, подвал — ниже, при прокрутке.
   Кнопки красные, как в сообществе; выбранное — бледно-сиреневое, без тёмной заливки. */

body.km-auth-body { margin: 0; background: #fff; color: var(--km-hub-ink); font-family: var(--km-hub-font); }
.km-auth { display: flex; min-height: 100vh; min-height: 100dvh; box-sizing: border-box; padding: 14px; gap: 0; background: #fff; color: var(--km-hub-ink); font-family: var(--km-hub-font); font-size: 15px; line-height: 1.5; }
.km-auth *, .km-auth *::before, .km-auth *::after { box-sizing: border-box; }
.km-auth .km-hub-icon { width: 18px; height: 18px; flex: none; }

/* Левая половина */
.km-auth__hero { position: relative; flex: 0 0 50%; display: flex; flex-direction: column; justify-content: space-between; gap: 24px; overflow: hidden; padding: 32px 34px 28px; border-radius: 22px; color: var(--km-hub-title); }
.km-auth__hero-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Светлая дымка сверху — тёмный текст читается на картинке. */
.km-auth__hero::after { content: ''; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(255, 255, 255, 0.62) 0%, rgba(255, 255, 255, 0.35) 30%, rgba(255, 255, 255, 0) 48%); pointer-events: none; }
.km-auth__hero-top, .km-auth__perks { position: relative; z-index: 1; }
.km-auth__hero-top { display: flex; flex-direction: column; gap: 26px; }
.km-auth__pitch { display: flex; flex-direction: column; gap: 10px; max-width: 440px; }
.km-auth p.km-auth__pitch-title { margin: 0; font-family: var(--km-hub-display); font-size: 40px; font-weight: 500; line-height: 1.1; color: var(--km-hub-title); }
.km-auth p.km-auth__pitch-text { margin: 0; font-size: 15px; line-height: 1.5; color: var(--km-hub-chip-ink); }
.km-auth__perks { display: flex; flex-direction: column; gap: 12px; padding: 14px 18px; border: 1px solid rgba(255, 255, 255, 0.75); border-radius: 16px; background: rgba(255, 255, 255, 0.62); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); }
.km-auth p.km-auth__perks-title { margin: 0; font-size: 14px; font-weight: 700; color: var(--km-hub-ink); }
.km-auth__perks-list { display: flex; gap: 8px; margin: 0; padding: 0; list-style: none; }
.km-auth__perk { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 6px; font-size: 13px; font-weight: 700; color: var(--km-hub-title); }
.km-auth__perk-icon { display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; border-radius: 50%; background: #fff; color: var(--km-hub-accent); box-shadow: 0 2px 8px rgba(59, 42, 71, 0.10); }
.km-auth__perk-icon .km-hub-icon { width: 20px; height: 20px; }

/* Логотип с подписью: «Центр обучения» мелко над жирным «Ключи Мастерства», оба с большой буквы, без капса. */
.km-auth-brand { display: flex; align-items: center; gap: 12px; }
.km-auth-brand__logo { display: block; flex: none; width: 52px; height: 52px; border-radius: 50%; box-shadow: 0 4px 14px rgba(0, 0, 0, 0.18); }
.km-auth-brand__text { display: flex; flex-direction: column; gap: 1px; }
.km-auth-brand__over { font-size: 12px; font-weight: 600; line-height: 1.3; color: var(--km-hub-muted); }
.km-auth-brand__name { font-family: var(--km-hub-display); font-size: 20px; font-weight: 600; line-height: 1.2; color: var(--km-hub-title); }

/* Правая половина */
.km-auth__side { flex: 1; min-width: 0; display: flex; flex-direction: column; padding: 6px 10px 0 40px; }
.km-auth__bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.km-auth__bar-brand { display: none; }
.km-auth a.km-auth__back { display: inline-flex; align-items: center; gap: 6px; font-size: 14px; font-weight: 700; color: var(--km-hub-link); text-decoration: none; }
.km-auth a.km-auth__back .km-hub-icon { width: 16px; height: 16px; }
.km-auth__center { flex: 1; display: flex; align-items: center; justify-content: center; padding: 24px 0; }
.km-auth__box { width: 100%; max-width: 400px; display: flex; flex-direction: column; gap: 18px; }

/* Переключатель «Вход / Регистрация» */
.km-auth-seg { display: flex; gap: 4px; padding: 4px; border-radius: 12px; background: var(--km-hub-hover); }
.km-auth a.km-auth-seg__item { flex: 1; display: flex; align-items: center; justify-content: center; height: 40px; border-radius: 9px; font-size: 15px; font-weight: 600; color: var(--km-hub-muted); text-decoration: none; }
.km-auth a.km-auth-seg__item:hover { color: var(--km-hub-ink); }
.km-auth a.km-auth-seg__item[aria-current="page"] { background: var(--km-hub-soft); color: var(--km-hub-ink); font-weight: 700; box-shadow: inset 0 0 0 1px var(--km-hub-pin-card-line); }

/* Заголовки — как шапка «Сообщества»: мелкая серая надпись, под ней Oswald с большой буквы. */
.km-auth__head { display: flex; flex-direction: column; gap: 8px; }
.km-auth__titles { display: flex; flex-direction: column; gap: 8px; }
.km-auth p.km-auth__eyebrow { margin: 0; font-size: 12px; font-weight: 700; line-height: 1.4; letter-spacing: 0.08em; text-transform: uppercase; color: var(--km-hub-muted); }
.km-auth h1.km-auth__title { margin: 0; font-family: var(--km-hub-display); font-size: 40px; font-weight: 500; line-height: 1.1; letter-spacing: normal; text-transform: none; color: var(--km-hub-title); }
.km-auth p.km-auth__lead { margin: 0; font-size: 15px; line-height: 1.55; color: var(--km-hub-chip-ink); }
.km-auth .km-auth__strong { font-weight: 700; color: var(--km-hub-ink); overflow-wrap: anywhere; }
.km-auth p.km-auth__alt { margin: 0; font-size: 15px; line-height: 1.55; text-align: center; color: var(--km-hub-chip-ink); }
.km-auth p.km-auth__small { margin: 0; font-size: 13px; text-align: center; color: var(--km-hub-muted); }
.km-auth a.km-auth__link { font-weight: 700; color: var(--km-hub-link); text-decoration: none; }
.km-auth a.km-auth__link:hover { color: var(--km-hub-accent); text-decoration: underline; }
.km-auth a.km-auth__doc { font-weight: 600; color: var(--km-hub-link); text-decoration: underline; text-decoration-color: var(--km-hub-dash); text-underline-offset: 2px; }
.km-auth a.km-auth__return { display: flex; align-items: center; justify-content: center; gap: 6px; font-size: 14px; font-weight: 700; color: var(--km-hub-link); text-decoration: none; }
.km-auth a.km-auth__return .km-hub-icon { width: 16px; height: 16px; }
.km-auth__badge { display: flex; align-items: center; justify-content: center; width: 64px; height: 64px; border-radius: 50%; background: var(--km-hub-soft); color: var(--km-hub-link); }
.km-auth__badge .km-hub-icon { width: 30px; height: 30px; }

/* Форма */
.km-auth-form { display: flex; flex-direction: column; gap: 16px; margin: 0; }
.km-auth-field { display: flex; flex-direction: column; gap: 7px; }
.km-auth-field__row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.km-auth label.km-auth-field__label { margin: 0; font-size: 14px; font-weight: 700; color: var(--km-hub-ink); }
.km-auth-field__row a.km-auth__link { font-size: 14px; }
.km-auth-field__box { position: relative; display: flex; align-items: center; gap: 10px; height: 50px; padding: 0 14px; border: 1px solid var(--km-hub-chip-line); border-radius: 12px; background: var(--km-hub-field); color: var(--km-hub-muted); }
.km-auth-field__box:focus-within { border-color: var(--km-hub-accent); background: #fff; }
.km-auth-field--error .km-auth-field__box { border-color: var(--km-hub-red); }
.km-auth input.km-auth-field__input { flex: 1; min-width: 0; height: 100%; margin: 0; padding: 0; border: 0; border-radius: 0; background: transparent; box-shadow: none; outline: none; font-family: inherit; font-size: 16px; font-weight: 400; color: var(--km-hub-ink); }
.km-auth button.km-auth-field__eye,
.km-auth button.km-auth-field__eye:hover,
.km-auth button.km-auth-field__eye:focus { display: flex; align-items: center; justify-content: center; width: 32px; height: 32px; margin: 0 -6px 0 0; padding: 0; border: 0; border-radius: 8px; background: transparent; box-shadow: none; color: var(--km-hub-muted); cursor: pointer; }
.km-auth button.km-auth-field__eye:hover { color: var(--km-hub-ink); }
.km-auth button.km-auth-field__eye .km-hub-icon + .km-hub-icon { display: none; }
.km-auth button.km-auth-field__eye[aria-pressed="true"] .km-hub-icon:first-child { display: none; }
.km-auth button.km-auth-field__eye[aria-pressed="true"] .km-hub-icon + .km-hub-icon { display: block; }
.km-auth p.km-auth-field__error,
.km-auth p.km-auth-consent__error { margin: 0; font-size: 13px; font-weight: 600; line-height: 1.4; color: var(--km-hub-red); }
.km-auth p.km-auth-field__note { margin: 0; font-size: 13px; line-height: 1.45; color: var(--km-hub-muted); }
.km-auth p.km-auth-error { margin: 0; padding: 12px 14px; border-radius: 12px; background: #FBEDEB; font-size: 14px; font-weight: 600; line-height: 1.45; color: var(--km-hub-red-deep); }
.km-auth p.km-auth-notice { margin: 0; padding: 12px 14px; border-radius: 12px; background: var(--km-hub-soft); font-size: 14px; font-weight: 600; line-height: 1.45; color: var(--km-hub-ink); }
.km-auth-known { display: flex; align-items: center; gap: 10px; height: 50px; padding: 0 14px; border: 1px solid var(--km-hub-chip-line); border-radius: 12px; background: var(--km-hub-field); color: var(--km-hub-muted); }
.km-auth-known__value { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 16px; color: var(--km-hub-ink); }

/* Ловушка для ботов и подсказка менеджеру паролей — вне экрана и вне порядка Tab. */
.km-auth .km-auth-trap { position: absolute; left: -10000px; top: auto; width: 1px; height: 1px; overflow: hidden; }

/* Галочки согласий — как у окон сообщества: отмеченная — знак на цвете акцента. */
.km-auth-consents { display: flex; flex-direction: column; gap: 12px; }
.km-auth-consent { display: flex; flex-direction: column; gap: 6px; }
.km-auth-consent__error { padding-left: 30px; }
.km-auth label.km-auth-check { position: relative; display: flex; align-items: flex-start; gap: 10px; margin: 0; font-size: 13px; font-weight: 400; line-height: 1.5; color: var(--km-hub-chip-ink); cursor: pointer; }
.km-auth label.km-auth-check input { position: absolute; width: 1px; height: 1px; margin: 0; opacity: 0; }
.km-auth-check__text { min-width: 0; }
.km-auth-check__box { position: relative; flex: none; width: 20px; height: 20px; margin-top: 1px; border: 1.5px solid var(--km-hub-box-line); border-radius: 6px; background: #fff; }
.km-auth label.km-auth-check input:checked + .km-auth-check__box { border-color: var(--km-hub-accent); background: var(--km-hub-accent); }
.km-auth label.km-auth-check input:checked + .km-auth-check__box::after { content: ''; position: absolute; left: 5.5px; top: 2px; width: 5px; height: 10px; border-right: 2px solid #fff; border-bottom: 2px solid #fff; transform: rotate(45deg); }
.km-auth label.km-auth-check input:focus-visible + .km-auth-check__box { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-auth-consent--error .km-auth-check__box { border-color: var(--km-hub-red); }

/* Кнопки — красная, как в сообществе; вторая — белая с рамкой. */
.km-auth button.km-auth-submit,
.km-auth button.km-auth-submit:hover,
.km-auth button.km-auth-submit:focus,
.km-auth button.km-auth-submit:active { display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%; height: 52px; margin: 0; padding: 0 20px; border: 0; border-radius: 12px; background: var(--km-hub-red); box-shadow: 0 6px 16px rgba(200, 67, 58, 0.25); color: #fff; font-family: inherit; font-size: 16px; font-weight: 700; line-height: 1; text-transform: none; cursor: pointer; }
.km-auth button.km-auth-submit:hover { background: var(--km-hub-red-deep); }
.km-auth button.km-auth-submit .km-hub-icon { stroke-width: 2.2; }
.km-auth button.km-auth-second,
.km-auth button.km-auth-second:hover,
.km-auth button.km-auth-second:focus,
.km-auth a.km-auth-second { display: flex; align-items: center; justify-content: center; width: 100%; height: 48px; margin: 0; padding: 0 16px; border: 1px solid var(--km-hub-chip-line); border-radius: 12px; background: #fff; box-shadow: none; color: var(--km-hub-ink); font-family: inherit; font-size: 15px; font-weight: 700; line-height: 1; text-decoration: none; text-transform: none; cursor: pointer; }
.km-auth button.km-auth-second:hover,
.km-auth a.km-auth-second:hover { border-color: var(--km-hub-pin-card-line); background: var(--km-hub-hover); }
.km-auth button.km-auth-second[disabled] { color: var(--km-hub-muted); background: #fff; cursor: default; }
.km-auth-form[aria-busy="true"] button.km-auth-submit { opacity: 0.75; cursor: progress; }

/* Подсказка о почте под полем — общий скрипт `email-check.js`, классы свои. */
.km-auth-hint { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; margin-top: 2px; font-size: 13px; line-height: 1.45; color: var(--km-hub-chip-ink); }
.km-auth-hint--block { color: var(--km-hub-red); font-weight: 600; }
.km-auth-hint__text { min-width: 0; }
.km-auth button.km-auth-hint__fix,
.km-auth button.km-auth-hint__fix:hover,
.km-auth button.km-auth-hint__fix:focus { margin: 0; padding: 0; border: 0; background: transparent; box-shadow: none; color: var(--km-hub-link); font-family: inherit; font-size: 13px; font-weight: 700; text-decoration: underline; cursor: pointer; }

/* Подвал */
.km-auth__foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 16px 0 6px; font-size: 12px; color: var(--km-hub-muted); }
.km-auth__foot-links { display: flex; gap: 16px; }
.km-auth a.km-auth__foot-link { color: var(--km-hub-muted); text-decoration: none; }
.km-auth a.km-auth__foot-link:hover { color: var(--km-hub-ink); }

/* Уже 960 — без картинки: строка с логотипом и «← На сайт», форма по центру во всю ширину до 400. */
@media (max-width: 959.98px) {
  .km-auth { padding: 0; }
  .km-auth__hero { display: none; }
  .km-auth__side { padding: 0; }
  .km-auth__bar { flex: none; height: 48px; padding: 0 14px; border-bottom: 1px solid var(--km-hub-line-soft); }
  .km-auth__bar-brand { display: block; }
  .km-auth__bar .km-auth-brand { gap: 10px; }
  .km-auth__bar .km-auth-brand__logo { width: 32px; height: 32px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.16); }
  .km-auth__bar .km-auth-brand__over { font-size: 11px; }
  .km-auth__bar .km-auth-brand__name { font-size: 15px; }
  .km-auth a.km-auth__back { font-size: 12px; gap: 4px; }
  .km-auth a.km-auth__back .km-hub-icon { width: 14px; height: 14px; }
  .km-auth__center { align-items: flex-start; padding: 12px 16px 0; }
  .km-auth__box { gap: 11px; }
  /* Экран с переключателем заголовок не повторяет — остаётся экранному диктору. */
  .km-auth__titles--switch { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .km-auth__head,
  .km-auth__titles { gap: 4px; }
  .km-auth p.km-auth__eyebrow { display: none; }
  .km-auth h1.km-auth__title { font-size: 26px; }
  .km-auth p.km-auth__lead { font-size: 13px; line-height: 1.45; }
  .km-auth p.km-auth__alt { font-size: 13px; }
  .km-auth a.km-auth-seg__item { height: 36px; font-size: 14px; }
  .km-auth-form { gap: 11px; }
  .km-auth-field { gap: 5px; }
  .km-auth label.km-auth-field__label { font-size: 13px; }
  .km-auth-field__row a.km-auth__link { font-size: 13px; }
  .km-auth-field__box,
  .km-auth-known { height: 42px; }
  .km-auth-consents { gap: 8px; }
  .km-auth label.km-auth-check { font-size: 12.5px; line-height: 1.4; }
  .km-auth p.km-auth-field__error,
  .km-auth p.km-auth-consent__error { font-size: 12.5px; }
  .km-auth-consent { gap: 4px; }
  .km-auth button.km-auth-submit,
  .km-auth button.km-auth-submit:hover,
  .km-auth button.km-auth-submit:focus,
  .km-auth button.km-auth-submit:active { height: 46px; font-size: 15px; }
  .km-auth button.km-auth-second,
  .km-auth a.km-auth-second { height: 44px; font-size: 14px; }
  .km-auth p.km-auth-error,
  .km-auth p.km-auth-notice { padding: 10px 12px; font-size: 13px; }
  .km-auth__badge { width: 56px; height: 56px; }
  /* Подвал — ниже, при прокрутке: форма с кнопкой помещается в экран, подвал за ним. */
  .km-auth__foot { flex-direction: column; justify-content: flex-start; gap: 6px; margin-top: 24px; padding: 24px 16px 12px; font-size: 11px; }
  .km-auth__foot-links { gap: 12px; }
}

/* Вход на телефоне: подвал — сразу под формой, обычным отступом, а не прижат к низу экрана с пустотой над ним (задание
   Алены 15.10.2026, правки после проверки на iPhone). Блок с формой больше не растягивается на высоту экрана. */
@media (max-width: 767px) {
  .km-auth .km-auth__center { flex: none; }
}

/* --- Блок в шапке: лупа · колокольчик · фото с меню (документ сообщества 1.95, «Блок в шапке», «Колокольчик»;
   доска design/header-block-v1.dc.html) -------------------------------------------------------------------------
   Блок плагина в правом углу шапки любой темы (`Notices\HeaderBlock`). Стоит на страницах темы, куда приходит урезанная
   таблица (только `:root` и `.km-`), поэтому всё здесь — классами `.km-`; кнопки и ссылки — с силой против умолчаний
   темы для `button` и `a` (тема красит любую кнопку: радиус 100px, заливка, тень при наведении). Под курсором меняется
   только цвет. Размеры и цвета — с доски: кнопки 40, фото 38 (в меню 48), число 18 на красном, меню 300, колокольчик 390;
   на телефоне — фото 32, меню снизу, колокольчик на весь экран. */

.km-hdr { display: flex; align-items: center; gap: 10px; font-family: var(--km-hub-font); color: var(--km-hub-ink); }
/* Обёртка, куда на телефоне переезжает открытое окно (`header-block.js`, `lift()`): сама места не занимает. */
.km-hdr.km-hdr--layer { display: contents; }
.km-hdr .km-hdr__sep { width: 1px; height: 28px; margin: 0 2px; background: var(--km-hub-chip-line); flex: none; }
.km-hdr .km-hdr__wrap { position: relative; display: flex; align-items: center; flex: none; }

.km-hdr .km-hdr__btn.km-hdr__btn,
.km-hdr .km-hdr__btn.km-hdr__btn:hover,
.km-hdr .km-hdr__btn.km-hdr__btn:focus,
.km-hdr .km-hdr__btn.km-hdr__btn:active {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  box-shadow: none;
  color: #3F4C5C;
  cursor: pointer;
  flex: none;
}
.km-hdr .km-hdr__btn.km-hdr__btn:hover,
.km-hdr .km-hdr__btn.km-hdr__btn.km-hdr__btn--on { background: var(--km-hub-soft); color: var(--km-hub-title); }
.km-hdr .km-hdr__btn.km-hdr__btn:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-hdr .km-hdr__count {
  position: absolute;
  top: 2px;
  right: 2px;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  border-radius: 9px;
  background: var(--km-hub-red);
  color: #FFFFFF;
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  box-sizing: border-box;
}
.km-hdr .km-hdr__count[hidden] { display: none; }

.km-hdr .km-hdr__ava.km-hdr__ava,
.km-hdr .km-hdr__ava.km-hdr__ava:hover,
.km-hdr .km-hdr__ava.km-hdr__ava:focus,
.km-hdr .km-hdr__ava.km-hdr__ava:active {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  margin: 0 0 0 4px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  overflow: hidden;
  font-family: var(--km-hub-font);
  font-size: 13px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  flex: none;
}
.km-hdr .km-hdr__ava.km-hdr__ava.km-hdr__ava--on { box-shadow: 0 0 0 3px var(--km-hub-soft), 0 0 0 4px #C9B6D3; }
.km-hdr .km-hdr__ava.km-hdr__ava:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 3px; }
.km-hdr .km-hdr__photo { display: block; width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }

/* Кружки с инициалами — пять пар доски; первая — лиловая, как фото в шапке доски. */
.km-hdr .km-hdr__ava--t1, .km-notes .km-hdr__ava--t1 { background: var(--km-hub-read); color: var(--km-hub-link); }
.km-hdr .km-hdr__ava--t2, .km-notes .km-hdr__ava--t2 { background: #DCE4EF; color: #2F5A7A; }
.km-hdr .km-hdr__ava--t3, .km-notes .km-hdr__ava--t3 { background: #F3EAD9; color: #7A5A2A; }
.km-hdr .km-hdr__ava--t4, .km-notes .km-hdr__ava--t4 { background: #E6F0E3; color: #3E6B35; }
.km-hdr .km-hdr__ava--t5, .km-notes .km-hdr__ava--t5 { background: #E1ECF5; color: #2F5A7A; }

.km-hdr a.km-hdr__login,
.km-hdr a.km-hdr__login:visited,
.km-hdr a.km-hdr__login:hover,
.km-hdr a.km-hdr__login:focus {
  display: inline-flex;
  align-items: center;
  height: 38px;
  padding: 0 18px;
  border-radius: 10px;
  background: var(--km-hub-red);
  color: #FFFFFF;
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
}
.km-hdr a.km-hdr__login:hover { background: var(--km-hub-red-deep); }

/* Меню у фото. */
.km-hdr .km-pmenu {
  position: absolute;
  top: calc(100% + 12px);
  right: 0;
  z-index: 2147483001;
  display: flex;
  flex-direction: column;
  width: 300px;
  padding: 6px 0;
  background: #FFFFFF;
  border: 1px solid var(--km-hub-line);
  border-radius: 14px;
  box-shadow: 0 14px 36px rgba(59, 42, 71, 0.2);
  box-sizing: border-box;
  text-align: left;
}
.km-hdr .km-pmenu[hidden],
.km-hdr .km-pmenu__shade[hidden] { display: none; }
.km-hdr .km-pmenu__shade { display: none; }
.km-hdr .km-pmenu__grab { display: none; }

.km-hdr a.km-pmenu__top,
.km-hdr a.km-pmenu__top:visited,
.km-hdr a.km-pmenu__top:hover,
.km-hdr a.km-pmenu__top:focus {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px 14px;
  border-bottom: 1px solid var(--km-hub-line-soft);
  color: var(--km-hub-ink);
  text-decoration: none;
}
.km-hdr .km-pmenu__ava {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  overflow: hidden;
  font-size: 16px;
  font-weight: 700;
  flex: none;
}
.km-hdr .km-pmenu__who { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.km-hdr .km-pmenu__name { font-size: 15px; font-weight: 700; color: var(--km-hub-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.km-hdr .km-pmenu__login { font-size: 13px; color: #9A90A2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.km-hdr .km-pmenu__chev { display: none; margin-left: auto; color: #9A90A2; flex: none; }
.km-hdr .km-pmenu__list { display: flex; flex-direction: column; padding: 6px; border-bottom: 1px solid var(--km-hub-line-soft); }

.km-hdr a.km-pmenu__item,
.km-hdr a.km-pmenu__item:visited,
.km-hdr a.km-pmenu__item:hover,
.km-hdr a.km-pmenu__item:focus {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-radius: 8px;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 15px;
  line-height: 1.35;
  text-decoration: none;
}
.km-hdr a.km-pmenu__item:hover,
.km-hdr a.km-pmenu__item:focus-visible { background: var(--km-hub-soft); outline: none; }
.km-hdr a.km-pmenu__item.km-pmenu__out { margin: 6px 6px 2px; }
.km-hdr .km-pmenu__icon { width: 19px; height: 19px; color: var(--km-hub-muted); flex: none; }

/* Колокольчик. */
.km-hdr .km-bell {
  position: absolute;
  top: calc(100% + 12px);
  right: 0;
  z-index: 2147483001;
  display: flex;
  flex-direction: column;
  width: 390px;
  max-height: min(640px, calc(100vh - 120px));
  background: #FFFFFF;
  border: 1px solid var(--km-hub-line);
  border-radius: 14px;
  box-shadow: 0 14px 36px rgba(59, 42, 71, 0.2);
  box-sizing: border-box;
  overflow: hidden;
  text-align: left;
}
.km-hdr .km-bell[hidden] { display: none; }
.km-hdr .km-bell__head { display: flex; align-items: center; gap: 6px; padding: 14px 16px; border-bottom: 1px solid var(--km-hub-line-soft); flex: none; }
.km-hdr .km-bell__title { flex: 1; font-family: var(--km-hub-display); font-size: 20px; font-weight: 500; line-height: 1.2; color: var(--km-hub-title); }

.km-hdr .km-bell__all.km-bell__all,
.km-hdr .km-bell__all.km-bell__all:hover,
.km-hdr .km-bell__all.km-bell__all:focus,
.km-hdr .km-bell__all.km-bell__all:active,
.km-hdr .km-bell__back.km-bell__back,
.km-hdr .km-bell__back.km-bell__back:hover,
.km-hdr .km-bell__back.km-bell__back:focus,
.km-hdr .km-bell__back.km-bell__back:active {
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  font-family: var(--km-hub-font);
  font-size: 13px;
  font-weight: 700;
  line-height: 1.4;
  color: var(--km-hub-link);
  cursor: pointer;
}
.km-hdr .km-bell__all.km-bell__all:hover { color: var(--km-hub-title); }
.km-hdr .km-bell__all.km-bell__all:disabled { color: var(--km-hub-muted); cursor: default; }
.km-hdr .km-bell__back.km-bell__back { display: none; color: var(--km-hub-ink); }

.km-hdr .km-bell__list { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.km-hdr .km-bell__empty { margin: 0; padding: 22px 16px; font-size: 14px; line-height: 1.5; color: var(--km-hub-muted); }

.km-hdr a.km-bell__item, .km-notes a.km-bell__item,
.km-hdr a.km-bell__item:visited, .km-notes a.km-bell__item:visited,
.km-hdr a.km-bell__item:hover, .km-notes a.km-bell__item:hover,
.km-hdr a.km-bell__item:focus, .km-notes a.km-bell__item:focus,
.km-hdr div.km-bell__item, .km-notes div.km-bell__item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 16px;
  color: var(--km-hub-ink);
  text-decoration: none;
}
.km-hdr a.km-bell__item:hover, .km-notes a.km-bell__item:hover { background: var(--km-hub-hover); }
.km-hdr .km-bell__item.km-bell__item--new, .km-notes .km-bell__item.km-bell__item--new { background: #FAF6FC; }
.km-hdr a.km-bell__item.km-bell__item--new:hover, .km-notes a.km-bell__item.km-bell__item--new:hover { background: var(--km-hub-hover); }
.km-hdr .km-bell__face, .km-notes .km-bell__face {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  overflow: hidden;
  font-size: 12px;
  font-weight: 700;
  flex: none;
}
.km-hdr .km-bell__face--icon, .km-notes .km-bell__face--icon { background: var(--km-hub-soft); color: var(--km-hub-link); }
.km-hdr .km-bell__face .km-hub-icon, .km-notes .km-bell__face .km-hub-icon { width: 18px; height: 18px; }
.km-hdr .km-bell__photo, .km-notes .km-bell__photo { display: block; width: 100%; height: 100%; object-fit: cover; }
.km-hdr .km-bell__text, .km-notes .km-bell__text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; font-size: 14px; line-height: 1.45; color: #4A3E52; overflow-wrap: anywhere; }
.km-hdr .km-bell__item--new .km-bell__text, .km-notes .km-bell__item--new .km-bell__text { color: var(--km-hub-ink); }
.km-hdr .km-bell__text b, .km-notes .km-bell__text b { font-weight: 700; color: var(--km-hub-ink); }
/*
 * «Вернуться к …» — ссылка плагина User Switching вверху страницы, в блоке шапки (документ сообщества 1.107, «Вход
 * под человеком»; `Support\Impersonation::back()`). Плашку плагина в подвале гасит его же фильтр, когда эта
 * нарисована. Тёмная, чтобы не спутать с меню: администратор сейчас под чужой учёткой.
 */
.km-hdr a.km-hdr__back,
.km-hdr a.km-hdr__back:visited,
.km-hdr a.km-hdr__back:focus { display: inline-flex; align-items: center; gap: 6px; max-width: 240px; height: 36px; margin: 0 6px 0 0; padding: 0 12px 0 8px; border-radius: 10px; background: var(--km-hub-title); color: #fff; font-family: var(--km-hub-font); font-size: 13px; font-weight: 700; line-height: 1; text-decoration: none; white-space: nowrap; }
.km-hdr a.km-hdr__back:hover { background: var(--km-hub-link); color: #fff; }
.km-hdr a.km-hdr__back svg { flex: none; width: 18px; height: 18px; }
.km-hdr .km-hdr__back-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/*
 * На телефоне — одна стрелка 36×36, подпись остаётся для экранного диктора и в подсказке. Со словами ссылка в 132 px
 * сжимала логотип темы до нуля: в мобильной шапке места на неё нет (снимок боевого 12.10.2026, 1.478.1).
 */
@media (max-width: 760px) {
  .km-hdr a.km-hdr__back,
  .km-hdr a.km-hdr__back:visited,
  .km-hdr a.km-hdr__back:focus { justify-content: center; width: 36px; max-width: none; padding: 0; flex: none; }
  .km-hdr .km-hdr__back-text { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
}

/*
 * Смайл — размером с букву (задача Алены 12.10.2026: «☀️ раздувает строку»). Браузер, не умеющий новые эмодзи,
 * получает от скрипта WordPress картинку `img.emoji`, а тема BuddyBoss задаёт им всем 24×24 с полями по 3 px
 * (`img.emoji` в `theme.css`) — выше строки в 20 px. Правило WordPress «размером с букву» на сайте не печатается.
 * Замер на боевом 12.10.2026: строка колокольчика с ☀️ — 30 px вместо 20; то же в имени «Мария Величко ☀️»
 * в «Участниках» (1.478.1). Отсюда правило на всё, что рисуем мы: шапку и сообщество (лента, карточки, профили,
 * «Уведомления», всплывающие окна — у них тот же корень `km-hub`).
 */
.km-hdr img.emoji, .km-hub img.emoji { display: inline; width: 1em; height: 1em; margin: 0 0.07em; padding: 0; border: 0; box-shadow: none; background: none; vertical-align: -0.1em; }
.km-hdr .km-bell__ago, .km-notes .km-bell__ago { font-size: 12px; color: var(--km-hub-muted); }
.km-hdr .km-bell__dot, .km-notes .km-bell__dot { width: 8px; height: 8px; margin-top: 6px; border-radius: 50%; background: var(--km-hub-red); flex: none; }

.km-hdr .km-bell__foot { display: flex; align-items: center; justify-content: center; gap: 14px; height: 46px; border-top: 1px solid var(--km-hub-line-soft); flex: none; }
/* Внизу две ссылки — «Все уведомления» и «Настройки уведомлений» через черту (доска notifications-v1, часть 1). */
.km-hdr a.km-bell__link,
.km-hdr a.km-bell__link:visited,
.km-hdr a.km-bell__link:hover,
.km-hdr a.km-bell__link:focus {
  font-family: var(--km-hub-font);
  font-size: 13px;
  font-weight: 700;
  color: var(--km-hub-link);
  text-decoration: none;
}
.km-hdr a.km-bell__link:hover { color: var(--km-hub-title); }
.km-hdr .km-bell__sep { width: 1px; height: 16px; background: var(--km-hub-chip-line); }

.km-hdr-lock,
.km-hdr-lock body { overflow: hidden; }

/* Страница «Уведомления» — все уведомления и чистка (документ сообщества 1.105; доска notifications-v1, части 2–5) */
.km-hub .km-notes__col { width: 100%; max-width: 780px; gap: 22px; }
.km-notes .km-notes__tools { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.km-notes .km-notes__tools[hidden] { display: none; }
.km-notes .km-notes__count { flex: 1; font-family: var(--km-hub-font); font-size: 14px; font-weight: 700; color: var(--km-hub-chip-ink); }
.km-notes button.km-notes__btn,
.km-notes button.km-notes__btn:focus,
.km-notes button.km-notes__btn:active {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 38px;
  margin: 0;
  padding: 0 14px;
  border: 1px solid var(--km-hub-chip-line);
  border-radius: 10px;
  background: #fff;
  box-shadow: none;
  color: var(--km-hub-ink);
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  cursor: pointer;
}
.km-notes button.km-notes__btn:hover { border: 1px solid var(--km-hub-chip-line); background: var(--km-hub-hover); box-shadow: none; color: var(--km-hub-ink); }
.km-notes button.km-notes__btn:disabled { color: var(--km-hub-muted); cursor: default; }
.km-notes button.km-notes__btn:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-notes button.km-notes__btn.km-notes__btn--danger,
.km-notes button.km-notes__btn.km-notes__btn--danger:focus,
.km-notes button.km-notes__btn.km-notes__btn--danger:active { border: 0; background: var(--km-hub-red); color: #fff; }
.km-notes button.km-notes__btn.km-notes__btn--danger:hover { border: 0; background: var(--km-hub-red-deep); color: #fff; }
.km-notes button.km-notes__btn.km-notes__more { align-self: center; height: 42px; padding: 0 22px; }
.km-notes .km-notes__more[hidden] { display: none; }
.km-notes .km-notes__card { background: #fff; border: 1px solid var(--km-hub-line); border-radius: 14px; overflow: hidden; }
.km-notes .km-notes__card[hidden] { display: none; }
.km-notes .km-notes__item { position: relative; border-top: 1px solid #F6F3F8; }
.km-notes .km-notes__item:first-child { border-top: 0; }
.km-notes .km-notes__item a.km-bell__item,
.km-notes .km-notes__item div.km-bell__item { align-items: center; padding: 14px 58px 14px 18px; }
.km-notes .km-notes__item .km-bell__dot { margin-top: 0; }
/* Наведение — на всю строку, вместе с крестиком: он лежит поверх ссылки, а не в ней (кнопка в ссылке — не разметка). */
.km-notes .km-notes__card .km-notes__item:hover a.km-bell__item,
.km-notes .km-notes__card .km-notes__item:hover div.km-bell__item { background: var(--km-hub-label); }
.km-notes button.km-notes__del,
.km-notes button.km-notes__del:focus,
.km-notes button.km-notes__del:active {
  position: absolute;
  top: 50%;
  right: 14px;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  margin: -15px 0 0;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  box-shadow: none;
  color: var(--km-hub-muted);
  font-family: var(--km-hub-font);
  font-size: 14px;
  font-weight: 400;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  visibility: hidden;
  cursor: pointer;
}
.km-notes button.km-notes__del .km-hub-icon { width: 16px; height: 16px; }
/* Крестик — при наведении на строку и с клавиатуры; удаляет сразу (доска, часть 2). */
.km-notes .km-notes__item:hover button.km-notes__del,
.km-notes .km-notes__item:focus-within button.km-notes__del { visibility: visible; background: #fff; box-shadow: 0 1px 3px rgba(59, 42, 71, 0.15); color: var(--km-hub-title); }
.km-notes button.km-notes__del:focus-visible { outline: 2px solid var(--km-hub-accent); outline-offset: 2px; }
.km-notes button.km-notes__del::after {
  content: attr(data-tip);
  position: absolute;
  top: 36px;
  right: 0;
  z-index: 2;
  padding: 5px 9px;
  border-radius: 6px;
  background: var(--km-hub-title);
  color: #fff;
  font-family: var(--km-hub-font);
  font-size: 12px;
  font-weight: 700;
  line-height: 1.2;
  white-space: nowrap;
  visibility: hidden;
  pointer-events: none;
}
.km-notes button.km-notes__del:hover::after,
.km-notes button.km-notes__del:focus-visible::after { visibility: visible; }
.km-notes .km-notes__empty { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 28px 24px; background: #fff; border: 1px solid var(--km-hub-line); border-radius: 14px; text-align: center; }
.km-notes .km-notes__empty[hidden] { display: none; }
.km-notes p.km-notes__empty-title { margin: 0; font-family: var(--km-hub-display); font-size: 22px; font-weight: 500; line-height: 1.25; color: var(--km-hub-title); }
.km-notes p.km-notes__empty-text { margin: 0; max-width: 360px; font-family: var(--km-hub-font); font-size: 14px; line-height: 1.55; color: var(--km-hub-chip-ink); }
.km-notes p.km-notes__store { margin: 0; font-family: var(--km-hub-font); font-size: 13px; line-height: 1.5; color: var(--km-hub-muted); text-align: center; }
.km-notes .km-notes__store[hidden] { display: none; }
.km-notes p.km-notes__status:empty { display: none; }
/* «Удалить прочитанные» переспрашивает (доска, часть 4) */
.km-notes .km-notes-ask { position: fixed; inset: 0; z-index: 100000; display: flex; align-items: center; justify-content: center; padding: 16px; background: var(--km-hub-dark); }
.km-notes .km-notes-ask[hidden] { display: none; }
.km-notes .km-notes-ask__box { box-sizing: border-box; display: flex; flex-direction: column; gap: 10px; width: 400px; max-width: 100%; padding: 22px 24px; border-radius: 16px; background: #fff; box-shadow: 0 18px 44px rgba(59, 42, 71, 0.22); }
.km-notes h2.km-notes-ask__title { margin: 0; font-family: var(--km-hub-display); font-size: 22px; font-weight: 500; line-height: 1.25; color: var(--km-hub-title); }
.km-notes p.km-notes-ask__text { margin: 0; font-family: var(--km-hub-font); font-size: 14px; line-height: 1.55; color: var(--km-hub-chip-ink); }
.km-notes .km-notes-ask__btns { display: flex; justify-content: flex-end; gap: 10px; margin-top: 8px; }
.km-notes .km-notes-ask__btns button.km-notes__btn { height: 42px; padding: 0 18px; }
/*
 * 30 px сниппета сайта «Объединённый CSS» над `h1` до 782 гасятся (тот же ответ той же силой, что у каталога, — абзац
 * «ЧУЖОЕ ПОЛЕ НАД ЗАГОЛОВКОМ»): на «Уведомлениях» (1.477.2: над заголовком стоит «Ключи Мастерства», и 30 px разводили
 * их на 36 px вместо 6), в ленте «Сообщества» и на трёх страницах профиля — «Мой профиль», профиль участника
 * (`km-hub--profile`), «Настройки профиля» (`km-me`) — с 1.479.0 (документ сообщества 1.108, слово Алены 12.10.2026:
 * «шапки на телефоне должны совпасть с досками»). Вне блока телефона: сниппет действует до 782, а телефон здесь —
 * до 760. С 1.483.0 — и на странице результатов поиска (`km-search-page`), и в приглашении войти для гостя (`km-me__title`)
 * (документ сообщества 1.112, слово Алены 12.10.2026: «убери лишние 30 точек над заголовком»).
 */
.km-hub.km-hub--feed h1.km-hub__title,
.km-hub.km-hub--profile h1.km-hub__title,
.km-hub.km-me h1.km-hub__title,
.km-hub.km-notes h1.km-hub__title,
.km-hub.km-search-page h1.km-hub__title,
.km-page.km-me h1.km-me__title { padding-top: 0 !important; }
@media (max-width: 760px) {
  /* Телефон: числа над списком нет, кнопки друг под другом во всю ширину, крестик виден всегда (доска, часть 3). */
  .km-hub .km-notes__col { gap: 12px; }
  /*
   * Шапка на телефоне — как на доске: «Ключи Мастерства» над заголовком и заголовок 32. Общее правило сообщества
   * прячет надстрочник и мельчит заголовок до 28 (лента, профили) — здесь доска рисует иначе, и правило сужено
   * корнем страницы, остальные шапки не задеты.
   */
  .km-hub.km-notes p.km-hub__eyebrow { display: block; }
  .km-hub.km-notes h1.km-hub__title { font-size: 32px; }
  .km-notes .km-notes__tools { flex-direction: column; align-items: stretch; gap: 8px; }
  .km-notes .km-notes__count { display: none; }
  .km-notes .km-notes__tools button.km-notes__btn { width: 100%; }
  .km-notes .km-notes__item a.km-bell__item,
  .km-notes .km-notes__item div.km-bell__item { align-items: flex-start; gap: 10px; padding: 12px 42px 12px 12px; }
  .km-notes .km-notes__item .km-bell__dot { margin-top: 7px; }
  .km-notes button.km-notes__del,
  .km-notes button.km-notes__del:focus,
  .km-notes button.km-notes__del:active { top: 12px; right: 6px; margin: 2px 0 0; visibility: visible; }
  .km-notes button.km-notes__del::after { display: none; }
}
/*
 * Устройство без мыши (планшет, например iPad; документ сообщества 1.108, слово Алены 12.10.2026): навести не на что —
 * крестик виден всегда, как на телефоне, и подсказки «Удалить» нет (на касании `:hover` залипает после нажатия).
 * С мышью на любой ширине — по-прежнему при наведении. Место крестика — компьютерное: у планшета строка широкая.
 */
@media (hover: none) {
  .km-notes button.km-notes__del,
  .km-notes button.km-notes__del:focus,
  .km-notes button.km-notes__del:active { visibility: visible; }
  .km-notes button.km-notes__del::after { display: none; }
}


/* Телефон: фото 32, меню у фото — снизу экрана с подложкой, колокольчик — на весь экран. */
@media (max-width: 767px) {
  .km-hdr { gap: 12px; }
  .km-hdr .km-hdr__sep { display: none; }
  .km-hdr .km-hdr__btn.km-hdr__btn,
  .km-hdr .km-hdr__btn.km-hdr__btn:hover,
  .km-hdr .km-hdr__btn.km-hdr__btn:focus,
  .km-hdr .km-hdr__btn.km-hdr__btn:active { width: 36px; height: 36px; }
  .km-hdr .km-hdr__ava.km-hdr__ava,
  .km-hdr .km-hdr__ava.km-hdr__ava:hover,
  .km-hdr .km-hdr__ava.km-hdr__ava:focus,
  .km-hdr .km-hdr__ava.km-hdr__ava:active { width: 32px; height: 32px; margin: 0; font-size: 12px; }

  .km-hdr .km-pmenu__shade { position: fixed; inset: 0; z-index: 2147483000; display: block; background: rgba(46, 36, 51, 0.32); }
  .km-hdr .km-pmenu {
    position: fixed;
    top: auto;
    right: 0;
    bottom: 0;
    left: 0;
    width: auto;
    max-height: 85vh;
    padding: 8px 0 calc(14px + env(safe-area-inset-bottom, 0px));
    border: 0;
    border-radius: 18px 18px 0 0;
    box-shadow: 0 -10px 30px rgba(59, 42, 71, 0.18);
    overflow-y: auto;
  }
  .km-hdr .km-pmenu__grab { display: block; width: 40px; height: 4px; margin: 2px auto 6px; border-radius: 2px; background: #DDD6E2; flex: none; }
  .km-hdr .km-pmenu__chev { display: block; }

  .km-hdr .km-bell {
    position: fixed;
    inset: 0;
    padding-top: env(safe-area-inset-top, 0px);
    width: auto;
    max-height: none;
    border: 0;
    border-radius: 0;
    box-shadow: none;
  }
  /*
   * «Отметить все как прочитанные» — своей строкой под заголовком «Уведомления», в одну строку (документ сообщества
   * 1.108, слово Алены 12.10.2026): рядом с заголовком она переносилась на две. Начало — под началом заголовка:
   * стрелка 32 и промежуток 6. На компьютере — по-прежнему справа от заголовка.
   */
  .km-hdr .km-bell__head { flex-wrap: wrap; row-gap: 4px; min-height: 56px; padding: 12px 14px; box-sizing: border-box; }
  .km-hdr .km-bell__back.km-bell__back { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; }
  .km-hdr .km-bell__all.km-bell__all,
  .km-hdr .km-bell__all.km-bell__all:hover,
  .km-hdr .km-bell__all.km-bell__all:focus,
  .km-hdr .km-bell__all.km-bell__all:active { flex: 0 0 100%; padding-left: 38px; text-align: left; white-space: nowrap; }
  .km-hdr a.km-bell__foot { padding-bottom: env(safe-area-inset-bottom, 0px); }
}

/* ==========================================================================
   Звёзды курса — раздел «Награда за курс» в настройках курса (4.21).
   Прототип `design/course/zvezdy-materialy-v2.html`, экран «Награда за курс
   (команда)». Коробка и строки — `km-box` и `km-set`, таблица — `km-table`,
   поля — `km-field`, `km-input`, `km-select`, галки — `km-check`. Своё здесь
   только то, чего в системе нет: «Для кого сколько», список материалов
   деревом, «Не из материалов курса», знак рядом с полями, узкое число,
   сводка по строкам «Для кого сколько».
   ========================================================================== */

.km-stars-set__cap {
  margin: 0 0 10px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--km-text-muted);
}

.km-stars-set__stack { display: flex; flex-direction: column; gap: 10px; }
.km-stars-set__stack > .km-stars-set__cap { margin: 0; }

.km-stars-set__switch .km-set__name { font-size: 15.5px; font-weight: 700; }

/* «Звёзды в курсе» — три положения (звёзды курса 1.21, раздел 4, п. 1): выбор одного из трёх, кнопками в ряд;
   на узком переносятся. Выбранное — тёплой подложкой и рамкой акцента. */
.km-stars-mode { display: flex; flex-wrap: wrap; gap: 8px; min-width: 0; margin: 0; padding: 0; border: 0; }
.km-stars-mode__legend { flex: 0 0 100%; margin: 0 0 2px; padding: 0; font-size: 15.5px; font-weight: 700; }
.km-stars-mode__opt { position: relative; display: inline-flex; align-items: center; min-height: 40px; padding: 8px 14px; border: 1px solid var(--km-border); border-radius: var(--km-radius-control); background: var(--km-surface); color: var(--km-text); font-size: 14px; font-weight: 600; line-height: 1.3; cursor: pointer; }
.km-stars-mode__opt input { position: absolute; opacity: 0; width: 0; height: 0; }
.km-stars-mode__opt:hover { border-color: var(--km-warm-border); }
.km-stars-mode__opt:has(input:checked) { border-color: var(--km-accent); background: var(--km-warm-bg); }
.km-stars-mode__opt:has(input:focus-visible) { box-shadow: 0 0 0 3px var(--km-warm-bg); }

/* «Начать проверку сначала» на вкладке «Награда» — только команде (звёзды курса 1.21, раздел 4, п. 1). */
.km-stars-check { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px 16px; }
.km-stars-check__text { flex: 1 1 260px; min-width: 0; margin: 0; font-size: 14px; line-height: 1.5; color: var(--km-text-secondary); }

.km-stars-set__text { margin: 0; font-size: 14px; line-height: 1.6; color: var(--km-text-secondary); }

/* «Для кого сколько»: кто — жирным, что входит — мелко под ним; выключено — серым. */
.km-stars-aud__row td { vertical-align: top; }
.km-stars-aud__who { font-weight: 700; }
.km-stars-aud__sub { display: block; font-size: 12px; color: var(--km-text-muted); }

/* Галка «Награда — за отзыв, без нормы» под потоком в «Для кого сколько» (документ 1.16, раздел 4). */
.km-stars-aud__review { margin-top: 6px; font-size: 13px; }
.km-stars-aud__row--off td { color: var(--km-text-muted); }

/* «За что даются звёзды» — материалы курса деревом. */
.km-stars-mat__tools { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px; }

.km-stars-mat { font-size: 14px; line-height: 1.45; border-collapse: collapse; }
.km-stars-mat td { padding-top: 8px; padding-bottom: 8px; vertical-align: top; }
.km-stars-mat td.km-stars-mat__cat,
.km-stars-mat td.km-stars-mat__st { padding-top: 6px; padding-bottom: 6px; white-space: nowrap; }
.km-stars-mat td.km-stars-mat__st { text-align: right; }

.km-stars-mat__row--module td { background: var(--km-surface-alt); border-top: 1px solid var(--km-border); }
.km-stars-mat__row--module .km-stars-mat__title { font-weight: 700; font-size: 15px; }
.km-stars-mat__row--lesson .km-stars-mat__title { font-weight: 600; }
.km-stars-mat__row.is-zero .km-stars-mat__title { color: var(--km-text-muted); }
.km-stars-mat__row.is-zero .km-stars-mat__sub { color: var(--km-text-faint); }

.km-stars-mat__line { display: flex; align-items: flex-start; gap: 8px; min-width: 0; }
.km-stars-mat__line--1 { padding-left: 32px; }
.km-stars-mat__line--2 { padding-left: 64px; }

button.km-stars-mat__tog {
  flex: none;
  width: 26px;
  height: 26px;
  margin-top: 3px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--km-border);
  border-radius: 7px;
  background: var(--km-surface);
  color: var(--km-text-secondary);
  cursor: pointer;
}

button.km-stars-mat__tog svg { transition: transform 0.15s; }
button.km-stars-mat__tog[aria-expanded="false"] svg { transform: rotate(-90deg); }

.km-stars-mat__gap { flex: none; width: 26px; }

.km-stars-mat__title { min-width: 0; padding-top: 5px; }

.km-stars-mat__sub { display: block; font-weight: 400; font-size: 12px; line-height: 1.4; color: var(--km-text-muted); }

.km-select.km-stars-mat__select { width: auto; max-width: 100%; height: 36px; min-height: 36px; padding-top: 0; padding-bottom: 0; font-size: 14px; }

/* Таблицы раздела без карточки — как в прототипе: строки на белом коробки, рамки только между строками. Обёртка
   прокрутки остаётся (`TableScrollTest`), карточку с неё снимает таблица внутри. */
.km-table-scroll:has(> .km-stars-set__plain) { border: none; border-radius: 0; box-shadow: none; background: none; }

.km-stars-mat__fix { display: inline-block; padding-top: 7px; font-size: 14px; color: var(--km-text-secondary); }

.km-stars-mat .km-input.km-stars-set__num { width: 62px; height: 36px; }

/* «Не из материалов курса»: что это — слева, числа — справа. */
.km-stars-x {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 6px 16px;
  align-items: start;
  padding: 12px 0;
  border-bottom: 1px solid var(--km-border-soft);
}

.km-stars-x:last-child { border-bottom: none; }

.km-stars-x__text { min-width: 0; }

.km-stars-x__name { display: block; font-size: 14.5px; }

.km-stars-x__about { font-size: 13px; color: var(--km-text-secondary); }

.km-stars-x__value { display: flex; align-items: center; gap: 10px; font-size: 14px; color: var(--km-text-secondary); white-space: nowrap; }

.km-stars-x__value--two { flex-direction: column; align-items: flex-start; gap: 8px; }

.km-stars-x__pair { display: inline-flex; align-items: center; gap: 8px; }

.km-stars-set__award { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 16px; }

.km-stars-set__badge-box { flex: none; display: flex; }

.km-stars-set__badge { display: block; width: 72px; height: 72px; object-fit: contain; }

.km-stars-set__award-fields {
  flex: 1 1 220px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: flex-start;
}

.km-stars-set__award-fields .km-field { width: 100%; }

.km-stars-set__row {
  margin-top: 16px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
}

.km-stars-set__row:first-child { margin-top: 0; }

.km-stars-set__aside { flex: 1 1 220px; min-width: 0; margin: 0; }

/* Узкое число — две цифры: `km-input--number` рассчитан на сумму. */
.km-input.km-stars-set__num { width: 68px; min-width: 0; padding: 7px 10px; }

.km-stars-set__line { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 8px; font-size: 14px; color: var(--km-text-secondary); }

.km-stars-set__table { font-variant-numeric: tabular-nums; }

.km-stars-set__table .km-stars-set__n { text-align: right; white-space: nowrap; }

.km-stars-set__table tfoot td {
  padding: 12px 12px;
  font-size: 14px;
  font-weight: 700;
  border-top: 1px solid var(--km-border);
}

.km-stars-set__sum {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 24px;
  background: var(--km-warm-bg);
  border: 1px solid var(--km-warm-border);
  border-radius: 12px;
  padding: 14px 18px;
  font-size: 15px;
  color: var(--km-warm-text);
}

.km-stars-set__big {
  font-family: var(--km-font-display);
  font-size: 24px;
  font-weight: 700;
  color: var(--km-warm-text-strong);
}

.km-stars-set__save { margin-top: 14px; }

/* Итог — строками «Для кого сколько»: столбцом, число поменьше. */
.km-stars-set__sum--aud { flex-direction: column; align-items: flex-start; gap: 6px; }
.km-stars-set__sum--aud .km-stars-set__big { font-size: 20px; }

@media (max-width: 640px) {
  .km-stars-mat thead { display: none; }
  .km-stars-mat,
  .km-stars-mat tbody { display: block; }
  .km-stars-mat tr {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 6px 10px;
    position: static;
    margin: 0;
    padding: 10px 12px;
    background: none;
    border: none;
    border-bottom: 1px solid var(--km-border-soft);
    border-radius: 0;
    box-shadow: none;
  }
  .km-stars-mat tr[hidden] { display: none; }
  .km-stars-mat .km-stars-mat__row--module { background: var(--km-surface-alt); border-top: 1px solid var(--km-border); }
  /* Сильнее общего `.km-table td:first-child` (флажок в углу карточки): тот же вес, позже в файле. */
  .km-table.km-stars-mat td,
  .km-stars-mat .km-stars-mat__row--module td { display: block; position: static; padding: 0; border: none; background: none; }
  .km-stars-mat td > div { overflow: visible; white-space: normal; }
  .km-stars-mat td.km-stars-mat__name { grid-column: 1 / -1; }
  .km-stars-mat td.km-stars-mat__cat { min-width: 0; }
  .km-stars-mat__line--1 { padding-left: 16px; }
  .km-stars-mat__line--2 { padding-left: 32px; }
  .km-stars-mat td.km-stars-mat__cat .km-select { width: 100%; }
  .km-stars-x { grid-template-columns: minmax(0, 1fr); }
  .km-stars-x__pair { flex-wrap: wrap; }
  .km-stars-set__sum { gap: 10px 20px; }
}

/* ==========================================================================
   Звёзды курса — что видит участник (4.21). Прототип `design/course/zvezdy-v4.html`:
   вкладка «Награда», карточка «Награда за курс», блок «Что даёт занятие»,
   плашка «+N» на «Отметить пройденным», окошки.
   Полоса — `<progress class="km-progress__bar km-stars-bar">`: значение
   и предел — данные (правило 13), здесь только её высота.
   ========================================================================== */

.km-stars-icon { flex: none; display: inline-block; vertical-align: -2px; }

.km-stars-bar { height: 8px; border-radius: 4px; }
.km-stars-bar::-webkit-progress-bar { border-radius: 4px; }
.km-stars-bar::-webkit-progress-value { border-radius: 4px; }
.km-stars-bar::-moz-progress-bar { border-radius: 4px; }

.km-stars-total { margin: 0; font-size: 14px; line-height: 1.35; color: var(--km-text-secondary); }

.km-stars-big {
  font-family: var(--km-font-display);
  font-size: 30px;
  font-weight: 700;
  line-height: 1;
  color: var(--km-text);
}

/* Кнопка-ссылка: «Показать ещё N», «Как получить награду →» — никуда не ведут, переключают на месте. */
.km-stars-link {
  align-self: flex-start;
  background: none;
  border: none;
  padding: 0;
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  color: var(--km-accent);
  cursor: pointer;
}

.km-stars-link:hover { color: var(--km-accent-light); }

/* --- Вкладка «Награда»: шапка ------------------------------------------- */
.km-stars-head { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 22px; }
.km-stars-head__badge { flex: none; display: block; width: 88px; height: 88px; object-fit: contain; }
.km-stars-head__txt { flex: 1 1 240px; min-width: 0; display: flex; flex-direction: column; gap: 8px; }

.km-stars-head__title {
  margin: 0;
  font-family: var(--km-font-display);
  font-size: 26px;
  font-weight: 700;
  line-height: 1.25;
}

.km-stars-head__prog { display: flex; flex-direction: column; gap: 8px; margin-top: 6px; }
.km-stars-head__go { align-self: flex-start; }

/* --- «За что даются звёзды» -------------------------------------------- */
.km-stars-rules-wrap { overflow-x: auto; }

.km-stars-rules {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
  font-variant-numeric: tabular-nums;
}

.km-stars-rules th {
  text-align: left;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--km-text-muted);
  padding: 10px 12px;
  border-bottom: 1px solid var(--km-border);
  white-space: nowrap;
}

/* Числа — по первой строке названия, а не посередине названия с условием под ним (слово Алены 14.10.2026). */
.km-stars-rules td { padding: 11px 12px; border-bottom: 1px solid var(--km-border-soft); vertical-align: top; }
.km-stars-rules tbody tr:last-child td { border-bottom: none; }
.km-stars-rules tfoot td { font-weight: 700; border-top: 1px solid var(--km-border); border-bottom: none; }
.km-stars-rules .km-stars-rules__n { text-align: right; white-space: nowrap; }
.km-stars-rules__sub { display: block; font-size: 12px; color: var(--km-text-muted); }
.km-stars-rules .km-stars-rules__got { color: var(--km-accent); font-weight: 700; }
.km-stars-rules .km-stars-rules__zero { color: var(--km-text-muted); }

/* --- «История звёзд» ----------------------------------------------------- */
.km-stars-hist { display: flex; flex-direction: column; }

.km-stars-hist__row {
  display: flex;
  align-items: baseline;
  gap: 14px;
  padding: 10px 0;
  border-top: 1px solid var(--km-border-soft);
  font-size: 14px;
}

.km-stars-hist__row:first-child { border-top: none; }
.km-stars-hist__date { flex: none; width: 96px; font-size: 13px; color: var(--km-text-muted); }
.km-stars-hist__what { flex: 1; min-width: 0; }

.km-stars-hist__plus {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-weight: 700;
  color: var(--km-warm-text-strong);
}

/* --- Карточка «Награда за курс» ----------------------------------------- */
.km-stars-card__row { display: flex; align-items: flex-start; gap: 14px; }
.km-stars-card__badge { flex: none; display: block; width: 52px; height: 52px; object-fit: contain; }
.km-stars-card__txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.km-stars-card__go { align-self: flex-start; }

/* --- Блок «Что даёт занятие» --------------------------------------------- */
.km-stars-gives { border-radius: 20px; padding: 20px 24px; display: flex; flex-direction: column; gap: 12px; }
.km-stars-gives__head { margin: 0; display: flex; align-items: center; gap: 10px; font-size: 15px; font-weight: 700; }
.km-stars-gives__rows { display: flex; flex-direction: column; }

/* Плашка «+N» — напротив первой строки названия, по её верху, а не по центру строки (слово Алены 14.10.2026). */
.km-stars-gives__row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 11px 0;
  border-top: 1px solid var(--km-border-soft);
  font-size: 14.5px;
  line-height: 1.4;
}

.km-stars-gives__row:first-child { border-top: none; }

.km-stars-gives__what {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
  color: inherit;
  text-decoration: none;
}

a.km-stars-gives__what:hover { color: var(--km-accent); }
.km-stars-gives__what small { font-size: 12.5px; color: var(--km-text-muted); }

.km-stars-plq {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  white-space: nowrap;
  font-size: 13px;
  font-weight: 700;
  line-height: 1;
  color: var(--km-warm-text-strong);
  background: var(--km-warm-bg);
  border: 1px solid var(--km-warm-border);
  border-radius: 8px;
  padding: 5px 9px;
}

.km-stars-plq--got { color: var(--km-done); background: var(--km-done-bg); border-color: var(--km-done-border); }

/* В строке блока плашка встаёт СЕРЕДИНОЙ НА СЕРЕДИНУ ПЕРВОЙ СТРОКИ названия — «напротив первой строки» (слово Алены
   14.10.2026). Плашка выше строки: 26 px (рамка 1 + поле 5 + звезда 14 + поле 5 + рамка 1) против строки 14,5 × 1,4 =
   20,3 px, — и по верху строки она свисала бы вниз на 6 px. Числа сложены здесь потому, что все три объявлены выше
   (`.km-stars-gives__row`, `.km-stars-plq`); разъедутся — покраснеет мерка стендов `firstLines`. */
.km-stars-gives__row > .km-stars-plq { margin-top: calc( ( 14.5px * 1.4 - 26px ) / 2 ); }

/* --- Блок «Бонус курса» и окно «Подробнее» ------------------------------
   Звёзды курса 1.22, раздел 6.3а; прототип `design/course/bonus-kursa-v2.html`, вариант 1 — буквально, на токенах.
   Имена `km-bonus*` проверены на занятость: в системе их не было.

   Блок стоит внутри содержимого темы, окно выносится в конец страницы — туда, где у темы голые `h2`, `p`, `a`
   и `button` с классом страницы. Поэтому всё внутри держится весом (0,2,0) — родитель и свой класс, — а не порядком
   таблиц (CLAUDE.md, «ничья по силе»). Кнопка «Подробнее» — `button`, и у темы на ней радиус, рамка и тень
   в `:hover` и `:focus`: они сняты для всех трёх состояний (общая мерка стендов `themeBleed`). */
.km-bonus { border-radius: 20px; padding: 20px 24px; display: flex; flex-direction: column; gap: 14px; }
.km-bonus .km-bonus__head { display: flex; align-items: flex-start; gap: 14px; }

/* Квадратик строки бонуса — вид «В» прототипа `design/course/bonus-vid-v3.html` (замки из «А», выбрано 14.10.2026):
   серый замок на светло-сером, у открытого — зелёная галочка на светло-зелёном. Одно на блок и окно «Подробнее». */
.km-bonus__ic {
  flex: none;
  width: 32px;
  height: 32px;
  border-radius: 9px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--km-border-soft);
  color: var(--km-text-muted);
}

.km-bonus__ic--open { background: var(--km-done-bg); color: var(--km-done); }

.km-bonus .km-bonus__ht { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }

.km-bonus .km-bonus__kicker {
  font-size: 12px;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--km-text-muted);
}

.km-bonus .km-bonus__title {
  font-family: var(--km-font-display);
  font-size: 22px;
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--km-text);
}

.km-bonus__chip {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1;
  white-space: nowrap;
  border-radius: 8px;
  padding: 5px 9px;
}

.km-bonus__chip--ended { color: var(--km-text-secondary); background: var(--km-border-soft); }

/* Порог справа в шапке одного бонуса — «37 ★» вместо «Пока закрыт» (вид «Б», выбрано 14.10.2026). */
.km-bonus__need {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding-top: 1px;
  font-size: 14px;
  font-weight: 700;
  line-height: 1.35;
  white-space: nowrap;
  color: var(--km-text-secondary);
}
.km-bonus__chip--open { color: var(--km-done); background: var(--km-done-bg); border: 1px solid var(--km-done-border); }

.km-bonus .km-bonus__text { margin: 0; font-size: 15.5px; line-height: 1.6; color: var(--km-text); }

/* Полоса до порога — `<progress>`: число данными, оформление здесь (правило 13 про оформление, а не про данные). */
.km-bonus__bar {
  appearance: none;
  -webkit-appearance: none;
  display: block;
  width: 100%;
  height: 8px;
  border: none;
  border-radius: 4px;
  background: var(--km-track);
  overflow: hidden;
}

.km-bonus__bar::-webkit-progress-bar { background: var(--km-track); border-radius: 4px; }
.km-bonus__bar::-webkit-progress-value { background: var(--km-accent); border-radius: 4px; }
.km-bonus__bar::-moz-progress-bar { background: var(--km-accent); border-radius: 4px; }

.km-bonus .km-bonus__acts { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }

/* Крупно «★ У вас {N} звёзд»: число — `km-stars-big`, как в карточке «Награда за курс» (слово Алены 14.10.2026). */
.km-bonus .km-bonus__total {
  margin: 0;
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  font-size: 15px;
  line-height: 1.35;
  white-space: nowrap;
  color: var(--km-text-secondary);
}

.km-bonus__total .km-stars-icon { align-self: center; }

/* Строка со счётом под полосой одного бонуса: «У вас», «звёзд», «осталось M» и «Подробнее» — на одной линии текста,
   той же, что низ цифр крупного числа (по базовой линии; слово Алены 14.10.2026, вариант «Б» прототипа
   `design/course/bonus-vid-v3.html`). Звезда — по центру числа (`align-self: center` выше). До 1.511.0 строка
   стояла по центру, и слова справа сидели выше слов у числа. Сила селектора (0,3,0) — поверх общего `__acts`. */
.km-bonus .km-bonus__acts.km-bonus__acts--count { align-items: baseline; }
.km-bonus .km-bonus__left { font-size: 15px; line-height: 1.35; color: var(--km-text-secondary); }

/* Число звёзд и шкала с порогами под шапкой «Все бонусы курса» (вид «В»). */
.km-bonus .km-bonus__scale { display: flex; flex-direction: column; gap: 8px; }

.km-bonus__more,
.km-bonus__more:hover,
.km-bonus__more:focus,
.km-bonus__more:active {
  display: inline;
  margin: 0;
  padding: 0;
  background: none;
  border: none;
  border-radius: 0;
  box-shadow: none;
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.4;
  color: var(--km-accent);
  text-decoration: none;
  text-transform: none;
  letter-spacing: normal;
  cursor: pointer;
}

.km-bonus__more:hover { text-decoration: underline; }
.km-bonus__more:focus-visible { outline: 2px solid var(--km-accent); outline-offset: 2px; }

.km-bonus .km-bonus__list { display: flex; flex-direction: column; }

.km-bonus__row,
.km-bonus-dlg__row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  border-top: 1px solid var(--km-border-soft);
}

.km-bonus__row { padding: 12px 0; }
.km-bonus__row:first-child { border-top: none; padding-top: 2px; }

.km-bonus__w { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.km-bonus__row .km-bonus__name { font-size: 15.5px; font-weight: 600; line-height: 1.35; color: var(--km-text); }
.km-bonus__row .km-bonus__sub { font-size: 13.5px; line-height: 1.45; color: var(--km-text-secondary); }
.km-bonus__sub a { color: var(--km-accent); font-weight: 600; text-decoration: none; }
.km-bonus__sub a:hover { text-decoration: underline; }

/* Звёзды смотрящему не видны — только «Перейти к бонусу» (6.3а). */
.km-bonus-go { display: flex; flex-wrap: wrap; gap: 10px; }

/* Окно «Как открываются бонусы». Выше всего на странице, как окно на платформе: чат и вкладка «Заметили ошибку?»
   над подложкой читались бы частью окна. */
.km-modal.km-bonus-dlg { z-index: 2147483600; padding: 16px; }

.km-bonus-dlg .km-bonus-dlg__box {
  max-width: 560px;
  max-height: calc(100vh - 32px);
  padding: 28px 28px 22px;
  border-radius: 20px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.km-bonus-dlg .km-bonus-dlg__x,
.km-bonus-dlg .km-bonus-dlg__x:hover,
.km-bonus-dlg .km-bonus-dlg__x:focus {
  top: 16px;
  right: 16px;
  width: 36px;
  height: 36px;
  font-size: 16px;
  color: var(--km-text-secondary);
  background: var(--km-surface);
  border: 1px solid var(--km-border);
  border-radius: 10px;
  box-shadow: none;
}

.km-bonus-dlg .km-bonus-dlg__x:hover { color: var(--km-accent); border-color: var(--km-warm-border); }

.km-bonus-dlg .km-bonus-dlg__h {
  margin: 0;
  padding-right: 44px;
  font-family: var(--km-font-display);
  font-size: 26px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--km-text);
}

/* Текст сверху — мелко, как подписи под названиями бонусов в этом же окне (слово Алены 14.10.2026). */
.km-bonus-dlg .km-bonus-dlg__lead { margin: 0; font-size: 13px; line-height: 1.4; color: var(--km-text-secondary); }

/* «★ У вас N звёзд» в окне — по базовой линии, звезда по центру числа, как у счёта в блоке (слово Алены 14.10.2026). */
.km-bonus-dlg .km-bonus-dlg__me {
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: 6px;
  padding: 12px 16px;
  font-size: 15px;
  line-height: 1.35;
  color: var(--km-warm-text-strong);
  background: var(--km-warm-bg);
  border: 1px solid var(--km-warm-border);
  border-radius: 14px;
}

.km-bonus-dlg__me b { font-family: var(--km-font-display); font-size: 22px; line-height: 1; }
.km-bonus-dlg__me .km-stars-icon { align-self: center; margin-right: 4px; }

.km-bonus-dlg .km-bonus-dlg__sec {
  margin: 8px 0 0;
  font-size: 12px;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--km-text-muted);
}

.km-bonus-dlg .km-bonus-dlg__rows { display: flex; flex-direction: column; }
.km-bonus-dlg .km-bonus-dlg__row { padding: 9px 0; font-size: 15px; line-height: 1.4; color: var(--km-text); }
.km-bonus-dlg .km-bonus-dlg__row:first-child { border-top: none; }
.km-bonus-dlg__row .km-bonus__name { font-weight: 400; }
.km-bonus-dlg__row .km-bonus__sub { font-size: 13px; color: var(--km-text-secondary); }

.km-bonus-dlg__n {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-weight: 700;
  white-space: nowrap;
  color: var(--km-warm-text-strong);
}

.km-bonus-dlg .km-bonus-dlg__note { margin: 0; font-size: 14px; line-height: 1.55; color: var(--km-text-secondary); }

.km-bonus-dlg .km-bonus-dlg__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px 16px;
  margin-top: 4px;
  padding-top: 16px;
  border-top: 1px solid var(--km-border);
}

/* Телефон: у карточки поля меньше, окно выезжает снизу. Плашка состояния в шапке остаётся — в виде «Б» прототипа
   `design/course/bonus-vid-v3.html` она есть и на телефоне (до 1.510.0 уходила). */
@media (max-width: 560px) {
  .km-bonus { padding: 18px; }
  .km-bonus .km-bonus__title { font-size: 20px; }
  .km-modal.km-bonus-dlg { align-items: flex-end; padding: 0; }
  .km-bonus-dlg .km-bonus-dlg__box { max-height: 90vh; padding: 22px 18px 18px; border-radius: 20px 20px 0 0; }
  .km-bonus-dlg .km-bonus-dlg__h { font-size: 22px; }
  .km-bonus-dlg .km-bonus-dlg__foot .km-btn { width: 100%; }
}

/* --- Блок «Награда за курс» ----------------------------------------------
   Звёзды курса 1.33, раздел 6.3б; прототип `design/course/nagrada-blok-v1.html`, вид А — буквально, на токенах.
   Имена `km-award*` проверены на занятость: в системе их не было (`km-stars-award*` — поздравление, другое имя).

   Блок стоит внутри содержимого темы — всё держится весом (0,2,0), родитель и свой класс, а не порядком таблиц
   (CLAUDE.md, «ничья по силе»). Знак, норма и плашка — по верхнему краю заголовка (`flex-start`, поля — прототипа;
   решение Алены 14.10.2026 «по верхнему краю первой строки, а не по центру»). */
.km-award { border-radius: 20px; padding: 24px 28px; display: flex; flex-direction: column; gap: 16px; }
.km-award .km-award__head { display: flex; align-items: flex-start; gap: 20px; }

/* Знак 120 px: картинка из настроек награды курса или временная медаль (`StarArt::badge()`). До награды — серый
   и приглушённый; после — в цвете, с мягким золотым свечением за ним. */
.km-award .km-award__medal {
  flex: none;
  position: relative;
  width: 120px;
  height: 120px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.km-award .km-award__badge {
  position: relative;
  z-index: 1;
  display: block;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: contain;
  transition: filter 0.5s ease, opacity 0.5s ease;
}

.km-award .km-award__medal--off .km-award__badge { filter: grayscale(1); opacity: 0.42; }

.km-award .km-award__medal--on::before {
  content: "";
  position: absolute;
  inset: -14px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(244, 183, 64, 0.38), rgba(244, 183, 64, 0) 68%);
}

.km-award .km-award__ht { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; padding-top: 6px; }

.km-award .km-award__kicker {
  font-size: 12px;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--km-text-muted);
}

.km-award .km-award__title {
  font-family: var(--km-font-display);
  font-size: 26px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: var(--km-text);
  text-wrap: balance;
  overflow-wrap: anywhere;
}

/* Норма справа в шапке — «{норма} ★». */
.km-award .km-award__need {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding-top: 8px;
  font-size: 15px;
  font-weight: 700;
  line-height: 1.65;
  white-space: nowrap;
  color: var(--km-text-secondary);
}

/* Плашка «✓ Получена» после награды. */
.km-award .km-award__chip {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-top: 6px;
  padding: 5px 9px;
  border: 1px solid var(--km-done-border);
  border-radius: 8px;
  background: var(--km-done-bg);
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1;
  white-space: nowrap;
  color: var(--km-done);
}

.km-award .km-award__text { margin: 0; font-size: 15.5px; line-height: 1.6; color: var(--km-text); }

/* Полоса до нормы — `<progress>`: число данными, оформление здесь (правило 13 про оформление, а не про данные). */
.km-award .km-award__bar {
  appearance: none;
  -webkit-appearance: none;
  display: block;
  width: 100%;
  height: 8px;
  border: none;
  border-radius: 4px;
  background: var(--km-track);
  overflow: hidden;
}

.km-award__bar::-webkit-progress-bar { background: var(--km-track); border-radius: 4px; }
.km-award__bar::-webkit-progress-value { background: var(--km-accent); border-radius: 4px; }
.km-award__bar::-moz-progress-bar { background: var(--km-accent); border-radius: 4px; }

.km-award .km-award__foot { display: flex; align-items: center; gap: 12px 18px; flex-wrap: wrap; }

/* «★ У вас {N} звёзд · осталось M» — по базовой линии крупного числа, как у блока бонуса. */
.km-award .km-award__foot.km-award__foot--count { align-items: baseline; }

.km-award .km-award__total {
  margin: 0;
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  font-size: 15px;
  line-height: 1.35;
  white-space: nowrap;
  color: var(--km-text-secondary);
}

.km-award__total .km-stars-icon { align-self: center; }

.km-award .km-award__left { font-size: 15px; line-height: 1.35; color: var(--km-text-secondary); }

/* «✓ Отзыв о курсе написан {дата}». */
.km-award .km-award__ok {
  margin: 0;
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 14.5px;
  font-weight: 600;
  line-height: 1.5;
  color: var(--km-done);
}

.km-award__ok svg { flex: none; margin-top: 3px; }

/* «Как получить награду →», «Посмотреть награду →» — ссылка на вкладку «Награда». */
.km-award .km-award__more,
.km-award .km-award__more:hover,
.km-award .km-award__more:focus,
.km-award .km-award__more:active {
  font-size: 15px;
  font-weight: 600;
  line-height: 1.4;
  color: var(--km-accent);
  text-decoration: none;
}

.km-award .km-award__more:hover { text-decoration: underline; }
.km-award .km-award__more:focus-visible { outline: 2px solid var(--km-accent); outline-offset: 2px; }

/* Телефон (6.3б): знак 84 px слева от заголовка, норма и плашка справа скрыты, кнопка — во всю ширину. */
@media (max-width: 560px) {
  .km-award { padding: 18px; }
  .km-award .km-award__head { gap: 14px; }
  .km-award .km-award__medal { width: 84px; height: 84px; }
  .km-award .km-award__ht { padding-top: 2px; }
  .km-award .km-award__title { font-size: 21px; }
  .km-award .km-award__need,
  .km-award .km-award__chip { display: none; }
  .km-award .km-award__go { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  .km-award .km-award__badge { transition: none; }
}

/* --- Челленджи («Челленджи» 1.0, раздел 3) --------------------------------
   Доски `design/course/chellendzh-*-v2.dc.html` — устройство, порядок и размеры буквально; цвета — токены этой
   системы (доски нарисованы в другой палитре). Имена `km-chal*` проверены на занятость: в системе их не было.
   Блок и строка стоят внутри содержимого темы — всё держится весом (0,2,0), а не порядком таблиц.
   Кружки с номером и галочки — по верхнему краю первой строки текста (`align-items: flex-start`). */
.km-chal { border-radius: 20px; padding: 20px 24px; display: flex; flex-direction: column; }
.km-chal .km-chal__head { display: flex; flex-direction: column; gap: 6px; padding-bottom: 14px; }
.km-chal .km-chal__kicker {
  margin: 0;
  font-size: 12px;
  font-weight: 800;
  line-height: 1.3;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--km-warn-text);
}
.km-chal .km-chal__title {
  margin: 0;
  font-family: var(--km-font-display);
  font-size: 24px;
  font-weight: 700;
  line-height: 1.15;
  color: var(--km-text);
  overflow-wrap: anywhere;
}
.km-chal .km-chal__goal { margin: 0; font-size: 14px; line-height: 1.55; color: var(--km-text-secondary); }

/* Строка этапа и строка медали: кружок 44 (медаль — 48) слева, текст справа. */
.km-chal .km-chal__stage,
.km-chal .km-chal__medal {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 14px 0;
  border-top: 1px solid var(--km-border-soft);
}
.km-chal .km-chal__medal--won {
  margin: 0 -24px -20px;
  padding: 14px 24px 20px;
  border-radius: 0 0 20px 20px;
  background: var(--km-star-bg);
}

/* «Без рамки» («Челленджи» 1.5, 3.1): ни подложки, ни рамки, ни тени, ни полей — блок стоит в чужой карточке;
   полоса медали — без скруглённых углов и без вылета за поля, которых нет. */
.km-chal.km-chal--bare { padding: 0; border-radius: 0; background: none; border: 0; box-shadow: none; }
.km-chal.km-chal--bare .km-chal__medal--won { margin: 0; padding: 14px 16px 16px; border-radius: 0; }

/* «Получили медаль» и «Править челлендж →» внутри полосы полученной медали (1.5, 3.1): без своей черты — полоса и так
   отделяет их от этапов. */
.km-chal__medal--won .km-chal-peers { margin-top: 12px; padding-top: 0; border-top: 0; }
.km-chal__medal--won .km-chal-edit { padding-top: 8px; }

.km-chal__num {
  flex: none;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--km-border-soft);
  color: var(--km-text-secondary);
  font-family: var(--km-font-display);
  font-size: 19px;
  font-weight: 700;
  line-height: 1;
}
.km-chal__num--done { background: var(--km-done-bg); color: var(--km-done); }
/* ЦИФРА — ПО ВЕРХУ ПЕРВОЙ СТРОКИ (правило 2 октября 2026, `CLAUDE.md`, «Правила отображения»): верх цифры в кружке —
   на одной линии с верхом букв «Неделя 1» (над формой — «Неделя 1 · 4 из 7 дней»). Кружок 44 держит цифру посередине,
   и без сдвига она стояла на 11,5 px (над формой — на 10,1) ниже букв. Пройденный кружок с галочкой — тем же сдвигом:
   ряд кружков не прыгает. Мерка — `stand.numberTops()`, допуск 2 px. */
.km-chal .km-chal__stage .km-chal__num { margin-top: -11.5px; }
.km-chal-line .km-chal__num { margin-top: -10.1px; }

.km-chal .km-chal__lock,
.km-chal .km-chal__badge {
  flex: none;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.km-chal .km-chal__lock { background: var(--km-border-soft); color: var(--km-text-muted); }
.km-chal .km-chal__badge img,
.km-chal .km-chal__badge svg { display: block; width: 48px; height: 48px; max-width: none; object-fit: contain; }

.km-chal__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.km-chal .km-chal__label {
  font-size: 12px;
  font-weight: 800;
  line-height: 1.3;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--km-text-secondary);
}
.km-chal .km-chal__name { font-size: 16px; font-weight: 700; line-height: 1.3; color: var(--km-text); overflow-wrap: anywhere; }
.km-chal .km-chal__days { font-size: 14px; line-height: 1.45; color: var(--km-text-secondary); }
.km-chal .km-chal__muted,
.km-chal-line .km-chal__muted { font-size: 13px; line-height: 1.5; color: var(--km-text-secondary); }
.km-chal .km-chal__done {
  margin-top: 8px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 13px;
  font-weight: 700;
  line-height: 1.4;
  color: var(--km-done);
}
.km-chal__done svg { flex: none; }
.km-chal .km-chal__link,
.km-chal .km-chal__link:hover,
.km-chal .km-chal__link:focus {
  margin-top: 8px;
  align-self: flex-start;
  font-size: 14px;
  font-weight: 700;
  line-height: 1.4;
  color: var(--km-accent);
  text-decoration: none;
}
.km-chal .km-chal__link:hover { text-decoration: underline; }

/* Блок и шорткод «Челлендж» на любой странице («Челленджи» 1.4, 3.1). Своих полей у места нет — ширину и поля даёт
   страница; карточка ресурса — во всю ширину места, а не колонкой 330 со страницы ресурса. */
.km-chal-place { width: 100%; max-width: none; min-width: 0; }
.km-chal-place.km-rp .km-rp-ch { width: 100%; }

/* «Получили медаль: N» и лица — внизу блока в обоих видах. Лица — до восьми, на узком — сколько влезает в строку:
   ряд не переносится, лишнее уходит за край ряда, а не страницы. */
.km-chal-peers { display: flex; align-items: center; gap: 12px; min-width: 0; margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--km-border); }
.km-rp-ch .km-chal-peers { border-top-color: var(--km-rp-ch-line); }
.km-chal-peers__text { flex: none; font-size: 14px; font-weight: 600; line-height: 1.4; color: var(--km-text-secondary); }
.km-rp-ch .km-chal-peers__text { color: var(--km-rp-ch-ink); }
.km-chal-peers__faces { flex: 0 1 auto; min-width: 0; overflow: hidden; }
.km-chal-peers__faces .km-avatars__item { flex: none; }

/* «Править челлендж →» — команде, последней строкой блока. */
.km-chal-edit { margin: 0; padding-top: 12px; font-size: 13px; line-height: 1.4; }
.km-chal-edit a.km-chal-edit__link,
.km-chal-edit a.km-chal-edit__link:visited { font-weight: 700; color: var(--km-text-secondary); text-decoration: none; }
.km-chal-edit a.km-chal-edit__link:hover,
.km-chal-edit a.km-chal-edit__link:focus-visible { color: var(--km-accent); text-decoration: none; }
.km-chal .km-chal__bonus {
  margin-top: 6px;
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 14px;
  line-height: 1.45;
  color: var(--km-text);
}
.km-chal__bonus svg { flex: none; margin-top: 2px; color: var(--km-warn-text); }

/* Точки по дням: пустая — кольцо, засчитанная — залита акцентом. */
.km-chal-dots { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.km-chal-dots--center { justify-content: center; }
.km-chal-dot {
  flex: none;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1.5px solid var(--km-border);
  background: var(--km-surface);
}
.km-chal-dot--on { background: var(--km-accent); border-color: var(--km-accent); }

/* Строка над формой этапа (3.2): карточка над формой, кружок по верху первой строки. */
/* Белая, как соседние карточки занятия: подложка, рамка, радиус и тень — от `km-card` (1.5, 3.2; Алена 23.10:
   «страшненький, другого цвета» — на доске она с цветной подложкой, верно то, что в спецификации). */
.km-chal-line {
  padding: 14px 16px;
  display: flex;
  align-items: flex-start;
  gap: 12px;
}
.km-chal-line .km-chal-line__head { font-size: 15px; font-weight: 700; line-height: 1.35; color: var(--km-text); }
.km-chal-line .km-chal-line__text { margin-top: 6px; }

/* Окошки «День засчитан» и «Неделя пройдена» (3.3): карточка поверх страницы. */
.km-chal-pop {
  position: fixed;
  inset: 0;
  z-index: 100001;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  overflow: auto;
  background: rgba(31, 27, 52, 0.38);
}
.km-chal-pop .km-chal-pop__box {
  width: 100%;
  max-width: 380px;
  border-radius: 20px;
  padding: 24px 20px 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  text-align: center;
  background: var(--km-surface);
  box-shadow: 0 18px 48px rgba(31, 27, 52, 0.22);
}
.km-chal-pop .km-chal-pop__frac {
  width: 84px;
  height: 84px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--km-warm-bg);
  color: var(--km-accent);
  font-family: var(--km-font-display);
  font-size: 30px;
  font-weight: 700;
  line-height: 1;
}
.km-chal-pop .km-chal-pop__badge {
  width: 96px;
  height: 96px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--km-done-bg);
  color: var(--km-done);
}
.km-chal-pop__badge svg { width: 44px; height: 44px; fill: none; stroke: currentColor; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; }
.km-chal-pop .km-chal-pop__kicker {
  margin: 4px 0 0;
  font-size: 12px;
  font-weight: 800;
  line-height: 1.3;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--km-warn-text);
}
.km-chal-pop .km-chal-pop__title { margin: 0; font-family: var(--km-font-display); font-size: 24px; font-weight: 700; line-height: 1.2; color: var(--km-text); }
.km-chal-pop .km-chal-pop__text { margin: 0; font-size: 15px; line-height: 1.55; color: var(--km-text-secondary); }
.km-chal-pop .km-chal-pop__go { align-self: stretch; margin-top: 6px; }

/* «Закрыть» — `button`: у темы на нём радиус, рамка и тень в `:hover` и `:focus` — сняты во всех состояниях. */
.km-chal-pop .km-chal-pop__close,
.km-chal-pop .km-chal-pop__close:hover,
.km-chal-pop .km-chal-pop__close:focus,
.km-chal-pop .km-chal-pop__close:active {
  margin: 0;
  padding: 4px 8px;
  background: none;
  border: none;
  border-radius: 0;
  box-shadow: none;
  font: inherit;
  font-size: 14px;
  font-weight: 700;
  line-height: 1.4;
  color: var(--km-text-secondary);
  text-transform: none;
  letter-spacing: normal;
  cursor: pointer;
}
.km-chal-pop .km-chal-pop__close:hover { color: var(--km-text); }
.km-chal-pop .km-chal-pop__close:focus-visible { outline: 2px solid var(--km-accent); outline-offset: 2px; }

/* Вторая кнопка поздравления с медалью — «Посмотреть мои награды», ссылкой под главной. */
.km-stars-award .km-stars-award__more,
.km-stars-award .km-stars-award__more:hover,
.km-stars-award .km-stars-award__more:focus {
  font-size: 14px;
  font-weight: 700;
  line-height: 1.4;
  color: var(--km-text-secondary);
  text-decoration: none;
}
.km-stars-award .km-stars-award__more:hover { color: var(--km-text); text-decoration: underline; }

/* «Награды и бонусы» в колокольчике — знак на золотистом кружке (доска `chellendzh-kolokolchik`). */
.km-hdr .km-bell__face--reward,
.km-notes .km-bell__face--reward { background: var(--km-star-bg); color: var(--km-warn-text); }

/* Экран «Программы → Челленджи» — на стилях админки WordPress; своё — только раскладка таблицы этапов и медали. */
.km-chal-admin .km-chal-admin__list { margin-top: 12px; }
.km-chal-admin .km-chal-admin__form { max-width: 980px; }
.km-chal-admin .km-chal-admin__stages { max-width: 760px; }
.km-chal-admin .km-chal-admin__n { width: 28px; }
.km-chal-admin .km-chal-admin__days { width: 80px; }
/* «Тексты на странице ресурса» (Ресурсы 1.2, 6.4): поле, под пустым — что подставится. */
.km-chal-admin p.km-chal-admin__text { margin: 0 0 14px; }
.km-chal-admin p.km-chal-admin__text .description { display: block; margin-top: 4px; }
.km-chal-admin .km-chal-admin__x { width: 32px; text-align: center; }
.km-chal-admin .km-chal-admin__label { display: inline-block; margin-right: 6px; color: var(--km-text-secondary); white-space: nowrap; }
.km-chal-admin .km-chal-admin__medal-row { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.km-chal-admin .km-chal-admin__medal-box { flex: none; width: 52px; height: 52px; display: flex; align-items: center; justify-content: center; }
.km-chal-admin .km-chal-admin__medal { display: block; width: 52px; height: 52px; object-fit: contain; }
.km-chal-admin .km-chal-admin__counts p { display: flex; gap: 24px; margin: 0; }

@media (max-width: 560px) {
  .km-chal { padding: 18px 16px; }
  .km-chal .km-chal__medal--won { margin: 0 -16px -18px; padding: 14px 16px 18px; border-radius: 0 0 20px 20px; }
}

/* --- Плашка «+N» на «Отметить пройденным» -------------------------------- */
.km-stars-btn {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  margin-left: 6px;
  padding: 3px 8px 3px 7px;
  border-radius: 999px;
  font-size: 14px;
  background: var(--km-warm-bg);
  color: var(--km-warm-text-strong);
}

.km-btn--primary .km-stars-btn { background: rgba(255, 255, 255, 0.22); color: inherit; }
.km-stars-btn[hidden] { display: none; }

/* --- Окошки ---------------------------------------------------------------- */
.km-stars-toasts {
  position: fixed;
  left: 50%;
  bottom: calc(20px + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%);
  z-index: 100000;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  width: max-content;
  max-width: calc(100vw - 32px);
  pointer-events: none;
}

.km-stars-toast {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: 14px;
  background: var(--km-surface);
  color: var(--km-text);
  border: 1px solid var(--km-warm-border);
  border-radius: 16px;
  padding: 10px 18px 10px 10px;
  box-shadow: 0 10px 28px rgba(63, 76, 92, 0.18);
  font-size: 14px;
  line-height: 1.35;
  animation: km-stars-in 0.35s cubic-bezier(0.2, 0.9, 0.3, 1.3) both;
}

.km-stars-toast--out { animation: km-stars-out 0.3s ease both; }

.km-stars-toast__star {
  flex: none;
  position: relative;
  width: 60px;
  height: 60px;
  display: flex;
  align-items: center;
  justify-content: center;
  animation: km-stars-pop 0.6s 0.05s cubic-bezier(0.2, 0.9, 0.3, 1.5) both;
}

.km-stars-toast__art { position: absolute; inset: 0; width: 60px; height: 60px; filter: drop-shadow(0 3px 6px rgba(227, 154, 28, 0.35)); }

.km-stars-toast__plus {
  position: relative;
  z-index: 1;
  margin-top: 4px;
  font-family: var(--km-font-display);
  font-size: 17px;
  font-weight: 700;
  line-height: 1;
  color: #6B3F06;
}

.km-stars-toast__coin {
  flex: none;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--km-peach);
  color: var(--km-accent);
  font-size: 22px;
  font-weight: 700;
  animation: km-stars-pop 0.55s 0.1s cubic-bezier(0.2, 0.9, 0.3, 1.5) both;
}

.km-stars-toast__tx { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.km-stars-toast__tx b { font-size: 15px; font-weight: 700; }
.km-stars-toast__tx span { font-size: 12.5px; color: var(--km-text-secondary); }

@keyframes km-stars-in { from { opacity: 0; transform: translateY(16px) scale(0.96); } to { opacity: 1; transform: none; } }
@keyframes km-stars-out { to { opacity: 0; transform: translateY(10px); } }
@keyframes km-stars-pop { 0% { transform: scale(0.3) rotate(-25deg); } 100% { transform: scale(1) rotate(0); } }

@media (prefers-reduced-motion: reduce) {
  .km-stars-toast,
  .km-stars-toast--out,
  .km-stars-toast__star,
  .km-stars-toast__coin { animation: none; }
}

/* --- Полоса с отметками порогов бонусов (вкладка и карточка) ---------------
   Отметка — линия `<svg>` в координатах нормы: её `x` и есть порог. Высота
   отметок больше полосы, как в прототипе (14 против 8). */
.km-stars-track { position: relative; }
.km-stars-track .km-stars-bar { display: block; width: 100%; }
.km-stars-track__marks {
  position: absolute;
  left: 0;
  top: -3px;
  width: 100%;
  height: 14px;
  overflow: visible;
  pointer-events: none;
}
.km-stars-track__mark { stroke: #C9D3DE; stroke-width: 2px; }

/* Числа порогов под отметками и зелёная отметка пройденного порога — шкала «Все бонусы курса» (вид «В» прототипа
   `design/course/bonus-vid-v3.html`). Числа — `<text>` с `x` в процентах: координата — данные, не оформление. */
.km-stars-track__mark--got { stroke: var(--km-done); }
.km-stars-track__ticks { display: block; width: 100%; height: 18px; margin-top: 4px; overflow: visible; }
.km-stars-track__tick { font-size: 12px; fill: var(--km-text-secondary); }

/* --- Бонусы курса на вкладке «Награда» -------------------------------------- */
.km-stars-bons { display: flex; flex-direction: column; gap: 12px; }
.km-stars-bon { display: flex; align-items: flex-start; gap: 12px; }
.km-stars-bon__ic {
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--km-border-soft);
  color: var(--km-text-muted);
}
.km-stars-bon__ic--gift { background: var(--km-peach); color: var(--km-accent); }
.km-stars-bon__ic--open { background: var(--km-done-bg); color: var(--km-done); }
.km-stars-bon__txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.km-stars-bon__title { font-size: 15px; font-weight: 600; line-height: 1.35; color: var(--km-text); }
.km-stars-bon__sub { font-size: 13px; line-height: 1.45; color: var(--km-text-muted); }
.km-stars-bon__sub a { color: var(--km-accent); }

/* --- Карточка: ближайший бонус и «Награда ваша» ------------------------------ */
.km-stars-next { display: flex; align-items: flex-start; gap: 10px; margin: 0; font-size: 13px; line-height: 1.45; color: var(--km-text-secondary); }
.km-stars-next b { color: var(--km-text); font-weight: 600; }
.km-stars-won { display: inline-flex; align-items: center; gap: 8px; font-weight: 700; color: var(--km-done); }

/* --- Окошко бонуса: кнопка «Перейти к бонусу» ------------------------------- */
.km-stars-toast__go { margin-left: 6px; }

/* --- Поздравление с наградой ------------------------------------------------ */
.km-stars-award {
  position: fixed;
  inset: 0;
  z-index: 100001;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  overflow: auto;
  background: rgba(31, 27, 52, 0.62);
}
.km-stars-award[hidden] { display: none; }
.km-stars-award__confetti { position: fixed; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 1; }
.km-stars-award__dialog {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: 520px;
  overflow: hidden;
  text-align: center;
  background: var(--km-surface);
  border-radius: 24px;
  box-shadow: 0 30px 70px rgba(15, 12, 30, 0.45);
  animation: km-stars-in 0.45s cubic-bezier(0.2, 0.9, 0.3, 1.25) both;
}
.km-stars-award__top {
  position: relative;
  height: 230px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: radial-gradient(120% 100% at 50% 100%, var(--km-peach) 0%, var(--km-warm-bg) 45%, #FFF8F2 100%);
}
.km-stars-award__rays {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 520px;
  height: 520px;
  margin: -260px 0 0 -260px;
  border-radius: 50%;
  background: repeating-conic-gradient(from 0deg, rgba(244, 183, 64, 0.3) 0deg 9deg, rgba(244, 183, 64, 0) 9deg 24deg);
  -webkit-mask: radial-gradient(circle, #000 18%, transparent 62%);
  mask: radial-gradient(circle, #000 18%, transparent 62%);
  animation: km-stars-spin 22s linear infinite;
}
.km-stars-award__spark { position: absolute; z-index: 1; width: 14px; height: 14px; fill: #F4B740; animation: km-stars-twinkle 2.2s ease-in-out infinite; }
.km-stars-award__spark--1 { left: 18%; top: 22%; }
.km-stars-award__spark--2 { right: 20%; top: 30%; fill: var(--km-accent); animation-delay: 0.6s; }
.km-stars-award__spark--3 { left: 28%; bottom: 18%; width: 10px; height: 10px; fill: var(--km-accent); animation-delay: 1.1s; }
.km-stars-award__spark--4 { right: 27%; bottom: 20%; width: 11px; height: 11px; animation-delay: 1.6s; }
.km-stars-award__medal {
  position: relative;
  z-index: 1;
  width: 160px;
  height: 160px;
  object-fit: contain;
  filter: drop-shadow(0 10px 18px rgba(232, 112, 58, 0.35));
  animation: km-stars-pop 0.8s 0.15s cubic-bezier(0.2, 0.9, 0.3, 1.45) both;
}
.km-stars-award__x {
  position: absolute;
  right: 14px;
  top: 14px;
  z-index: 3;
  width: 36px;
  height: 36px;
  border-radius: var(--km-radius-control);
  border: 1px solid rgba(63, 76, 92, 0.15);
  background: rgba(255, 255, 255, 0.8);
  color: var(--km-text-secondary);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
}
.km-stars-award__body { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 22px 32px 28px; }
.km-stars-award__title {
  margin: 0;
  font-family: var(--km-font-display);
  font-size: 34px;
  font-weight: 700;
  line-height: 1.1;
  color: var(--km-text);
  text-wrap: balance;
}
.km-stars-award__lead { max-width: 400px; margin: 0; font-size: 16px; line-height: 1.6; color: var(--km-text-secondary); }
.km-stars-award__lead b { color: var(--km-text); }
.km-stars-award__wins { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; width: 100%; margin: 8px 0 6px; }
.km-stars-award__win {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 12px 8px;
  background: var(--km-warm-bg);
  border: 1px solid var(--km-warm-border);
  border-radius: 14px;
}
.km-stars-award__win b { font-family: var(--km-font-display); font-size: 26px; line-height: 1.1; color: var(--km-warm-text-strong); }
.km-stars-award__win span { font-size: 12.5px; line-height: 1.3; color: var(--km-warm-text); }

@keyframes km-stars-spin { to { transform: rotate(360deg); } }
@keyframes km-stars-twinkle { 0%, 100% { opacity: 0.2; transform: scale(0.6); } 50% { opacity: 1; transform: scale(1); } }

@media (max-width: 480px) {
  .km-stars-award__title { font-size: 28px; }
  .km-stars-award__body { padding: 20px 20px 24px; }
  .km-stars-award__win b { font-size: 22px; }
}

@media (prefers-reduced-motion: reduce) {
  .km-stars-award__dialog,
  .km-stars-award__rays,
  .km-stars-award__spark,
  .km-stars-award__medal { animation: none; }
}

/* ==========================================================================
   Приложение на телефоне (спецификация «Приложение на телефоне» 1.1; задание Алены 15.10.2026; макеты
   `design/app/prilozhenie-*-v2.dc.html`): нижнее меню, «назад» в приложении, плашка и окно «Как установить»,
   «Нет связи», карточка «Уведомления на телефон» в колокольчике.

   Нижнее меню — на телефоне везде, и в приложении, и в браузере; на компьютере его нет. Своего нижнего меню у темы
   BuddyBoss нет, прежнюю панель WPBar Алена убрала в черновики (15.10.2026): наше встаёт на пустое место, ничего
   чужого не прячет. Страница кончается над меню — отступом снизу у `body` (`km-has-appbar`), у iPhone с полоской
   «домой». Под открытой левой панелью темы (её слой — 999) меню уходит вниз: слой 998.

   Кнопки — с силой выше любой `button` темы (радиус 100px, синяя заливка при наведении), во всех состояниях:
   ничья по силе выигрывается порядком, а порядок меняет правка, которая о ней не знает (CLAUDE.md). */

:root {
  --km-app-on: #5E4270;
  --km-app-off: #8E8496;
  --km-app-line: #ECE7F0;
  --km-app-face: #E7D3E8;
  --km-app-text: #4A3E52;
  --km-app-hint: #F6F1F8;
  --km-app-grab: #DDD6E2;
  --km-app-share: #0A6CFF;
  --km-app-shade: rgba(46, 36, 51, 0.38);
  --km-app-page: #F5F3F7;
  /* Высота меню без полоски «домой»: 7 + значок 24 + 3 + подпись 14 + 7, и линия сверху. */
  --km-app-bar: 56px;
  --km-app-safe: env(safe-area-inset-bottom, 0px);
}

.km-appbar { display: none; }

@media (max-width: 767px) {
  .km-has-appbar.km-has-appbar { padding-bottom: calc(var(--km-app-bar) + var(--km-app-safe)); }

  /* Кнопка чата Carrot quest — закреплена внизу справа слоем выше нашего меню и ложилась на «Профиль» (снимок боевого
     15.10.2026). Чат не прячется и не правится — встаёт над меню. Сила — выше правил самого виджета (у них `!important`
     на `#id`): ничья по силе выигрывается порядком, а порядок меняет первая же правка (CLAUDE.md). */
  .km-has-appbar #carrotquest-messenger-collapsed-container.carrotquest-css-reset { bottom: calc(var(--km-app-bar) + var(--km-app-safe)) !important; }

  .km-appbar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 998;
    display: flex;
    min-height: var(--km-app-bar);
    padding: 7px 4px max(7px, var(--km-app-safe));
    background: #fff;
    border-top: 1px solid var(--km-app-line);
    font-family: var(--km-hub-font);
    box-sizing: border-box;
  }
}

.km-appbar .km-appbar__item.km-appbar__item,
.km-appbar .km-appbar__item.km-appbar__item:hover,
.km-appbar .km-appbar__item.km-appbar__item:focus,
.km-appbar .km-appbar__item.km-appbar__item:active,
.km-appbar .km-appbar__item.km-appbar__item:visited {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 0 2px;
  color: var(--km-app-off);
  font-size: 11px;
  font-weight: 600;
  line-height: 14px;
  text-decoration: none;
  background: none;
  border: 0;
  box-shadow: none;
}
.km-appbar .km-appbar__item.km-appbar__item:focus-visible { outline: 2px solid var(--km-app-on); outline-offset: -2px; border-radius: 8px; }
.km-appbar .km-appbar__item.km-appbar__item--on,
.km-appbar .km-appbar__item.km-appbar__item--on:hover,
.km-appbar .km-appbar__item.km-appbar__item--on:focus,
.km-appbar .km-appbar__item.km-appbar__item--on:visited { color: var(--km-app-on); font-weight: 800; }
.km-appbar .km-appbar__item svg { display: block; width: 24px; height: 24px; flex: none; color: inherit; stroke-width: 1.8; }
.km-appbar .km-appbar__item--on svg { stroke-width: 2; }
.km-appbar .km-appbar__label { display: block; max-width: 100%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.km-appbar .km-appbar__face { display: block; width: 24px; height: 24px; flex: none; border-radius: 50%; object-fit: cover; }
/* Фото нет — буквы имени на сиреневом кружке (макет: «АС»). */
.km-appbar .km-appbar__face--letters {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--km-app-face);
  color: var(--km-app-on);
  font-size: 9px;
  font-weight: 800;
  line-height: 1;
}
.km-appbar .km-appbar__item--on .km-appbar__face { box-shadow: 0 0 0 2px #fff, 0 0 0 3.5px var(--km-app-on); }

/* Полоска загрузки — тонкая сливовая сверху, пока после нажатия на пункт нижнего меню не откроется новая страница
   (задание Алены 15.10.2026 «ускорить переходы», шаг 1; ставит `app.js`). Бежит быстро в начале и замедляется
   к концу, до конца не доходит: когда придёт страница, неизвестно, — её приход и есть конец. Выше панели
   администратора (слой 99999), в приложении — под вырезом экрана. Кто просил меньше движения — полоска стоит.
   Переходом, а не `@keyframes`: так сделано, пока встраиваемая таблица (`design-system-embed.css`, она стоит и на
   страницах с нижним меню) их теряла; с 16.10.2026 она несёт `@keyframes` целиком (`DesignSystemEmbedTest`). */
.km-app-progress {
  position: fixed;
  top: env(safe-area-inset-top, 0px);
  left: 0;
  right: 0;
  z-index: 100000;
  height: 3px;
  overflow: hidden;
  pointer-events: none;
}
.km-app-progress::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 100%;
  background: var(--km-app-on);
  transform: scaleX(0);
  transform-origin: left center;
}
.km-app-progress.km-app-progress--run::before { transform: scaleX(0.92); transition: transform 8s cubic-bezier(0.1, 0.7, 0.2, 1); }
@media (prefers-reduced-motion: reduce) {
  .km-app-progress.km-app-progress--run::before { transform: scaleX(0.6); transition: none; }
}

/* ПОЛЯ СТРАНИЦ НИЖНЕГО МЕНЮ НА ТЕЛЕФОНЕ — 16 по бокам и 16 сверху под шапкой (правки Алены 15.10.2026 после проверки
   на iPhone; макет `design/app/prilozhenie-glavnaya-v2`: карточки на всю ширину между полями). Только телефон; тема не
   правится — наши правила поверх. Сила — выше правил Elementor у его блоков (0,3,0), а не порядком.
   - «Мои курсы» стоят в контейнере Elementor с полями 40 по бокам и 60 сверху: его отступы снимаются, поля — у нашего
     корня (на компьютере корень по-прежнему без своих полей и вровень с меню — решение 15 сентября 2026).
   - «Расписание» — страница Elementor с нашими классами у блоков (`km-schedule-page`, `km-schedule-shell`): отступы —
     её же переменными Elementor.
   - «Библиотека»: справа на телефоне остаётся место под вкладку «Заметили ошибку?» (решение 4 октября 2026: вкладка
     не закрывает сердечки и «Поделиться»); нет вкладки — 16.
   - «Сообщество» и «Мой профиль» — `.km-page.km-hub` ниже по файлу: 16 сверху. */
@media (max-width: 767px) {
  .km-has-appbar .e-con.e-con:has(.km-page.km-dashboard--page),
  .km-has-appbar .e-con-inner.e-con-inner:has(.km-page.km-dashboard--page) { --padding-top: 0px; --padding-right: 0px; --padding-bottom: 0px; --padding-left: 0px; padding: 0; }
  .km-has-appbar .km-page.km-hub.km-dashboard--page { padding: 16px 16px 40px; }
  .km-has-appbar .km-schedule-page.km-schedule-page.e-con { --padding-left: 16px; --padding-right: 16px; }
  .km-has-appbar .km-schedule-shell.km-schedule-shell.e-con { --padding-top: 16px; }
  .km-has-appbar .km-page.km-cast { padding-top: 16px; padding-left: 16px; }
  .km-has-appbar:not(:has(.km-defect__tab)) .km-page.km-cast { padding-right: 16px; }
}

/* «Назад» вместо значка меню темы — только в установленном приложении и не на страницах нижнего меню (раздел 3):
   ставит и убирает `app.js`, значок темы прячется своим классом только на эти страницы. */
.km-appback__theme.km-appback__theme { display: none !important; }
.km-appback.km-appback,
.km-appback.km-appback:hover,
.km-appback.km-appback:focus,
.km-appback.km-appback:active {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  margin: 0;
  padding: 0;
  flex: none;
  color: var(--km-hub-ink);
  background: none;
  border: 0;
  border-radius: 50%;
  box-shadow: none;
  cursor: pointer;
}
.km-appback.km-appback:focus-visible { outline: 2px solid var(--km-app-on); outline-offset: 2px; }
.km-appback svg { display: block; width: 22px; height: 22px; }

/* Плашка «Центр обучения на экране «Домой»» — над нижним меню (макеты `prilozhenie-iphone-podskazka-v2`,
   `prilozhenie-android-ustanovit-v2`). Только телефон: на компьютере её нет и с разметкой. */
.km-install[hidden] { display: none; }
.km-install {
  position: fixed;
  left: 10px;
  right: 10px;
  bottom: calc(var(--km-app-bar) + var(--km-app-safe) + 20px);
  z-index: 998;
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 14px;
  background: #fff;
  border: 1px solid var(--km-hub-line);
  border-radius: 16px;
  box-shadow: 0 12px 32px rgba(59, 42, 71, 0.22);
  font-family: var(--km-hub-font);
  color: var(--km-hub-ink);
  box-sizing: border-box;
}
@media (min-width: 768px) {
  .km-install.km-install { display: none; }
}
.km-install .km-install__icon { display: block; width: 46px; height: 46px; flex: none; border-radius: 12px; }
.km-install .km-install__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.km-install .km-install__title { font-size: 15px; font-weight: 700; line-height: 1.3; }
.km-install .km-install__text { font-size: 13px; line-height: 1.45; color: var(--km-app-text); }
/* Спрятанная кнопка — сильнее правила показа (0,4,0 против 0,3,0), а не порядком: где страница грузит обе таблицы
   (полную и урезанную), показ из второй перебивал `[hidden]` первой — на «Расписании» стояли обе кнопки (боевой 15.10). */
.km-install .km-install__go.km-install__go[hidden] { display: none; }
.km-install .km-install__go.km-install__go,
.km-install .km-install__go.km-install__go:hover,
.km-install .km-install__go.km-install__go:focus,
.km-install .km-install__go.km-install__go:active {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 38px;
  margin: 8px 0 0;
  padding: 0 16px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  color: #fff;
  background: var(--km-hub-red);
  border: 0;
  border-radius: 10px;
  box-shadow: none;
  cursor: pointer;
}
.km-install .km-install__go.km-install__go:hover { background: var(--km-hub-red-hover); }
.km-install .km-install__close.km-install__close,
.km-install .km-install__close.km-install__close:hover,
.km-install .km-install__close.km-install__close:focus,
.km-install .km-install__close.km-install__close:active {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  margin: -8px -8px 0 0;
  padding: 0;
  flex: none;
  color: var(--km-app-off);
  background: none;
  border: 0;
  border-radius: 50%;
  box-shadow: none;
  cursor: pointer;
}
.km-install .km-install__close svg { display: block; width: 20px; height: 20px; }

/* Окно «Как установить на iPhone» — снизу экрана (макет `prilozhenie-iphone-kak-ustanovit-v2`). */
.km-howto[hidden] { display: none; }
.km-howto { position: fixed; inset: 0; z-index: 100000; font-family: var(--km-hub-font); color: var(--km-hub-ink); }
.km-howto .km-howto__shade { position: absolute; inset: 0; background: var(--km-app-shade); }
.km-howto .km-howto__sheet {
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 100%;
  max-width: 520px;
  max-height: 100%;
  overflow-y: auto;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 8px 20px calc(40px + var(--km-app-safe));
  background: #fff;
  border-radius: 20px 20px 0 0;
  box-sizing: border-box;
}
.km-howto .km-howto__grab { display: block; width: 40px; height: 4px; flex: none; align-self: center; border-radius: 2px; background: var(--km-app-grab); }
.km-howto .km-howto__head { display: flex; gap: 12px; align-items: center; margin-top: 4px; }
.km-howto .km-howto__icon { display: block; width: 52px; height: 52px; flex: none; border-radius: 13px; }
.km-howto .km-howto__title { margin: 0; font-family: var(--km-hub-display); font-size: 24px; font-weight: 500; line-height: 1.15; color: var(--km-hub-title); }
/* Шаги — одни на окно «Как установить» и на страницу /app (`.km-appinst`). Номер — только круглый: тема ставит браузерный
   номер самим `li` (было «1. 1Нажмите…», снимок Алены 15.10.2026), поэтому список снимается и у `li`. */
.km-howto .km-howto__steps,
.km-appinst .km-howto__steps { display: flex; flex-direction: column; gap: 14px; margin: 0; padding: 0; list-style: none; }
.km-howto .km-howto__step,
.km-appinst .km-howto__step { display: flex; gap: 12px; align-items: flex-start; margin: 0; padding: 0; list-style: none; }
.km-howto .km-howto__step::marker,
.km-appinst .km-howto__step::marker { content: none; }
.km-howto .km-howto__num,
.km-appinst .km-howto__num {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  flex: none;
  border-radius: 50%;
  background: var(--km-hub-soft);
  color: var(--km-app-on);
  font-size: 14px;
  font-weight: 800;
  line-height: 1;
}
.km-howto .km-howto__say,
.km-appinst .km-howto__say { padding-top: 2px; font-size: 15px; line-height: 1.5; }
.km-howto .km-howto__glyph,
.km-appinst .km-howto__glyph { display: inline-block; width: 18px; height: 18px; vertical-align: -3px; color: var(--km-hub-ink); }
.km-howto .km-howto__glyph--share,
.km-appinst .km-howto__glyph--share { color: var(--km-app-share); }
.km-howto .km-howto__hint { margin: 0; padding: 12px 14px; font-size: 14px; line-height: 1.55; color: var(--km-app-text); background: var(--km-app-hint); border-radius: 12px; }
.km-howto .km-howto__ok.km-howto__ok,
.km-howto .km-howto__ok.km-howto__ok:hover,
.km-howto .km-howto__ok.km-howto__ok:focus,
.km-howto .km-howto__ok.km-howto__ok:active {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 44px;
  margin: 2px 0 0;
  padding: 0 20px;
  font-family: inherit;
  font-size: 15px;
  font-weight: 700;
  line-height: 1;
  color: #fff;
  background: var(--km-hub-red);
  border: 0;
  border-radius: 10px;
  box-shadow: none;
  cursor: pointer;
}
.km-howto .km-howto__ok.km-howto__ok:hover { background: var(--km-hub-red-hover); }

/* «Нет связи» (макет `prilozhenie-net-svyazi-v2`) — своя страница целиком, без темы: её отдаёт service worker. */
.km-offline-body { margin: 0; min-height: 100vh; background: var(--km-app-page); font-family: var(--km-hub-font); color: var(--km-hub-ink); -webkit-text-size-adjust: 100%; }
.km-offline-body *,
.km-offline-body *::before,
.km-offline-body *::after { box-sizing: border-box; }
.km-offline__bar { display: flex; align-items: center; height: 56px; padding: 0 14px; background: #fff; border-bottom: 1px solid var(--km-hub-line-soft); }
.km-offline__logo { display: block; width: 32px; height: 32px; border-radius: 8px; }
.km-offline {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  min-height: calc(100vh - 56px - var(--km-app-bar) - var(--km-app-safe));
  padding: 24px 36px 64px;
  text-align: center;
}
.km-offline .km-offline__icon { display: flex; align-items: center; justify-content: center; width: 76px; height: 76px; border-radius: 50%; background: var(--km-hub-soft); color: var(--km-app-on); }
.km-offline .km-offline__icon svg { display: block; width: 34px; height: 34px; }
.km-offline .km-offline__title { margin: 0; font-family: var(--km-hub-display); font-size: 26px; font-weight: 500; line-height: 1.15; color: var(--km-hub-title); }
.km-offline .km-offline__text { max-width: 320px; margin: 0; font-size: 15px; line-height: 1.55; color: var(--km-app-text); }
.km-offline .km-offline__retry.km-offline__retry,
.km-offline .km-offline__retry.km-offline__retry:hover,
.km-offline .km-offline__retry.km-offline__retry:focus,
.km-offline .km-offline__retry.km-offline__retry:active {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 44px;
  margin: 4px 0 0;
  padding: 0 28px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 700;
  color: var(--km-hub-ink);
  background: #fff;
  border: 1px solid var(--km-hub-chip-line);
  border-radius: 10px;
  box-shadow: none;
  cursor: pointer;
}
.km-offline .km-offline__retry.km-offline__retry:hover { background: var(--km-hub-hover); }

/* Карточки «Уведомления на телефон» и «Уведомления на iPhone» над списком колокольчика (макеты
   `prilozhenie-kolokolchik-vklyuchit-v2`, `prilozhenie-kolokolchik-iphone-v2`). */
.km-hdr .km-pushcard[hidden] { display: none; }
.km-hdr .km-pushcard { display: flex; gap: 12px; align-items: flex-start; margin: 12px 16px; padding: 14px; background: var(--km-app-hint); border-radius: 14px; }
.km-hdr .km-pushcard__icon { display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; flex: none; border-radius: 50%; background: #fff; color: var(--km-app-on); }
.km-hdr .km-pushcard__icon svg { display: block; width: 20px; height: 20px; }
.km-hdr .km-pushcard__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.km-hdr .km-pushcard__title { font-size: 15px; font-weight: 700; line-height: 1.3; color: var(--km-hub-ink); }
.km-hdr .km-pushcard__text { font-size: 14px; line-height: 1.5; color: var(--km-app-text); }
.km-hdr .km-pushcard__note[hidden] { display: none; }
.km-hdr .km-pushcard__note { font-size: 13px; line-height: 1.45; color: var(--km-danger); }
.km-hdr .km-pushcard__acts { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; margin-top: 6px; }
.km-hdr .km-pushcard__go.km-pushcard__go,
.km-hdr .km-pushcard__go.km-pushcard__go:hover,
.km-hdr .km-pushcard__go.km-pushcard__go:focus,
.km-hdr .km-pushcard__go.km-pushcard__go:active {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 40px;
  margin: 0;
  padding: 0 18px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  color: #fff;
  background: var(--km-hub-red);
  border: 0;
  border-radius: 10px;
  box-shadow: none;
  cursor: pointer;
}
.km-hdr .km-pushcard__go.km-pushcard__go:hover { background: var(--km-hub-red-hover); }
.km-hdr .km-pushcard__go.km-pushcard__go:disabled { opacity: 0.6; cursor: default; }
.km-hdr .km-pushcard__later.km-pushcard__later,
.km-hdr .km-pushcard__later.km-pushcard__later:hover,
.km-hdr .km-pushcard__later.km-pushcard__later:focus,
.km-hdr .km-pushcard__later.km-pushcard__later:active {
  display: inline-flex;
  align-items: center;
  height: 40px;
  margin: 0;
  padding: 0;
  font-family: inherit;
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  color: var(--km-hub-muted);
  background: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  cursor: pointer;
}
.km-hdr .km-pushcard__later.km-pushcard__later:hover { color: var(--km-hub-ink); }

/* Открыто со значка (`app.js` ставит `km-is-app` на `<html>`): плашки «установить» в приложении нет (раздел 4). */
.km-is-app .km-install.km-install { display: none; }

/* «Ключи LMS → Приложение на телефоне»: значок приложения — как на экране телефона, скруглённым квадратом. */
.km-app-admin__icon { display: block; width: 56px; height: 56px; flex: none; border-radius: 13px; }

/* Страница установки `/treningi/app` (спецификация «Приложение на телефоне» 1.3, раздел 4; макеты
   `design/app/prilozhenie-app-*-v2`). Вид — по месту, где открыли (`data-lms-appinst`): iPhone, Android, внутри
   приложения, компьютер; «Приложение уже установлено» открывает `app.js`. Шаги — те же классы, что у окна
   «Как установить» (`km-howto__…`): один вид на оба места. */
.km-appinst {
  display: flex;
  flex-direction: column;
  gap: 18px;
  max-width: 520px;
  margin: 0 auto;
  padding: 22px 18px 40px;
  font-family: var(--km-hub-font);
  color: var(--km-hub-ink);
  box-sizing: border-box;
}
.km-appinst[data-lms-appinst="desktop"] { max-width: 760px; padding: 56px 20px; }
.km-appinst .km-appinst__head { display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 4px 6px 0; text-align: center; }
.km-appinst .km-appinst__icon { display: block; width: 84px; height: 84px; flex: none; border-radius: 20px; }
.km-appinst .km-appinst__icon--small { width: 64px; height: 64px; border-radius: 15px; }
.km-appinst .km-appinst__title { margin: 0; font-family: var(--km-hub-display); font-size: 26px; font-weight: 500; line-height: 1.15; color: var(--km-hub-title); }
.km-appinst .km-appinst__title--desk { font-size: 30px; }
.km-appinst .km-appinst__lead { margin: 0; font-size: 15px; line-height: 1.55; color: var(--km-app-text); }
.km-appinst .km-appinst__body[hidden] { display: none; }
.km-appinst .km-appinst__body { display: flex; flex-direction: column; gap: 16px; }
.km-appinst .km-appinst__card { display: flex; flex-direction: column; gap: 14px; padding: 18px 16px; background: #fff; border: 1px solid var(--km-hub-line); border-radius: 16px; }
.km-appinst .km-appinst__card--soft { gap: 10px; background: #FBF8FC; border-color: #E2D3E8; }
.km-appinst .km-appinst__card--done { align-items: stretch; text-align: center; }
.km-appinst .km-appinst__card-title { margin: 0; font-family: var(--km-hub-display); font-size: 20px; font-weight: 500; line-height: 1.2; color: var(--km-hub-title); }
.km-appinst .km-appinst__card-lead { font-size: 17px; font-weight: 700; line-height: 1.3; }
.km-appinst .km-appinst__text { margin: 0; font-size: 15px; line-height: 1.55; color: var(--km-app-text); }
.km-appinst .km-appinst__out { display: flex; align-items: center; justify-content: center; width: 42px; height: 42px; border-radius: 50%; background: var(--km-hub-soft); color: var(--km-app-on); }
.km-appinst .km-appinst__out svg { display: block; width: 21px; height: 21px; }
.km-appinst .km-appinst__hint { margin: 0; padding: 12px 14px; font-size: 14px; line-height: 1.55; color: var(--km-app-text); background: var(--km-app-hint); border-radius: 12px; }
.km-appinst .km-appinst__small { margin: 0; font-size: 13px; line-height: 1.5; color: var(--km-hub-muted); }
.km-appinst .km-appinst__small--center { text-align: center; }
.km-appinst .km-appinst__copied[hidden] { display: none; }
.km-appinst .km-appinst__copied { margin: 0; font-size: 13px; line-height: 1.5; color: var(--km-ok); overflow-wrap: anywhere; }
.km-appinst .km-appinst__go.km-appinst__go[hidden] { display: none; }
.km-appinst .km-appinst__go.km-appinst__go,
.km-appinst .km-appinst__go.km-appinst__go:hover,
.km-appinst .km-appinst__go.km-appinst__go:focus,
.km-appinst .km-appinst__go.km-appinst__go:active,
.km-appinst .km-appinst__go.km-appinst__go:visited {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 50px;
  margin: 4px 0 0;
  padding: 0 20px;
  font-family: inherit;
  font-size: 16px;
  font-weight: 700;
  line-height: 1;
  color: #fff;
  text-decoration: none;
  background: var(--km-hub-red);
  border: 0;
  border-radius: 10px;
  box-shadow: none;
  cursor: pointer;
  box-sizing: border-box;
}
.km-appinst .km-appinst__go.km-appinst__go:hover { background: var(--km-hub-red-hover); }
.km-appinst .km-appinst__copy.km-appinst__copy,
.km-appinst .km-appinst__copy.km-appinst__copy:hover,
.km-appinst .km-appinst__copy.km-appinst__copy:focus,
.km-appinst .km-appinst__copy.km-appinst__copy:active {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 44px;
  margin: 4px 0 0;
  padding: 0 18px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  color: var(--km-hub-ink);
  background: #fff;
  border: 1px solid var(--km-hub-chip-line);
  border-radius: 10px;
  box-shadow: none;
  cursor: pointer;
}
.km-appinst .km-appinst__copy.km-appinst__copy:hover { background: var(--km-hub-hover); }
.km-appinst .km-appinst__desk { display: flex; flex-wrap: wrap; gap: 36px; align-items: center; padding: 34px 36px; background: #fff; border: 1px solid var(--km-hub-line); border-radius: 16px; }
.km-appinst .km-appinst__desk-text { flex: 1 1 280px; min-width: 0; display: flex; flex-direction: column; gap: 14px; }
.km-appinst .km-appinst__desk .km-appinst__lead { line-height: 1.6; }
.km-appinst .km-appinst__addr { margin: 0; font-size: 14px; line-height: 1.5; color: var(--km-hub-muted); }
.km-appinst .km-appinst__addr-url { color: var(--km-app-on); overflow-wrap: anywhere; }
.km-appinst .km-appinst__qr { flex: none; padding: 12px; line-height: 0; background: #fff; border: 1px solid var(--km-hub-line); border-radius: 16px; }
.km-appinst .km-appinst__qr-code { display: block; width: 165px; height: 165px; }

/* ---------------------------------------------------------------------------
   РАЗДЕЛ «РЕСУРСЫ» — «Ресурсы» 1.0, прототип `design/resursy-prototip-v4.html`.
   Каталог /treningi/resursy/ и страница ресурса стоят в обвязке страницы трансляции библиотеки (`.km-cast`):
   шрифты прототипа (KM Manrope, KM Oswald), палитра, карточки, крошки, шапка и значки — её. Здесь — своё
   раздела: шапка каталога, поиск, вкладки, карточки ресурсов, «С чего начать», панели страницы, замок.
   Числа — прототипа. Под курсором ничего не двигается: наведение меняет цвет и тень, не положение.
   Состояния ссылок и кнопок — силой селектора под `.km-cast`, не порядком: тема перекрашивает `a` и `button`.
   --------------------------------------------------------------------------- */

.km-res { --km-res-line: #e9e1ed; --km-res-line2: #f0eaf2; --km-res-line3: #e4d5e9; --km-res-muted: #83708c; --km-res-muted2: #948197; --km-res-muted3: #aa91b1; --km-res-label: #947ba0; --km-res-kicker: #b17d91; --km-res-ink: #333044; --km-res-plum: #795985; --km-res-plum-ink: #53405b; --km-res-link: #9a647f; --km-res-chip-bg: #efe7f5; --km-res-chip: #88639c; --km-res-gold: #9a6b1f; --km-res-gold-bg: #fbf1de; --km-res-step: #efeaf2; --km-res-step-ink: #766c7e; --km-res-red: #d54844; --km-res-red-hover: #bd3e3a; --km-res-focus: #c9b4d6; --km-res-sec-line: #dfd0e7; --km-res-sec-ink: #856595; }
.km-page.km-cast.km-res { padding-top: 38px; padding-bottom: 60px; }
.km-res .km-res-ico { width: 18px; height: 18px; flex: none; }

/* ── Шапка каталога ── */
.km-res .km-res-cat__head { display: flex; align-items: flex-end; justify-content: space-between; flex-wrap: wrap; gap: 20px 32px; }
.km-res .km-res-cat__titles { flex: 1 1 420px; min-width: 0; }
.km-res .km-res-kicker { margin: 0; font-size: 11px; font-weight: 750; line-height: 1.6; letter-spacing: 1.5px; color: var(--km-res-kicker); }
.km-cast h1.km-res-cat__title { margin: 4px 0; padding: 0 !important; font-family: var(--km-cast-display); font-size: 48px; font-weight: 500; line-height: 1.28; text-transform: uppercase; color: var(--km-res-ink); text-wrap: balance; }
.km-res .km-res-cat__sub { margin: 0; font-size: 16px; line-height: 1.75; color: var(--km-res-muted2); }
.km-res .km-res-search { display: flex; align-items: center; gap: 11px; width: min(360px, 100%); padding: 11px 15px; border: 1px solid var(--km-res-line3); border-radius: 9px; background: transparent; color: #9777a0; }
.km-res .km-res-search .km-res-ico { width: 16px; height: 16px; }
.km-res input.km-res-search__input,
.km-res input.km-res-search__input:focus { flex: 1; min-width: 0; height: auto; margin: 0; padding: 0; border: 0; border-radius: 0; outline: 0; background: transparent; box-shadow: none; font-family: var(--km-cast-font); font-size: 14px; line-height: 1.5; color: var(--km-res-plum-ink); }
.km-res input.km-res-search__input::placeholder { color: #aba1b1; }

/* ── Вкладки ── */
.km-res .km-res-tabs { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 28px; }
.km-cast button.km-res-tab,
.km-cast button.km-res-tab:focus,
.km-cast button.km-res-tab:active { display: inline-flex; align-items: center; gap: 8px; min-height: 0; padding: 11px 15px; border: 0; border-radius: 9px; background: transparent; box-shadow: none; font-family: var(--km-cast-font); font-size: 14px; font-weight: 650; line-height: 1.6; color: #8a738f; white-space: nowrap; }
.km-cast button.km-res-tab:hover { background: #eee5f2; color: var(--km-res-plum); }
.km-cast button.km-res-tab[aria-selected="true"],
.km-cast button.km-res-tab[aria-selected="true"]:hover,
.km-cast button.km-res-tab[aria-selected="true"]:focus { background: var(--km-res-red); color: #fff; }
.km-res .km-res-tab .km-res-ico { width: 15px; height: 15px; color: #9b80a5; }
.km-res .km-res-tab[aria-selected="true"] .km-res-ico { color: #fff; }
.km-res .km-res-cat__row { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; margin: 24px 0 16px; }
.km-res .km-res-cat__hint { font-size: 14px; font-weight: 400; line-height: 1.5; color: #85718d; }
.km-res .km-res-cat__order { font-size: 13px; color: var(--km-res-muted3); white-space: nowrap; }

/* ── Карточки ── */
.km-res .km-res-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; }
.km-res .km-res-grid[hidden],
.km-res .km-res-card[hidden],
.km-res .km-res-empty[hidden] { display: none; }
.km-cast a.km-res-card,
.km-cast a.km-res-card:visited,
.km-cast a.km-res-card:focus,
.km-cast a.km-res-card:active { display: flex; flex-direction: column; min-width: 0; padding: 0; overflow: hidden; border: 1px solid var(--km-res-line); border-radius: 15px; background: #fff; box-shadow: 0 5px 18px rgba(80, 50, 88, .04); color: inherit; text-align: left; text-decoration: none; }
.km-cast a.km-res-card:hover { background: #fff; box-shadow: 0 10px 26px rgba(80, 50, 88, .09); color: inherit; text-decoration: none; }
.km-res .km-res-card__cover { position: relative; display: flex; align-items: center; justify-content: center; width: 100%; aspect-ratio: 16 / 9; overflow: hidden; background: #f3eef5; }
.km-res .km-res-card__cover--art { background: linear-gradient(150deg, #f7f2f9, #d6c6df); }
.km-res .km-res-card__img { display: block; width: 100%; height: 100%; }
.km-res .km-res-card__cover--fill .km-res-card__img { object-fit: cover; }
.km-res .km-res-card__cover--whole .km-res-card__img { object-fit: contain; }
.km-res .km-res-card__sign { display: flex; align-items: center; justify-content: center; width: 76px; height: 76px; border-radius: 50%; background: rgba(255, 255, 255, .72); color: var(--km-res-plum); }
.km-res .km-res-card__sign .km-res-ico { width: 34px; height: 34px; stroke-width: 1.5; }
.km-res .km-res-card__new { position: absolute; top: 12px; left: 12px; padding: 4px 9px; border-radius: 6px; background: #fffffff0; font-size: 12px; font-weight: 600; line-height: 1.5; color: var(--km-res-plum); }
.km-res .km-res-card__body { flex: 1; display: flex; flex-direction: column; gap: 10px; padding: 20px 23px 22px; }
.km-res .km-res-card__kind { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; font-size: 12px; font-weight: 600; line-height: 1.5; color: var(--km-res-label); }
.km-res .km-res-mark { display: inline-flex; align-items: center; gap: 4px; padding: 1px 7px; border-radius: 5px; background: var(--km-res-chip-bg); font-size: 11px; font-weight: 700; line-height: 1.6; color: var(--km-res-chip); }
.km-res .km-res-mark--challenge { background: var(--km-res-gold-bg); color: var(--km-res-gold); }
.km-res .km-res-mark .km-res-ico { width: 12px; height: 12px; }
.km-res .km-res-card__title { font-family: var(--km-cast-display); font-size: 26px; font-weight: 400; line-height: 1.3; color: var(--km-res-plum-ink); }
.km-res .km-res-card__desc { flex: 1; font-size: 16px; line-height: 1.65; color: var(--km-res-muted); }
.km-res .km-res-card__btn { display: flex; align-items: center; gap: 6px; margin-top: 9px; padding-top: 13px; border-top: 1px solid var(--km-res-line2); font-size: 14px; font-weight: 600; line-height: 1.5; color: var(--km-res-link); }
.km-res .km-res-card__btn .km-res-ico { width: 15px; height: 15px; }

.km-res .km-res-empty { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 40px 24px; border: 1px dashed var(--km-res-line3); border-radius: 15px; text-align: center; color: var(--km-res-muted); }
.km-res .km-res-empty__title { font-family: var(--km-cast-display); font-size: 22px; font-weight: 500; line-height: 1.3; color: var(--km-res-plum-ink); }
.km-cast button.km-res-empty__reset,
.km-cast button.km-res-empty__reset:hover,
.km-cast button.km-res-empty__reset:focus { margin-top: 12px; padding: 0; border: 0; background: none; box-shadow: none; font-family: var(--km-cast-font); font-size: 14px; font-weight: 700; color: var(--km-res-link); }

/* ── «С чего начать» и «Ещё в «Ключах Мастерства»» ── */
.km-res .km-res-start { margin-top: 56px; }
.km-cast h2.km-res-start__title { margin: 4px 0 18px; font-family: var(--km-cast-display); font-size: 32px; font-weight: 500; line-height: 1.25; color: var(--km-res-ink); }
.km-res .km-res-start__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; }
.km-cast button.km-res-tile,
.km-cast button.km-res-tile:focus,
.km-cast button.km-res-tile:active { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; min-width: 0; padding: 22px 23px; border: 1px solid var(--km-res-line); border-radius: 15px; background: #fff; box-shadow: none; font-family: var(--km-cast-font); text-align: left; color: inherit; }
.km-cast button.km-res-tile:hover { border-color: #dccde3; background: #fff; color: inherit; }
.km-res .km-res-tile__sign { display: flex; align-items: center; justify-content: center; width: 42px; height: 42px; border-radius: 50%; background: var(--km-res-step); color: var(--km-res-plum); }
.km-res .km-res-tile__title { font-family: var(--km-cast-display); font-size: 22px; font-weight: 400; line-height: 1.3; color: var(--km-res-plum-ink); }
.km-res .km-res-tile__text { font-size: 15px; line-height: 1.6; color: var(--km-res-muted); }
.km-res .km-res-more { display: flex; flex-direction: column; margin-top: 48px; }
.km-res .km-res-more__links { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 4px; }
.km-cast a.km-res-more__link,
.km-cast a.km-res-more__link:visited,
.km-cast a.km-res-more__link:hover,
.km-cast a.km-res-more__link:focus,
.km-cast a.km-res-more__link:active { display: inline-flex; align-items: center; gap: 8px; padding: 11px 16px; border: 1px solid var(--km-res-line3); border-radius: 9px; background: #fff; font-size: 14px; font-weight: 650; line-height: 1.5; color: var(--km-res-plum); text-decoration: none; }
.km-cast a.km-res-more__link:hover { border-color: #dccde3; }

/* ── Страница ресурса ── */
.km-page.km-cast.km-res.km-res-page { padding-top: 30px; padding-bottom: 64px; }
.km-res .km-res-badges { display: flex; flex-wrap: wrap; gap: 6px; }
.km-cast .km-cast-badge.km-res-badge--challenge { background: var(--km-res-gold-bg); color: var(--km-res-gold); }
.km-res .km-res-lay { display: grid; grid-template-columns: minmax(0, 1fr) 330px; column-gap: 23px; row-gap: 20px; align-items: start; }
.km-res .km-res-lay--solo { grid-template-columns: minmax(0, 805px); }
.km-res .km-res-col { display: flex; flex-direction: column; gap: 20px; min-width: 0; }
.km-res .km-res-pane { min-width: 0; padding: 26px 28px; border: 1px solid #e7dfeb; border-radius: 15px; background: #fff; box-shadow: 0 5px 20px rgba(68, 37, 80, .025); }
.km-res .km-res-prose { font-size: 16px; line-height: 1.65; color: var(--km-cast-body); }
.km-res .km-res-prose > * { margin-top: 0; margin-bottom: 12px; }
.km-res .km-res-prose > :last-child { margin-bottom: 0; }
.km-res .km-res-prose p { margin: 0 0 12px; }
.km-res .km-res-prose p:last-child { margin-bottom: 0; }
.km-res .km-res-prose ul,
.km-res .km-res-prose ol { margin: 0 0 12px; padding-left: 20px; }
.km-res .km-res-prose li { margin: 2px 0; }
.km-res .km-res-prose strong,
.km-res .km-res-prose b { color: var(--km-cast-ink); }
.km-cast .km-res-prose h2,
.km-cast .km-res-prose h3,
.km-cast .km-res-prose h4 { margin: 0 0 6px; font-family: var(--km-cast-display); font-weight: 500; line-height: 1.3; letter-spacing: normal; text-transform: none; color: var(--km-cast-ink); }
.km-cast .km-res-prose h2 { font-size: 24px; }
.km-cast .km-res-prose h3 { font-size: 20px; }
.km-cast .km-res-prose h4 { font-size: 18px; }
.km-cast .km-res-prose * + h2,
.km-cast .km-res-prose * + h3,
.km-cast .km-res-prose * + h4 { margin-top: 18px; }
.km-res .km-res-prose img { max-width: 100%; height: auto; }
.km-res .km-res-video iframe { display: block; width: 100%; max-width: 100%; border: 0; border-radius: 12px; }
/* Подпись под видео — текст после плеера (прототип: `.video-cap`). */
.km-res .km-res-video p { margin: 10px 0 0; font-size: 14px; line-height: 1.6; color: var(--km-res-muted); }
.km-res .km-res-side .km-chal { margin: 0; }
.km-res .km-res-side .km-res-pane { display: flex; flex-direction: column; gap: 12px; }

/* Замок: гость и «нет доступа» (правила 3 и 4). */
.km-res .km-res-lock { display: flex; align-items: flex-start; gap: 16px; }
.km-res .km-res-lock__sign { flex: none; display: flex; align-items: center; justify-content: center; width: 48px; height: 48px; border-radius: 50%; background: var(--km-res-step); color: var(--km-res-step-ink); }
.km-res .km-res-lock__body { display: flex; flex-direction: column; align-items: flex-start; gap: 16px; min-width: 0; padding-top: 6px; }
.km-res .km-res-lock__title { display: block; font-family: var(--km-cast-display); font-size: 22px; font-weight: 500; line-height: 1.3; color: var(--km-cast-ink); }
.km-cast a.km-res-btn,
.km-cast a.km-res-btn:visited,
.km-cast a.km-res-btn:focus,
.km-cast a.km-res-btn:active { display: inline-flex; align-items: center; justify-content: center; gap: 9px; min-height: 44px; padding: 11px 17px; border: 0; border-radius: 8px; background: var(--km-res-red); box-shadow: 0 3px 7px rgba(213, 72, 68, .1); font-size: 14px; font-weight: 700; line-height: 1.5; color: #fff; text-decoration: none; }
.km-cast a.km-res-btn:hover { background: var(--km-res-red-hover); color: #fff; }
.km-cast a.km-res-quiet,
.km-cast a.km-res-quiet:visited,
.km-cast a.km-res-quiet:hover,
.km-cast a.km-res-quiet:focus,
.km-cast a.km-res-quiet:active { padding: 0; font-size: 14px; font-weight: 700; line-height: 1.5; color: var(--km-res-link); text-decoration: none; }

/* «К записи за сегодня →» — кнопка прокрутки к форме на этой же странице (6.2), видом ссылки этапа. */
.km-chal button.km-chal__link--scroll,
.km-chal button.km-chal__link--scroll:hover,
.km-chal button.km-chal__link--scroll:focus { min-height: 0; padding: 0; border: 0; border-radius: 0; background: none; box-shadow: none; font-family: inherit; cursor: pointer; }

.km-res .km-res-others { margin-top: 44px; }
.km-cast h2.km-res-others__title { margin: 0 0 18px; font-family: var(--km-cast-display); font-size: 28px; font-weight: 500; line-height: 1.25; color: var(--km-cast-ink); }

@media (max-width: 1100px) {
  .km-res .km-res-grid,
  .km-res .km-res-start__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 860px) {
  .km-res .km-res-lay { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 700px) {
  .km-page.km-cast.km-res { padding-top: 24px; padding-bottom: 44px; }
  .km-cast h1.km-res-cat__title { font-size: 34px; }
  .km-res .km-res-search { width: 100%; }
  /* Телефон: вкладки прокручиваются вбок внутри полосы, страница вбок не едет (раздел 3). */
  .km-res .km-res-tabs { flex-wrap: nowrap; gap: 8px; overflow-x: auto; margin-right: -16px; padding-right: 16px; scrollbar-width: none; }
  .km-res .km-res-tabs::-webkit-scrollbar { display: none; }
  .km-res .km-res-grid,
  .km-res .km-res-start__grid { grid-template-columns: minmax(0, 1fr); }
  .km-res .km-res-pane { padding: 22px 20px; }
  .km-cast h2.km-res-start__title { font-size: 28px; }
}

/* ── Админка: список ресурсов, переключатель раздела ── */
.km-res-admin .km-res-admin__switch { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; margin: 14px 0 6px; padding: 12px 16px; border: 1px solid #c3c4c7; background: #fff; }
.km-res-admin .km-res-admin__switch-label { font-weight: 600; }
.km-res-admin .km-res-admin__choice { display: inline-flex; align-items: center; gap: 6px; }
.km-res-admin .km-res-admin__switch-hint { flex-basis: 100%; color: #646970; }
.km-res-admin .km-res-admin__name { display: flex; align-items: flex-start; gap: 10px; }
.km-res-admin .km-res-admin__thumb { flex: none; display: flex; align-items: center; justify-content: center; width: 64px; aspect-ratio: 16 / 9; overflow: hidden; border-radius: 4px; background: linear-gradient(150deg, #f7f2f9, #d6c6df); }
.km-res-admin .km-res-admin__img { display: block; width: 100%; height: 100%; }
.km-res-admin .km-res-admin__thumb--fill .km-res-admin__img { object-fit: cover; }
.km-res-admin .km-res-admin__thumb--whole { background: #f3eef5; }
.km-res-admin .km-res-admin__thumb--whole .km-res-admin__img { object-fit: contain; }
.km-res-admin .km-res-admin__dim { color: #646970; }
.km-res-admin .km-res-admin__acts { position: static; left: auto; }

/* ── Редактор ресурса: панели справа ── */
.km-sp .km-res-radio { display: grid; gap: 6px; margin: 0 0 10px; }
.km-sp .km-res-radio__item { display: flex; align-items: center; gap: 8px; font-size: 13px; }
.km-sp .km-res-cover { display: flex; align-items: center; justify-content: center; width: 100%; aspect-ratio: 16 / 9; margin: 6px 0; overflow: hidden; border-radius: 6px; background: linear-gradient(150deg, #f7f2f9, #d6c6df); }
.km-sp .km-res-cover__img { display: block; width: 100%; height: 100%; }
.km-sp .km-res-cover--fill .km-res-cover__img { object-fit: cover; }
.km-sp .km-res-cover--whole { background: #f3eef5; }
.km-sp .km-res-cover--whole .km-res-cover__img { object-fit: contain; }
.km-sp .km-res-cover__replace { margin: 0 0 6px; padding: 0; border: 0; background: none; cursor: pointer; }
.km-sp .km-res-access { display: grid; gap: 4px; }
.km-sp .km-res-chpnl { display: grid; gap: 4px; margin: 0 0 8px; }
.km-sp .km-res-chpnl__title { font-size: 14px; }
.km-sp .km-res-chpnl__mode { font-size: 12.5px; color: var(--km-text-secondary); }
.km-sp .km-res-chpnl__mode--on { color: var(--km-done); }
.km-sp .km-res-old { margin: 4px 0 8px; padding: 0; list-style: none; }
.km-sp .km-res-old__item { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: 0 0 4px; }
.km-sp .km-res-old__path { overflow-wrap: anywhere; font-family: var(--km-mono); font-size: 12px; }
.km-sp .km-res-old__drop { flex: none; width: 24px; height: 24px; padding: 0; border: 1px solid var(--km-border); border-radius: var(--km-radius-badge); background: var(--km-surface); line-height: 1; color: var(--km-text-secondary); cursor: pointer; }
.km-sp .km-res-old__add { display: grid; gap: 6px; margin: 0 0 8px; }

/* «Где проходит» на экране челленджа — курс или ресурс («Челленджи» 1.3, раздел 2; «Ресурсы» 1.0, 6.1). */
.km-chal-admin .km-chal-admin__where { display: grid; gap: 8px; margin: 0; padding: 0; border: 0; }
.km-chal-admin .km-chal-admin__where-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.km-chal-admin .km-chal-admin__where-row span { min-width: 56px; }
/* Невыбранное место приглушено, как в прототипе (`.inp.off`): выбор решает переключатель слева. */
.km-chal-admin .km-chal-admin__where[data-lms-chal-where="resource"] [data-lms-chal-course],
.km-chal-admin .km-chal-admin__where[data-lms-chal-where="course"] [data-lms-chal-resource] { opacity: .5; }
.km-chal-admin [data-lms-chal-for][hidden] { display: none; }
.km-res .km-res-cat__titles .km-editlinks { margin: 12px 0 0; }
.km-res-admin .km-res-admin__list td { vertical-align: top; }
.km-res .km-res-head .km-editlinks { margin: 12px 0 0; }
/* Форма и список — чужая разметка (Gravity Forms, GravityView): широкая таблица прокручивается внутри своей панели,
   страница вбок не едет (раздел 4, «Телефон»). Якорь формы — ниже липкой шапки темы. */
.km-res .km-res-form { scroll-margin-top: 90px; overflow-x: auto; }
.km-res .km-res-list { overflow-x: auto; }

/*
 * Формы Gravity на странице ресурса — как форма прототипа (`.fld`, `.opt`, `.btn`, `.sub`; слово Алены 21.10.2026:
 * «оформляешь как в прототипе — только стилями на страницах ресурсов»). Формы и их поля не меняются; формы
 * в занятиях курсов этих правил не видят — всё под `.km-res .km-res-form`.
 *
 * `!important` — только против `!important` сниппетов сайта «Gravity View/Gravity form - CSS» и «Объединённый CSS»
 * (кнопки и отступы низа формы, подписи полей и вариантов, отмеченный вариант, полоса шагов; прочитано на копии
 * боевого 21.10.2026). Сила — выше их
 * (у них до (0,3,1)), а не порядок подключения.
 */
.km-res .km-res-form > p { margin: 0 0 18px; font-size: 15px; line-height: 1.6; color: var(--km-res-muted); }
.km-res .km-res-form .gform_wrapper.gravity-theme { margin: 0; }
.km-res .km-res-form .gform_wrapper.gravity-theme .gform_fields { row-gap: 18px; }
.km-res .km-res-form .gform_wrapper.gravity-theme .gfield_label,
.km-res .km-res-form .gform_wrapper.gravity-theme legend.gfield_label { margin: 0 0 8px; padding: 0; font-family: var(--km-cast-font) !important; font-size: 15px !important; font-weight: 700 !important; line-height: 1.45; color: var(--km-res-ink); }
.km-res .km-res-form .gform_wrapper.gravity-theme .gfield_required { color: var(--km-res-red); }
.km-res .km-res-form .gform_wrapper.gravity-theme .gfield_description,
.km-res .km-res-form .gform_wrapper.gravity-theme .gform-field-label--type-sub,
.km-res .km-res-form .gform_wrapper.gravity-theme .ginput_complex label { padding-top: 6px; font-family: var(--km-cast-font) !important; font-size: 13px !important; font-weight: 400 !important; line-height: 1.5; color: var(--km-res-muted); }
.km-res .km-res-form .gform_wrapper.gravity-theme input:not([type="radio"]):not([type="checkbox"]):not([type="submit"]):not([type="button"]):not([type="hidden"]):not([type="file"]):not([type="image"]),
.km-res .km-res-form .gform_wrapper.gravity-theme textarea,
.km-res .km-res-form .gform_wrapper.gravity-theme select { width: 100%; height: auto; min-height: 0; padding: 11px 14px; border: 1px solid var(--km-res-line3); border-radius: 9px; background: #fff; box-shadow: none; font-family: var(--km-cast-font); font-size: 15px; font-weight: 400; line-height: 1.55; color: var(--km-res-plum-ink); }
/* Высота — прототипа (72 px), а не «большого» поля Gravity в десять строк; где браузер умеет, поле растёт по тексту. */
.km-res .km-res-form .gform_wrapper.gravity-theme .gfield textarea { height: 72px; min-height: 72px; resize: vertical; }
@supports (field-sizing: content) {
  .km-res .km-res-form .gform_wrapper.gravity-theme .gfield textarea { height: auto; max-height: 420px; field-sizing: content; }
}
.km-res .km-res-form .gform_wrapper.gravity-theme input:not([type="radio"]):not([type="checkbox"]):focus,
.km-res .km-res-form .gform_wrapper.gravity-theme textarea:focus,
.km-res .km-res-form .gform_wrapper.gravity-theme select:focus { outline: 2px solid var(--km-res-focus); outline-offset: 0; border-color: var(--km-res-focus); }

/* Варианты ответа — «таблетки» с родным кружком или квадратиком (прототип `.opt`); свои кружки темы сняты. */
.km-res .km-res-form .gform_wrapper.gravity-theme .gfield_radio,
.km-res .km-res-form .gform_wrapper.gravity-theme .gfield_checkbox { display: flex; flex-wrap: wrap; gap: 8px; }
.km-res .km-res-form .gform_wrapper.gravity-theme .gchoice { display: inline-flex; align-items: center; gap: 8px; max-width: 100%; margin: 0; padding: 8px 13px; border: 1px solid var(--km-res-line3); border-radius: 9px; background: #fff; }
/* Список не в строку (у формы нет `gf_list_inline`: длинные пункты «Похвастушек») — столбцом, во всю ширину (прототип `.opts.col1`). */
.km-res .km-res-form .gform_wrapper.gravity-theme .gfield:not(.gf_list_inline) .gfield_radio,
.km-res .km-res-form .gform_wrapper.gravity-theme .gfield:not(.gf_list_inline) .gfield_checkbox { flex-direction: column; align-items: stretch; }
.km-res .km-res-form .gform_wrapper.gravity-theme .gfield:not(.gf_list_inline) .ginput_container .gchoice label { font-weight: 500 !important; }
.km-res .km-res-form .gform_wrapper.gravity-theme .gchoice input[type="radio"],
.km-res .km-res-form .gform_wrapper.gravity-theme .gchoice input[type="checkbox"] { position: static; flex: none; width: 16px; height: 16px; margin: 0; opacity: 1; appearance: auto; accent-color: var(--km-res-red); cursor: pointer; }
.km-res .km-res-form .gform_wrapper.gravity-theme .ginput_container .gchoice label { position: static; min-height: 0; margin: 0; padding: 0; font-family: var(--km-cast-font) !important; font-size: 14px !important; font-weight: 600 !important; line-height: 1.4; color: var(--km-res-plum-ink); cursor: pointer; }
/* Отмеченный вариант подложкой не красится — как в прототипе; у сниппета сайта правило (0,7,1) с `!important`. */
.km-res .km-res-form .gform_wrapper.gravity-theme .gfield .ginput_container .gchoice:has(input:checked) { border-color: var(--km-res-line3) !important; background-color: #fff !important; }
.km-res .km-res-form .gform_wrapper.gravity-theme .gchoice label::before,
.km-res .km-res-form .gform_wrapper.gravity-theme .gchoice label::after { content: none; display: none; }

/* Раздел формы — надписью над вопросами (прототип `.eyebrow`). */
.km-res .km-res-form .gform_wrapper.gravity-theme .gsection { margin: 6px 0 0; padding: 0; border: 0; }
.km-res .km-res-form .gform_wrapper.gravity-theme .gsection_title { margin: 0; padding: 0; font-family: var(--km-cast-font); font-size: 11px; font-weight: 800; line-height: 1.65; letter-spacing: 1.8px; text-transform: uppercase; color: var(--km-res-kicker); }
.km-res .km-res-form .gform_wrapper.gravity-theme .gsection_description { padding-top: 4px; font-size: 14px; color: var(--km-res-muted); }

/*
 * Многостраничная форма — «Шаг N из M» и полоса с процентом, как на образце «Нарциссические матери» («Ресурсы» 1.1,
 * раздел 4). Вид полосы — общий для форм сайта: его задаёт сниппет сайта «Прогресс-бар Gravity Forms» (сиреневая
 * полоса и надпись, `!important`), и образец показывает ровно его. Своё здесь — только высота строки надписи (на
 * образце 27, у нас её сжимала проза ресурса); прототип v4 прятал полосу, и его правило снято.
 */
.km-res .km-res-form .gform_wrapper.gravity-theme .gf_progressbar_title { line-height: 27px; }

/* Кнопки внизу формы и её страниц (прототип `.btn`; «Назад» — `.btn.sec`). Кнопки внутри полей («Добавить») не трогаются. */
.km-res .km-res-form .gform_wrapper.gravity-theme .gform_footer,
.km-res .km-res-form .gform_wrapper.gravity-theme .gform_page_footer { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 6px 0 0; padding: 0 !important; }
.km-res .km-res-form .gform_wrapper.gravity-theme .gform_footer .gform_button,
.km-res .km-res-form .gform_wrapper.gravity-theme .gform_page_footer .gform_button,
.km-res .km-res-form .gform_wrapper.gravity-theme .gform_page_footer .gform_next_button { min-height: 44px; margin: 0; padding: 11px 17px !important; border: 0; border-radius: 8px !important; background: var(--km-res-red) !important; box-shadow: 0 3px 7px rgba(213, 72, 68, .1); font-family: var(--km-cast-font); font-size: 14px !important; font-weight: 700 !important; line-height: 1.5; color: #fff !important; cursor: pointer; }
.km-res .km-res-form .gform_wrapper.gravity-theme .gform_footer .gform_button:hover,
.km-res .km-res-form .gform_wrapper.gravity-theme .gform_page_footer .gform_button:hover,
.km-res .km-res-form .gform_wrapper.gravity-theme .gform_page_footer .gform_next_button:hover { background: var(--km-res-red-hover) !important; }
.km-res .km-res-form .gform_wrapper.gravity-theme .gform_page_footer .gform_previous_button { min-height: 44px; margin: 0; padding: 11px 17px !important; border: 1px solid var(--km-res-sec-line) !important; border-radius: 8px !important; background: #fff !important; box-shadow: none; font-family: var(--km-cast-font); font-size: 14px !important; font-weight: 700 !important; line-height: 1.5; color: var(--km-res-sec-ink) !important; cursor: pointer; }
.km-res .km-res-form .gform_wrapper.gravity-theme .gform_footer .gform_button:focus-visible,
.km-res .km-res-form .gform_wrapper.gravity-theme .gform_page_footer .gform_next_button:focus-visible,
.km-res .km-res-form .gform_wrapper.gravity-theme .gform_page_footer .gform_previous_button:focus-visible { outline: 2px solid var(--km-res-focus); outline-offset: 2px; }
.km-res .km-res-aside img { max-width: 100%; height: auto; border-radius: 6px; }
/* «Справа» как «Из книги» прототипа: обложка 120 px, текст 15 px приглушённый, надпись вплотную к первому блоку. */
.km-res .km-res-aside .wp-block-image img { width: 120px; }
.km-res .km-res-aside .wp-block-image { margin: 0; }
.km-cast .km-res-aside.km-res-prose > * + h2 { margin-top: 0; }
.km-res .km-res-aside p:not(.km-cast-eyebrow) { font-size: 15px; line-height: 1.6; color: var(--km-res-muted); }
.km-cast .km-res-prose .km-cast-eyebrow + * { margin-top: 0; }

/* ── Страница ресурса — прототип v6 и образцы Алены («Ресурсы» 1.2, раздел 4) ──────────────────────────────────
 *
 * Прототип — `design/resursy-prototip-v6.html` (вариант 6, «Трекер благодарности»), числа и цвета — из него
 * буквально; где прототипа нет (опросник, строка под описанием, карточки «Справа»), — образцы Алены, как в 1.550.0.
 * Кнопки — красные. Ширина — 1180 с полями 40, колонки 1fr и 340 через 28; до 1000 — одна колонка, до 700 —
 * телефон: поля 16, обложка маленькая над надписью, над формой — полоса челленджа.
 *
 * Пространство — `km-rp-`: у прототипа v4 было своё (`km-res-…`), им по-прежнему живут каталог и карточки.
 */
.km-rp {
  --km-rp-card: #ffffff;
  --km-rp-line: #e6dfea;
  --km-rp-line2: #efe9f2;
  --km-rp-ink: #2e2a3f;
  --km-rp-ink2: #3a3550;
  --km-rp-text: #5b5268;
  --km-rp-muted: #7d7187;
  --km-rp-muted2: #a196a9;
  --km-rp-kicker: #9b7086;
  --km-rp-red: #d5483f;
  --km-rp-red-h: #bb3b33;
  --km-rp-orange: #e3702c;
  --km-rp-chip: #f1ebf4;
  --km-rp-chip-ink: #76657f;
  --km-rp-tab: #6e5f7a;
  --km-rp-tab-hover: #eee7f2;
  --km-rp-ch-bg: #f7eff6;
  --km-rp-ch-line: #eadce8;
  --km-rp-ch-ink: #6e5f78;
  --km-rp-ch-title: #3b2a47;
  --km-rp-ch-dot: #ede1ef;
  --km-rp-ch-dot-ink: #94839e;
  --km-rp-track: #e9dceb;
  --km-rp-ok: #3e7a4f;
  --km-rp-ok-bg: #e3f0e6;
  --km-rp-lilac: #f3eaf6;
  --km-rp-out: #c9c0ce;
  --km-rp-edit: #8a93a2;
  --km-rp-edit-a: #6f7a8c;
  --km-rp-pick: #f3edfa;
  --km-rp-pick-line: #cdbde6;
  --km-rp-hover-line: #d6c7df;
  --km-rp-sec-hover: #f6f1f8;
  /* Образцы Алены — то, чего в прототипе нет: карточки «Справа» и строка под описанием. */
  --km-rp-soft: #f0e8f3;
  --km-rp-plum: #58425f;
  --km-rp-heart: #9982a4;
  --km-rp-sub: #7b6684;
  --km-rp-shadow: 0 4px 20px rgba(80, 50, 88, 0.024);
}

body:has(.km-page.km-cast.km-rp) { background-color: #f4f1f5; }

.km-page.km-cast.km-res.km-rp {
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 40px;
  font-size: 16px;
  line-height: 1.65;
  color: var(--km-rp-text);
}

/* Крошки «Центр обучения / Ресурсы / {название}» */
.km-rp .km-rp-crumbs { display: flex; flex-wrap: wrap; gap: 6px 10px; margin: 0; padding: 34px 0 0; font-size: 15px; line-height: 1.5; color: var(--km-rp-muted); }
.km-rp a.km-rp-crumbs__link,
.km-rp a.km-rp-crumbs__link:visited { color: var(--km-rp-muted); text-decoration: none; }
.km-rp a.km-rp-crumbs__link:hover,
.km-rp a.km-rp-crumbs__link:focus-visible { color: var(--km-rp-ink2); text-decoration: none; }
.km-rp .km-rp-crumbs__sep { color: var(--km-rp-muted2); }
.km-rp .km-rp-crumbs__here { color: var(--km-rp-muted); }

/* Шапка: текст слева, обложка 190 справа, линия снизу */
.km-rp .km-rp-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 20px 48px; align-items: start; padding: 40px 0 34px; border-bottom: 1px solid var(--km-rp-line); }
.km-rp .km-rp-head--bare { grid-template-columns: minmax(0, 1fr); }
/* Обычным потоком, а не гибкой колонкой: промежутки у строк шапки разные, и каждый — полем одной стороны. */
.km-rp .km-rp-head__text { min-width: 0; }
.km-rp .km-rp-eyebrow { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0; font-size: 13px; font-weight: 600; line-height: 1.5; letter-spacing: 1.6px; text-transform: uppercase; color: var(--km-rp-kicker); }
.km-rp .km-rp-draft { padding: 0 8px; border-radius: 5px; background: var(--km-rp-chip); font-size: 11px; letter-spacing: 0.6px; color: var(--km-rp-chip-ink); }
/* Сниппет сайта даёт любому `h1` на телефоне `padding-top: 30px !important`; у прототипа его нет. */
.km-rp h1.km-rp-title { margin: 10px 0 14px; padding: 0 !important; font-family: var(--km-cast-display); font-size: 58px; font-weight: 500; line-height: 1.08; letter-spacing: normal; text-transform: uppercase; color: var(--km-rp-ink); text-wrap: balance; }
.km-rp .km-rp-lead { max-width: 62ch; margin: 0; font-size: 17px; line-height: 1.7; color: var(--km-rp-text); }
.km-rp .km-rp-subline { display: flex; align-items: flex-start; gap: 10px; margin: 14px 0 0; font-size: 14px; line-height: 1.6; color: var(--km-rp-sub); }
.km-rp .km-rp-subline .km-res-ico { flex: none; width: 18px; height: 18px; margin-top: 2px; }
.km-rp .km-rp-head__text .km-editlinks { margin: 14px 0 0; }
.km-rp .km-rp-cover { display: block; width: 190px; height: 190px; margin-top: 6px; border-radius: 12px; box-shadow: 0 8px 24px rgba(60, 40, 70, 0.12); object-fit: cover; }
.km-rp .km-rp-cover--whole { object-fit: contain; background: #fff; }

/* Раскладка по прототипу v7: основная колонка и правая 340 через 28. Вкладки — первой строкой над левой колонкой,
   карточка вкладки и правая колонка — второй, верх у них общий («Ресурсы» 1.3). Без вкладок правая колонка встаёт
   в первую строку сама. */
.km-rp .km-rp-lay { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: 0 28px; align-items: start; padding: 26px 0 0; }
.km-rp .km-rp-lay--solo { grid-template-columns: minmax(0, 1fr); }
.km-rp .km-rp-main { grid-column: 1; min-width: 0; }
.km-rp .km-rp-panel { min-width: 0; }
/* Спрятанная вкладка — классом, а не атрибутом `hidden`: смену класса видит Gravity Forms и запускает форму, когда
   её вкладку показали (`assets/js/resources.js`, `tabs()`). */
.km-rp .km-rp-panel--off { display: none; }
.km-rp .km-rp-side { grid-column: 2; display: flex; flex-direction: column; gap: 18px; min-width: 0; }
.km-rp .km-rp-tabs ~ .km-rp-side { grid-row: 2; }

/* Вкладки: выбранная — красная плашка со значком; линии под вкладками нет, до карточки 10 + 14 = 24 (прототип v7) */
.km-rp .km-rp-tabs { grid-column: 1; display: flex; flex-wrap: nowrap; gap: 6px; margin: 0 0 14px; padding: 0 0 10px; overflow-x: auto; scrollbar-width: none; }
.km-rp .km-rp-tabs::-webkit-scrollbar { display: none; }
.km-rp a.km-rp-tab,
.km-rp a.km-rp-tab:visited {
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: 9px;
  padding: 12px 18px;
  border-radius: 8px;
  background: transparent;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--km-rp-tab);
  text-decoration: none;
  white-space: nowrap;
}
.km-rp a.km-rp-tab:hover,
.km-rp a.km-rp-tab:focus-visible { background: var(--km-rp-tab-hover); color: var(--km-rp-ink2); text-decoration: none; }
.km-rp a.km-rp-tab[aria-selected="true"],
.km-rp a.km-rp-tab[aria-selected="true"]:hover,
.km-rp a.km-rp-tab[aria-selected="true"]:focus-visible { background: var(--km-rp-red); box-shadow: 0 4px 10px rgba(213, 72, 63, 0.18); color: #fff; }
.km-rp a.km-rp-tab .km-res-ico { width: 17px; height: 17px; }

/* Карточка вкладки */
.km-rp .km-rp-card { min-width: 0; padding: 32px 34px 34px; border: 1px solid var(--km-rp-line); border-radius: 14px; background: var(--km-rp-card); }
.km-rp h2.km-rp-card__title { margin: 0; font-family: var(--km-cast-display); font-size: 32px; font-weight: 500; line-height: 1.2; letter-spacing: normal; text-transform: none; color: var(--km-rp-ink2); text-wrap: balance; }

/* Вкладка 1 — форма в карточке */
.km-rp .km-rp-form { scroll-margin-top: calc(var(--km-chrome-top, 0px) + 16px); }
.km-rp .km-rp-form__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px 20px; margin: 0 0 8px; }
.km-rp .km-rp-form__titles { min-width: 0; }
.km-rp p.km-rp-form__label { margin: 0 0 8px; font-size: 12px; font-weight: 600; line-height: 1.5; letter-spacing: 1.4px; text-transform: uppercase; color: var(--km-rp-kicker); }
.km-rp h2.km-rp-form__title { margin: 0; font-family: var(--km-cast-display); font-size: 32px; font-weight: 500; line-height: 1.2; letter-spacing: normal; text-transform: none; color: var(--km-rp-ink2); text-wrap: balance; }
.km-rp .km-rp-pill { display: inline-flex; flex: none; align-items: center; gap: 8px; margin-top: 6px; padding: 7px 12px; border-radius: 7px; background: var(--km-rp-chip); font-size: 13px; font-weight: 500; line-height: 1.3; color: var(--km-rp-chip-ink); white-space: nowrap; }
.km-rp .km-rp-pill .km-res-ico { width: 15px; height: 15px; }
/* Плашка опросника («Анкета») — та же, что дата трекера, без значка. */
.km-rp .km-rp-pill--badge { gap: 0; }
.km-rp p.km-rp-form__sub { margin: 0 0 28px; font-size: 16px; line-height: 1.65; color: var(--km-rp-muted); }
/* «Подзаголовок», набранный полем с панелью писем сценариев («Ресурсы» 1.4): абзацы, жирный, курсив, списки, ссылки. */
.km-rp div.km-rp-form__sub--rich { margin: 0 0 28px; font-size: 16px; line-height: 1.65; color: var(--km-rp-muted); }
.km-rp .km-rp-form__sub--rich > * { margin: 0; }
.km-rp .km-rp-form__sub--rich > * + * { margin-top: 10px; }
.km-rp .km-rp-form__sub--rich h3 { font-family: var(--km-cast-display); font-size: 20px; font-weight: 500; line-height: 1.3; letter-spacing: normal; text-transform: none; color: var(--km-rp-ink2); }
.km-rp .km-rp-form__sub--rich ul,
.km-rp .km-rp-form__sub--rich ol { padding-left: 22px; }
.km-rp .km-rp-form__sub--rich li + li { margin-top: 4px; }
.km-rp .km-rp-form__sub--rich strong,
.km-rp .km-rp-form__sub--rich b { font-weight: 700; color: var(--km-rp-ink2); }
.km-rp .km-rp-form__sub--rich a,
.km-rp .km-rp-form__sub--rich a:visited { color: var(--km-rp-orange); text-decoration: none; }
.km-rp .km-rp-form__sub--rich a:hover { text-decoration: underline; }
.km-rp .km-rp-form__head + .km-rp-form__body { margin-top: 20px; }
/* Тренажёр: во вкладке 1 его экран как есть; заголовок над ним — название ресурса. */
.km-rp .km-rp-form__body--trainer { margin-top: 20px; }

/* Форма — по прототипу v6: вопросы Oswald 20, варианты-«таблетки», поля, красная кнопка. */
.km-rp .km-res-form .gform_wrapper.gravity-theme .gform_fields { row-gap: 28px; }
.km-rp .km-res-form .gform_wrapper.gravity-theme .gfield_label,
.km-rp .km-res-form .gform_wrapper.gravity-theme legend.gfield_label { margin: 0 0 14px; font-family: var(--km-cast-display) !important; font-size: 20px !important; font-weight: 500 !important; line-height: 1.35 !important; color: var(--km-rp-ink2) !important; }
.km-rp .km-res-form .gform_wrapper.gravity-theme .gfield_radio,
.km-rp .km-res-form .gform_wrapper.gravity-theme .gfield_checkbox,
.km-rp .km-res-form .gform_wrapper.gravity-theme .gfield:not(.gf_list_inline) .gfield_radio,
.km-rp .km-res-form .gform_wrapper.gravity-theme .gfield:not(.gf_list_inline) .gfield_checkbox { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 10px; }
.km-rp .km-res-form .gform_wrapper.gravity-theme .gchoice { gap: 10px; padding: 11px 16px; border: 1px solid var(--km-rp-line); border-radius: 8px; background: #fff; }
.km-rp .km-res-form .gform_wrapper.gravity-theme .gchoice:hover { border-color: var(--km-rp-hover-line); }
.km-rp .km-res-form .gform_wrapper.gravity-theme .gfield .ginput_container .gchoice:has(input:checked) { border-color: var(--km-rp-pick-line) !important; background-color: var(--km-rp-pick) !important; }
.km-rp .km-res-form .gform_wrapper.gravity-theme .gchoice input[type="radio"],
.km-rp .km-res-form .gform_wrapper.gravity-theme .gchoice input[type="checkbox"] { width: 17px; height: 17px; accent-color: var(--km-rp-orange); }
.km-rp .km-res-form .gform_wrapper.gravity-theme .ginput_container .gchoice label { font-size: 15px !important; font-weight: 500 !important; line-height: 1.3 !important; color: var(--km-rp-ink2) !important; }
.km-rp .km-res-form .gform_wrapper.gravity-theme textarea { min-height: 120px; padding: 14px 16px; border: 1px solid var(--km-rp-line); border-radius: 8px; font-size: 16px; line-height: 1.6; color: var(--km-rp-ink2); }
.km-rp .km-res-form .gform_wrapper.gravity-theme .gfield textarea { height: 120px; min-height: 120px; }
.km-rp .km-res-form .gform_wrapper.gravity-theme textarea:focus { outline: 2px solid var(--km-rp-pick-line); outline-offset: 0; border-color: var(--km-rp-pick-line); }
.km-rp .km-res-form .gform_wrapper.gravity-theme .gform_footer .gform_button,
.km-rp .km-res-form .gform_wrapper.gravity-theme .gform_page_footer .gform_button,
.km-rp .km-res-form .gform_wrapper.gravity-theme .gform_page_footer .gform_next_button { min-height: 46px; padding: 12px 24px !important; border-radius: 8px !important; background: var(--km-rp-red) !important; box-shadow: 0 4px 10px rgba(213, 72, 63, 0.16); font-size: 15px !important; font-weight: 700 !important; line-height: 1.4 !important; color: #fff !important; }
.km-rp .km-res-form .gform_wrapper.gravity-theme .gform_footer .gform_button:hover,
.km-rp .km-res-form .gform_wrapper.gravity-theme .gform_page_footer .gform_button:hover,
.km-rp .km-res-form .gform_wrapper.gravity-theme .gform_page_footer .gform_next_button:hover { background: var(--km-rp-red-h) !important; }

/* Полоса челленджа над формой — только на телефоне («Ресурсы» 1.2, 6.3) */
.km-rp .km-rp-strip { display: none; flex-direction: column; margin: 0 0 14px; padding: 14px 16px; border: 1px solid var(--km-rp-ch-line); border-radius: 12px; background: var(--km-rp-ch-bg); }
.km-rp .km-rp-strip__kicker { display: block; font-size: 11px; font-weight: 700; line-height: 1.4; letter-spacing: 1.2px; text-transform: uppercase; color: var(--km-rp-kicker); }
.km-rp .km-rp-strip__head { display: block; margin-top: 2px; font-size: 14px; font-weight: 700; line-height: 1.4; color: var(--km-rp-ink2); }
.km-rp .km-rp-strip .km-rp-progress { margin-top: 8px; }
.km-rp .km-rp-strip__text { display: block; margin-top: 6px; font-size: 12.5px; line-height: 1.45; color: var(--km-rp-ch-ink); }
.km-rp progress.km-rp-progress { display: block; width: 100%; height: 8px; border: 0; border-radius: 4px; background: var(--km-rp-track); overflow: hidden; appearance: none; color: var(--km-rp-orange); }
.km-rp progress.km-rp-progress::-webkit-progress-bar { border-radius: 4px; background: var(--km-rp-track); }
.km-rp progress.km-rp-progress::-webkit-progress-value { border-radius: 4px; background: var(--km-rp-orange); }
.km-rp progress.km-rp-progress::-moz-progress-bar { border-radius: 4px; background: var(--km-rp-orange); }

/* Вход и замок во вкладке 1. Верх замка = верх прописных букв первой строки: Oswald 24/1.3 — тексту −7 px. */
.km-rp .km-rp-gate { display: flex; align-items: flex-start; gap: 18px; }
.km-rp .km-rp-gate__sign { display: flex; flex: none; align-items: center; justify-content: center; width: 50px; height: 50px; border-radius: 50%; background: var(--km-rp-chip); color: var(--km-rp-chip-ink); }
.km-rp .km-rp-gate__sign .km-res-ico { width: 20px; height: 20px; }
.km-rp .km-rp-gate__text { display: flex; flex-direction: column; align-items: flex-start; gap: 16px; min-width: 0; margin-top: -7px; }
.km-rp .km-rp-gate__title { font-family: var(--km-cast-display); font-size: 24px; font-weight: 500; line-height: 1.3; color: var(--km-rp-ink2); }
.km-rp a.km-rp-btn,
.km-rp a.km-rp-btn:visited,
.km-rp button.km-rp-btn,
.km-rp button.km-rp-btn:focus,
.km-rp button.km-rp-btn:active {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  min-height: 46px;
  margin: 0;
  padding: 12px 24px;
  border: 0;
  border-radius: 8px;
  background: var(--km-rp-red);
  box-shadow: 0 4px 10px rgba(213, 72, 63, 0.16);
  font-family: var(--km-cast-font);
  font-size: 15px;
  font-weight: 700;
  line-height: 1.4;
  letter-spacing: normal;
  text-transform: none;
  color: #fff;
  text-decoration: none;
  cursor: pointer;
}
.km-rp a.km-rp-btn:hover,
.km-rp a.km-rp-btn:focus-visible,
.km-rp button.km-rp-btn:hover,
.km-rp button.km-rp-btn:focus-visible { background: var(--km-rp-red-h); color: #fff; text-decoration: none; }
.km-rp button.km-rp-btn.km-rp-btn--sec,
.km-rp button.km-rp-btn.km-rp-btn--sec:focus,
.km-rp button.km-rp-btn.km-rp-btn--sec:active { border: 1px solid var(--km-rp-line); background: #fff; box-shadow: none; color: var(--km-rp-tab); }
.km-rp button.km-rp-btn.km-rp-btn--sec:hover,
.km-rp button.km-rp-btn.km-rp-btn--sec:focus-visible { background: var(--km-rp-sec-hover); color: var(--km-rp-ink2); }
.km-rp a.km-rp-quiet,
.km-rp a.km-rp-quiet:visited,
.km-rp button.km-rp-link,
.km-rp button.km-rp-link:focus,
.km-rp button.km-rp-link:active { display: inline-block; min-height: 0; margin: 0; padding: 0; border: 0; border-radius: 0; background: none; box-shadow: none; font-family: var(--km-cast-font); font-size: 14px; font-weight: 700; line-height: 1.5; letter-spacing: normal; text-transform: none; color: var(--km-rp-orange); text-decoration: none; cursor: pointer; }
.km-rp a.km-rp-quiet:hover,
.km-rp a.km-rp-quiet:focus-visible,
.km-rp button.km-rp-link:hover,
.km-rp button.km-rp-link:focus-visible { background: none; color: var(--km-rp-red); text-decoration: none; }

/* Вкладка 2 — «Мой журнал»: тот же вид GravityView, вопрос над ответом, дата словами, «Показать ещё» */
.km-rp .km-rp-journal__head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin: 0 0 20px; }
.km-rp .km-rp-journal__count { flex: none; font-size: 14px; color: var(--km-rp-muted); }
.km-rp .km-rp-empty { margin: 12px 0 0; font-size: 15px; line-height: 1.6; color: var(--km-rp-text); }
.km-rp .km-rp-list .gv-widgets-header,
.km-rp .km-rp-list .gv-widgets-footer,
.km-rp .km-rp-list .gv-widget-page-size,
.km-rp .km-rp-list .gv-entries-title { display: none; }
.km-rp .km-rp-list .gv-list-container,
.km-rp .km-rp-list .gv-entries { margin: 0; padding: 0; border: 0; }
/*
 * Записи — линиями, без рамок («Ресурсы» 1.4, прототип v7). Карточку с рамкой и линию над «Редактировать» рисует
 * общий CSS сайта для списков GravityView (сниппеты WPCode «Объединённый CSS» и «Gravity View/Gravity form - CSS»)
 * с `!important`; его не трогаем — перебиваем здесь, только на странице ресурса, как форму выше.
 */
.km-rp .km-rp-list .gv-list-view { margin: 0 !important; padding: 22px 0 !important; border: 0 !important; border-top: 1px solid var(--km-rp-line2) !important; border-radius: 0 !important; background: none !important; box-shadow: none; }
.km-rp .km-rp-list .gv-list-view:first-of-type { padding-top: 12px !important; border-top: 0 !important; }
.km-rp .km-rp-list .gv-list-view-title { margin: 0; padding: 0; border: 0; background: none; }
.km-rp .km-rp-list .gv-list-view-title h3 { margin: 0 0 14px; padding: 0; border: 0; font-family: var(--km-cast-display); font-size: 20px; font-weight: 500; line-height: 1.3; letter-spacing: normal; text-transform: none; color: var(--km-rp-ink2); }
.km-rp .km-rp-list .gv-list-view-content,
.km-rp .km-rp-list .gv-list-view-content-description { display: block; width: auto; margin: 0; padding: 0; }
.km-rp .km-rp-list .gv-list-view-content-description > div { margin: 0; font-size: 15px; line-height: 1.6; color: var(--km-rp-text); }
.km-rp .km-rp-list .gv-list-view-content-description > div + div { margin-top: 14px; }
.km-rp .km-rp-list .gv-field-label { display: block; font-weight: 700; color: var(--km-rp-ink2); }
/* Подпись поля-даты — в строку с датой: «Дата практики: 1 февраля 2024» («Ресурсы» 1.4), видом заголовка. */
.km-rp .km-rp-list .gv-list-view-title .gv-field-label { display: inline; font-weight: inherit !important; color: inherit; }
.km-rp .km-rp-list .gv-list-view-content-description p { margin: 2px 0 0; font-size: 15px; line-height: 1.6; color: var(--km-rp-text); }
/* Настрой — обычным полем, без значков списка (раздел 4, вкладка 2). */
.km-rp .km-rp-list .gv-list-view-content-description ul { margin: 2px 0 0; padding: 0; list-style: none; }
.km-rp .km-rp-list .gv-list-view-content-description li { margin: 0; padding: 0; }
.km-rp .km-rp-list .gv-list-view-content-description li::before { content: none; }
.km-rp .km-rp-list .gv-list-view-footer { display: flex; flex-wrap: wrap; gap: 18px; width: auto; margin: 14px 0 0 !important; padding: 0 !important; border: 0 !important; background: none !important; }
.km-rp .km-rp-list .gv-list-view-footer > div { width: auto; margin: 0; padding: 0; }
.km-rp .km-rp-list .gv-list-view-footer .gv-right { order: -1; }
.km-rp .km-rp-list .gv-list-view-footer .dashicons { display: none; }
.km-rp .km-rp-list .gv-list-view-footer a,
.km-rp .km-rp-list .gv-list-view-footer a:visited { font-size: 13px; font-weight: 600; line-height: 1.4; color: var(--km-rp-muted); text-decoration: none; }
.km-rp .km-rp-list .gv-list-view-footer a:hover,
.km-rp .km-rp-list .gv-list-view-footer a:focus-visible { color: var(--km-rp-red); text-decoration: none; }
.km-rp .km-rp-journal__foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding-top: 20px; border-top: 1px solid var(--km-rp-line2); font-size: 13px; color: var(--km-rp-muted2); }

/* Вкладка 3 — описание: ровный ритм числами раздела 4 */
.km-rp .km-rp-about { font-size: 16px; line-height: 1.8; color: var(--km-rp-text); }
.km-rp .km-rp-about > * { margin: 0; }
.km-rp .km-rp-about > * + * { margin-top: 18px; }
.km-rp .km-rp-about :is(ul, ol) { padding-left: 22px; }
.km-rp .km-rp-about li + li { margin-top: 8px; }
.km-rp .km-rp-about img { max-width: 100%; height: auto; }
.km-rp .km-rp-about :is(h2, h3, h4) { font-family: var(--km-cast-display); font-size: 26px; font-weight: 500; line-height: 1.25; letter-spacing: normal; text-transform: none; color: var(--km-rp-ink2); }
.km-rp .km-rp-about > * + :is(h2, h3, h4) { margin-top: 56px; }
.km-rp .km-rp-about > :is(h2, h3, h4) + * { margin-top: 24px; }
/* Видео: 24 под заголовком, подпись — 16 под ним, после видео или подписи — 40 до следующего блока. */
.km-rp .km-rp-about > :is(div:has(> iframe), figure.wp-block-embed, .wp-block-video, .wp-block-omnivideo, [class*="omnivideo"]) { border-radius: 12px; overflow: hidden; }
.km-rp .km-rp-about > :is(div:has(> iframe), figure.wp-block-embed, .wp-block-video, .wp-block-omnivideo, [class*="omnivideo"]) + * { margin-top: 40px; }
.km-rp .km-rp-about > :is(div:has(> iframe), figure.wp-block-embed, .wp-block-video, .wp-block-omnivideo, [class*="omnivideo"]) + p { margin-top: 16px; font-size: 14px; line-height: 1.6; color: var(--km-rp-muted); }
.km-rp .km-rp-about > :is(div:has(> iframe), figure.wp-block-embed, .wp-block-video, .wp-block-omnivideo, [class*="omnivideo"]) + p + * { margin-top: 40px; }
.km-rp .km-rp-about a,
.km-rp .km-rp-about a:visited { color: var(--km-rp-orange); text-decoration: none; }
.km-rp .km-rp-about a:hover { text-decoration: underline; }

/* Правая колонка: календарь практики */
.km-rp .km-rp-box { min-width: 0; padding: 22px 22px 20px; border: 1px solid var(--km-rp-line); border-radius: 14px; background: var(--km-rp-card); }
.km-rp h2.km-rp-cal__title { margin: 0 0 14px; font-family: var(--km-cast-display); font-size: 22px; font-weight: 500; line-height: 1.25; letter-spacing: normal; text-transform: none; color: var(--km-rp-ink2); }
.km-rp .km-rp-cal__head { display: flex; align-items: center; justify-content: space-between; margin: 0 0 8px; }
.km-rp .km-rp-cal__month { font-size: 15px; font-weight: 600; line-height: 1.4; color: var(--km-rp-ink2); }
.km-rp button.km-rp-cal__nav,
.km-rp button.km-rp-cal__nav:focus,
.km-rp button.km-rp-cal__nav:active,
.km-rp button.km-rp-cal__nav:disabled {
  appearance: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  box-shadow: none;
  color: var(--km-rp-tab);
  cursor: pointer;
}
.km-rp button.km-rp-cal__nav:hover,
.km-rp button.km-rp-cal__nav:focus-visible { background: var(--km-rp-chip); color: var(--km-rp-tab); }
.km-rp button.km-rp-cal__nav:disabled { color: var(--km-rp-out); cursor: default; }
.km-rp .km-rp-cal__nav .km-res-ico { width: 16px; height: 16px; }
.km-rp .km-rp-cal__grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 2px; text-align: center; }
.km-rp .km-rp-cal__wd { padding: 6px 0; font-size: 11px; font-weight: 600; line-height: 1.3; color: var(--km-rp-muted2); }
.km-rp button.km-rp-cal__day,
.km-rp button.km-rp-cal__day:focus,
.km-rp button.km-rp-cal__day:active,
.km-rp button.km-rp-cal__day:disabled {
  appearance: none;
  position: relative;
  height: 36px;
  min-width: 0;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  box-shadow: none;
  font-family: var(--km-cast-font);
  font-size: 13px;
  font-weight: 500;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  color: var(--km-rp-ink2);
  cursor: pointer;
}
.km-rp button.km-rp-cal__day:disabled { color: var(--km-rp-out); cursor: default; }
.km-rp button.km-rp-cal__day:not(:disabled):hover { background: var(--km-rp-chip); }
.km-rp button.km-rp-cal__day.is-recorded { font-weight: 700; }
.km-rp button.km-rp-cal__day.is-recorded::after { content: ""; position: absolute; bottom: 5px; left: 50%; width: 5px; height: 5px; margin-left: -2.5px; border-radius: 50%; background: var(--km-rp-red); }
.km-rp button.km-rp-cal__day.is-today { box-shadow: inset 0 0 0 1.5px var(--km-rp-red); }
.km-rp button.km-rp-cal__day.is-selected,
.km-rp button.km-rp-cal__day.is-selected:hover { background: var(--km-rp-red); color: #fff; }
.km-rp button.km-rp-cal__day.is-selected::after { background: #fff; }
.km-rp button.km-rp-cal__day:focus-visible { outline: 2px solid var(--km-rp-red); outline-offset: 1px; }
.km-rp .km-rp-cal__legend { display: flex; flex-wrap: wrap; gap: 14px; margin: 10px 0 0; font-size: 12px; line-height: 1.6; color: var(--km-rp-muted); }
.km-rp .km-rp-cal__legend-item { display: inline-flex; align-items: center; gap: 6px; }
.km-rp .km-rp-cal__mark { display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: var(--km-rp-red); }
.km-rp .km-rp-cal__ring { display: inline-block; width: 12px; height: 12px; border-radius: 4px; box-shadow: inset 0 0 0 1.5px var(--km-rp-red); }
/* Счёт одной строкой; цифра по верху строки — верх цифры = верх строчных букв подписи (Oswald 30/30 и Manrope
   14/20 — цифре 4 px сверху). Та же разметка у счёта челленджа. */
.km-rp .km-rp-num { display: flex; align-items: flex-start; gap: 10px; margin: 0; }
.km-rp .km-rp-num__big { flex: none; margin-top: 4px; font-family: var(--km-cast-display); font-size: 30px; font-weight: 500; line-height: 30px; color: var(--km-rp-ink2); }
.km-rp .km-rp-num__words { min-width: 0; font-size: 14px; line-height: 20px; color: var(--km-rp-text); }
.km-rp .km-rp-cal__count { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--km-rp-line2); }
.km-rp .km-rp-cal__note { margin: 12px 0 0; font-size: 13px; line-height: 1.5; color: var(--km-rp-muted); }
.km-rp .km-rp-cal__day-view { margin-top: 14px; padding: 14px 16px; border-radius: 10px; background: var(--km-rp-lilac); font-size: 13.5px; line-height: 1.55; color: var(--km-rp-text); }
.km-rp .km-rp-cal__day-view b { display: block; margin-bottom: 4px; font-weight: 700; color: var(--km-rp-ink2); }
.km-rp .km-rp-cal__day-view .km-rp-cal__answer { display: block; margin: 0; }
.km-rp .km-rp-cal__day-view button.km-rp-link { margin-top: 8px; font-size: 13px; }

/* Карточка «Челлендж» — компактная, сиреневая (6.2) */
.km-rp .km-rp-ch { min-width: 0; padding: 22px 22px 20px; border: 1px solid var(--km-rp-ch-line); border-radius: 14px; background: var(--km-rp-ch-bg); }
/* «Без рамки» (1.5, 3.1): карточка ресурса в чужой карточке — без своих полей, рамки и подложки. */
.km-rp .km-rp-ch.km-rp-ch--bare { padding: 0; border: 0; border-radius: 0; background: none; }
.km-rp p.km-rp-ch__kicker { margin: 0; font-size: 12px; font-weight: 700; line-height: 1.4; letter-spacing: 1.4px; text-transform: uppercase; color: var(--km-rp-kicker); }
.km-rp h2.km-rp-ch__title { margin: 4px 0 8px; font-family: var(--km-cast-display); font-size: 24px; font-weight: 500; line-height: 1.2; letter-spacing: normal; text-transform: none; color: var(--km-rp-ch-title); }
.km-rp p.km-rp-ch__goal { margin: 0; font-size: 13.5px; line-height: 1.6; color: var(--km-rp-ch-ink); }
.km-rp .km-rp-ch__sum { margin-top: 18px; }
.km-rp .km-rp-ch__num { gap: 8px; }
.km-rp .km-rp-ch__num .km-rp-num__big { color: var(--km-rp-ch-title); }
.km-rp .km-rp-ch__num .km-rp-num__words { font-size: 13.5px; color: var(--km-rp-ch-ink); }
.km-rp .km-rp-ch__bar { display: flex; height: 8px; margin-top: 10px; border-radius: 4px; background: var(--km-rp-track); overflow: hidden; }
.km-rp .km-rp-ch__cell { flex: 1 1 0; min-width: 0; }
.km-rp .km-rp-ch__cell.is-on { background: var(--km-rp-orange); }
.km-rp .km-rp-ch__cell.is-cut { border-right: 2px solid var(--km-rp-ch-bg); }
.km-rp .km-rp-ch__ticks { display: flex; height: 16px; margin-top: 4px; font-size: 11px; font-weight: 600; line-height: 16px; color: var(--km-rp-ch-dot-ink); }
.km-rp .km-rp-ch__tick-cell { position: relative; flex: 1 1 0; min-width: 0; }
.km-rp .km-rp-ch__tick { position: absolute; top: 0; right: 0; transform: translateX(50%); white-space: nowrap; }
.km-rp .km-rp-ch__tick--last { transform: none; }
.km-rp p.km-rp-ch__today { margin: 10px 0 0; font-size: 12.5px; line-height: 1.45; color: var(--km-rp-ok); }
.km-rp ul.km-rp-ch__stages { margin: 16px 0 0; padding: 0; border-top: 1px solid var(--km-rp-ch-line); list-style: none; }
.km-rp .km-rp-ch__stage { display: grid; grid-template-columns: 30px minmax(0, 1fr); gap: 12px; margin: 0; padding: 13px 0; border-bottom: 1px solid var(--km-rp-ch-line); }
.km-rp .km-rp-ch__stage:last-child { padding-bottom: 2px; border-bottom: 0; }
.km-rp .km-rp-ch__stage::before { content: none; }
.km-rp .km-rp-ch__dot { display: flex; align-items: center; justify-content: center; width: 30px; height: 30px; border-radius: 50%; background: var(--km-rp-ch-dot); font-family: var(--km-cast-display); font-size: 14px; font-weight: 600; line-height: 1; color: var(--km-rp-ch-dot-ink); }
.km-rp .km-rp-ch__dot--done { background: var(--km-rp-ok-bg); color: var(--km-rp-ok); }
.km-rp .km-rp-ch__dot--cur { background: #fff; box-shadow: inset 0 0 0 2px var(--km-rp-orange); color: var(--km-rp-orange); }
.km-rp .km-rp-ch__dot .km-res-ico { width: 16px; height: 16px; stroke-width: 2.6; }
.km-rp .km-rp-ch__dot--lock .km-res-ico { stroke-width: 1.8; }
.km-rp img.km-rp-ch__dot--medal { display: block; padding: 0; background: none; object-fit: cover; }
/* Верх кружка = верх прописных букв первой строки: Manrope 700 14/1,35 — тексту −4 px. */
.km-rp .km-rp-ch__stage-text { min-width: 0; margin-top: -4px; }
.km-rp .km-rp-ch__stage-title { display: block; font-size: 14px; font-weight: 700; line-height: 1.35; color: var(--km-rp-ch-title); }
.km-rp .km-rp-ch__stage-note { display: block; margin-top: 2px; font-size: 12.5px; line-height: 1.45; color: var(--km-rp-ch-ink); }
.km-rp .km-rp-ch__stage-note--ok { font-weight: 600; color: var(--km-rp-ok); }
.km-rp .km-rp-ch__stage-text button.km-rp-link { margin-top: 6px; font-size: 13px; }
/* Блок «Челлендж» на другой странице (1.4): «К записи за сегодня →» — ссылка на страницу ресурса, а не прокрутка. */
.km-rp .km-rp-ch__stage-text a.km-rp-link,
.km-rp .km-rp-ch__stage-text a.km-rp-link:visited { display: inline-block; margin-top: 6px; font-size: 13px; font-weight: 700; line-height: 1.5; color: var(--km-rp-orange); text-decoration: none; }
.km-rp .km-rp-ch__stage-text a.km-rp-link:hover,
.km-rp .km-rp-ch__stage-text a.km-rp-link:focus-visible { color: var(--km-rp-red); text-decoration: none; }
.km-rp p.km-rp-ch__edit { margin: 14px 0 0; padding-top: 12px; border-top: 1px solid var(--km-rp-ch-line); font-size: 13px; line-height: 1.5; color: var(--km-rp-edit); }
.km-rp p.km-rp-ch__edit a,
.km-rp p.km-rp-ch__edit a:visited { color: var(--km-rp-edit-a); text-decoration: none; }
.km-rp p.km-rp-ch__edit a:hover { color: var(--km-rp-red); }

/* Карточки блока «Справа»: «Мягкая» — сиреневая с сердцем, «Обычная» — белая. Стили блока «Группа». */
.km-rp .km-rp-cards { display: flex; flex-direction: column; gap: 20px; }
.km-rp .km-rp-cards > :where(*) { margin: 0; }
.km-rp .km-rp-cards .is-style-lms-res-soft,
.km-rp .km-rp-cards .is-style-lms-res-plain { display: flex; flex-direction: column; gap: 12px; margin: 0; padding: 25px 25px 35px; border: 1px solid var(--km-rp-line); border-radius: 14px; }
.km-rp .km-rp-cards .is-style-lms-res-soft { background: var(--km-rp-soft); }
/* Тема без поддержки раскладок заворачивает блоки группы во внутреннюю обёртку — промежутки ставятся и там. */
.km-rp .km-rp-cards :is(.is-style-lms-res-soft, .is-style-lms-res-plain) > .wp-block-group__inner-container { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.km-rp .km-rp-cards .is-style-lms-res-plain { border-radius: 15px; background: #fff; box-shadow: var(--km-rp-shadow); }
.km-rp .km-rp-cards .is-style-lms-res-soft::before {
  content: "";
  width: 24px;
  height: 34px;
  background: var(--km-rp-heart);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 20s-7-4.4-7-10a4 4 0 0 1 7-2.6A4 4 0 0 1 19 10c0 5.6-7 10-7 10z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 20s-7-4.4-7-10a4 4 0 0 1 7-2.6A4 4 0 0 1 19 10c0 5.6-7 10-7 10z'/%3E%3C/svg%3E") center / contain no-repeat;
}
.km-rp .km-rp-cards :is(.is-style-lms-res-soft, .is-style-lms-res-plain) :is(h2, h3, h4) { margin: 0; font-family: var(--km-cast-display); font-size: 24px; font-weight: 450; line-height: 1.25; color: var(--km-rp-plum); }
.km-rp .km-rp-cards :is(.is-style-lms-res-soft, .is-style-lms-res-plain) :is(p, li) { margin: 0; font-size: 15px; line-height: 1.75; color: var(--km-rp-text); }
.km-rp .km-rp-cards :is(.is-style-lms-res-soft, .is-style-lms-res-plain) :is(ol, ul) { margin: 0 0 16px; padding-left: 27px; }
.km-rp .km-rp-cards :is(.is-style-lms-res-soft, .is-style-lms-res-plain) p + p { margin-top: -2px; }

/* Внизу — компактные «Другие»: справа только «Все ресурсы →» */
.km-rp .km-rp-others { padding: 56px 0 64px; }
.km-rp .km-rp-others__head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 12px 20px; margin: 0 0 20px; }
.km-rp h2.km-rp-others__title { margin: 0; font-family: var(--km-cast-display); font-size: 34px; font-weight: 500; line-height: 1.2; letter-spacing: normal; text-transform: none; color: var(--km-rp-ink2); }
.km-rp a.km-rp-others__all,
.km-rp a.km-rp-others__all:visited { font-size: 15px; color: var(--km-rp-tab); text-decoration: none; }
.km-rp a.km-rp-others__all:hover,
.km-rp a.km-rp-others__all:focus-visible { color: var(--km-rp-red); text-decoration: none; }
.km-rp .km-rp-others__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 22px; }
.km-rp a.km-rp-mini,
.km-rp a.km-rp-mini:visited { display: flex; align-items: center; gap: 16px; min-width: 0; padding: 14px; border: 1px solid var(--km-rp-line); border-radius: 14px; background: #fff; text-decoration: none; }
.km-rp a.km-rp-mini:hover,
.km-rp a.km-rp-mini:focus-visible { border-color: var(--km-rp-hover-line); box-shadow: 0 8px 22px rgba(60, 40, 70, 0.06); text-decoration: none; }
.km-rp .km-rp-mini__img { flex: none; width: 100px; height: 100px; border-radius: 8px; object-fit: cover; }
.km-rp .km-rp-mini__img--bare { display: inline-flex; align-items: center; justify-content: center; background: var(--km-rp-chip); color: var(--km-rp-chip-ink); }
.km-rp .km-rp-mini__text { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.km-rp .km-rp-mini__kind { font-size: 13.5px; color: var(--km-rp-muted); }
.km-rp .km-rp-mini__title { font-family: var(--km-cast-display); font-size: 23px; font-weight: 500; line-height: 1.25; color: var(--km-rp-ink2); }

/* Окошко «Войдите» сообщества на странице ресурса: на компьютере — по центру, на телефоне — выезжает снизу. */
.km-rp .km-rp-login .km-hub-modal { align-items: center; }

@media (max-width: 1000px) {
  .km-rp .km-rp-lay { grid-template-columns: minmax(0, 1fr); }
  .km-rp .km-rp-side { grid-column: 1; margin-top: 28px; }
  .km-rp .km-rp-tabs ~ .km-rp-side { grid-row: auto; }
  .km-rp .km-rp-others__grid { grid-template-columns: minmax(0, 1fr); }
}

/* Телефон: поля 16, обложка маленькая над надписью, над формой — полоса челленджа */
@media (max-width: 700px) {
  .km-page.km-cast.km-res.km-rp { padding: 0 16px; }
  .km-rp .km-rp-crumbs { padding-top: 20px; font-size: 13px; }
  .km-rp .km-rp-head { grid-template-columns: minmax(0, 1fr); gap: 16px; padding: 20px 0 22px; }
  .km-rp .km-rp-cover { order: -1; width: 96px; height: 96px; margin: 0; border-radius: 10px; }
  .km-rp h1.km-rp-title { margin: 8px 0 10px; font-size: 34px; }
  .km-rp .km-rp-lead { font-size: 15.5px; }
  .km-rp .km-rp-lay { padding-top: 18px; }
  .km-rp .km-rp-side { margin-top: 18px; }
  .km-rp .km-rp-tabs { margin: 0 -16px 8px; padding: 0 16px 8px; }
  .km-rp a.km-rp-tab,
  .km-rp a.km-rp-tab:visited { padding: 10px 14px; font-size: 14px; }
  .km-rp .km-rp-card { padding: 22px 18px 24px; border-radius: 12px; }
  .km-rp h2.km-rp-card__title,
  .km-rp h2.km-rp-form__title { font-size: 26px; }
  .km-rp .km-rp-form__head { flex-direction: column; gap: 10px; }
  .km-rp .km-rp-pill { margin-top: 0; }
  .km-rp .km-res-form .gform_wrapper.gravity-theme .gfield_label,
  .km-rp .km-res-form .gform_wrapper.gravity-theme legend.gfield_label { font-size: 18px !important; }
  .km-rp .km-rp-strip { display: flex; }
  .km-rp .km-rp-others { padding: 40px 0 48px; }
  .km-rp h2.km-rp-others__title { font-size: 28px; }
  .km-rp .km-rp-mini__img { width: 76px; height: 76px; }
  .km-rp .km-rp-mini__title { font-size: 20px; }
  .km-rp .km-rp-cards .is-style-lms-res-soft,
  .km-rp .km-rp-cards .is-style-lms-res-plain { padding: 23px 19px 33px; }
  .km-rp .km-rp-cards :is(.is-style-lms-res-soft, .is-style-lms-res-plain) :is(h2, h3, h4) { font-size: 25px; }
  .km-rp .km-rp-login .km-hub-modal { align-items: flex-end; padding: 0; }
  .km-rp .km-rp-login .km-hub-dialog { width: 100%; min-height: 0; border-radius: 18px 18px 0 0; }
}
.km-rp .km-rp-cal__blank { display: block; }
