/* i(m)perfect — общий стиль платформы
   Опирается на бренд-платформу FutureProof: один яркий акцент (лайм),
   жирный гротеск на заголовках, толстая рамка-кадр, ясный/прямолинейный тон.
   Шрифты грузятся из <head> каждой страницы (preconnect + link), а не через
   @import здесь — @import создаёт лишний блокирующий рейс CSS→шрифты. */

:root {
  /* FutureProof · i(m)perfect — акцент вермилион, диапазон ИИ — Jordy Blue.
     Лайм (агентство INSAIM) удалён; см. DESIGN.md. Легаси-имена --lime*
     временно алиасят вермилион, чтобы точечные акценты флипнулись без
     переименования 55 мест; флуд-случаи (фон, рамка) правятся явно ниже
     и постепенно переезжают на семантические имена. */
  --accent: #ff4800;
  --accent-dim: #e63f00;
  --accent-tint: #fff2ec;
  --accent-line: #ffd7c7;
  --accent-ink: #c73500;  /* вермилион для мелкого текста на --accent-tint: 4.9:1 (WCAG 1.4.3); сам --accent там даёт 3.1:1 */
  /* ГОЛУБОЙ = «ВЫ» (решение 04.08, было наоборот — см. DESIGN.md, Colors).
     Участник отмечен голубым везде: своя реплика в дне (--band), маркер и свои
     значения в отчёте (--jb-ink). Вермилион в словаре сравнения перешёл на
     ИИ-референс и там всегда контуром, а не заливкой: у своих значений заливка,
     у референса контур — форма различает их, если цвет не прочитался. */
  --jb: #89bbf1;
  --band: #eaf3fb;
  --band-line: #bcd9f2;
  --jb-ink: #2f6bb0;   /* читаемый синий: текст на светлом и ЗАЛИТЫЙ маркер «вы» —
                          сам --jb на бумаге даёт ≈2:1, ниже порога 3:1 (WCAG 1.4.11) */
  --ink: #181818;
  --paper: #ffffff;
  /* ⚠ ВЕРМИЛИОНА ВНУТРИ АССЕССМЕНТА НЕТ (решение владельца 07.08). Он остаётся на
     двух экранах до старта — настройка и введение в роль; начиная с кейса всё,
     что было вермилионом, голубое. Правило одно и живёт в токенах: подменяем всю
     семью акцента на странице (body.p-assess ниже), а не тридцать правил по одному.
     Последствие названо владельцу: голубой внутри дня несёт два смысла — «моё»
     (бледная заливка --band) и «действие» (залитая кнопка --jb-ink); различает их
     заливка, а не оттенок. */
  --muted: #6b6e73;
  --muted-soft: #71747a; /* затемнён с #9a9da2 до ≈4.8:1 на белом (WCAG 1.4.3): читаемый текст/плейсхолдеры/хинты */
  --hairline: #e7e7e7;
  --soft: #f5f5f6;
  --frame: 0px;
  /* ⚠ 8px, а не 4 (решение владельца 07.08). DESIGN.md стр. 128 задаёт sm 4px, но
     один и тот же радиус на маленьком пузыре читается скруглением, а на большом поле
     ответа — почти прямым углом, и стиль расходился на глаз при одинаковом коде.
     Радиус остаётся ОДИН на всю платформу — меняется только его значение. */
  --radius: 8px;

  /* ---- масштаб раскладки (DESIGN.md → spacing / Layout) ----
     Одна шкала на всю платформу: ширины больше НЕ задаются литералами по месту.
     Правило «какая ширина какому типу контента»:
       --maxw     рамка приложения: шапка + рабочее тело раунда. Текучая:
                  снизу упирается в maxWidth 1120 из DESIGN.md, дальше тянется
                  до 1560 — чтобы на 1920/2560 не оставалось полполосы пустоты.
                  Это max-width, поэтому на узких экранах просто отдаёт всю ширину.
       --w-read   ЧТЕНИЕ (легенда, реплики, вопросы, текст кейса) — readWidth из
                  DESIGN.md. 04.08 опущен с 68ch до 60ch по решению владельца:
                  замер на русском тексте кейса дал при 68ch восемьдесят один знак
                  в строке, а комфортная полоса кончается на 75. Единица врёт по
                  построению — ch это ширина латинского нуля, кириллица у́же, — так
                  что ориентир здесь замер, а не число в записи. На мониторах до
                  1680 потолок вообще не участвует: строку держит ширина колонки.
       --w-form   ПИСЬМО (текстареа, поля) — шире прозы: человек пишет стратегию,
                  а не читает её. Но не во всю рамку, иначе строка расползается.
       --frame-pad боковой отступ рамки (spacing.frame) — текучий, ОДИН для шапки
                  и для тела, иначе лого разъезжается с колонкой контента. */
  --maxw: clamp(1120px, 92vw, 1560px);
  --w-read: 60ch;
  --w-form: 880px;
  --frame-pad: clamp(20px, 4vw, 56px);
  /* высота шапки раунда — нужна, чтобы экран легенды ложился ПОД шапку, а не поверх неё */
  --hdr-h: 70px;
  --ff-display: 'Inter Tight', sans-serif;
  --ff-body: 'Inter Tight', sans-serif;

  /* ---- МЕТКА: один рецепт на всю систему ----
     DESIGN.md, Label/kicker: 11px / вес 600 / разрядка 0.1em / UPPERCASE / серый-2.
     Сведено 04.08 по решению владельца. До этого одна и та же метка была написана
     ДВЕНАДЦАТЬЮ правилами и ВОСЬМЮ разными наборами значений: кегли 10, 10.5, 11 и 13,
     вес всюду 700 вместо 600, разрядка от 0.05 до 0.14em. Разница читалась не как
     иерархия, а как небрежность, и любая правка «метки» требовала найти все двенадцать.
     Теперь размер, вес и разрядка живут здесь; правила ниже задают только положение
     и цвет (цвет отдельный, потому что у двух меток он несёт сигнал). */
  /* ---- ШКАЛА КЕГЛЯ: пять ступеней, у каждой своя работа ----
     Сведено 04.08 по решению владельца («давай пока 5»). До этого на экране дня
     было ПЯТНАДЦАТЬ размеров в шестидесяти семи объявлениях, шесть из них
     половинные (10.5, 11.5, 12.5, 13.5, 14.5, 15.5) — между 13 и 12.5 разницы не
     видно, то есть половинные ступени не работали как иерархия, а только добавляли
     голосов. DESIGN.md определяет для такого экрана три ступени; двух не хватает,
     потому что плотные списки портфеля шестнадцатым кеглем не помещаются, — эти две
     дописаны в документ вместе с их работой.
     Глубокая адаптация бренд-платформы под инструмент — отдельный проход позже. */
  /* ⚠ ШКАЛА СВЕДЕНА К ДЕВЯТИ СТУПЕНЯМ (правка владельца 19.08). Было восемнадцать
     кеглей, из них шесть дробных — 10,5 / 11,5 / 12,5 / 13,5 / 14,5 / 15,5 — в
     четырнадцати местах: от соседней ступени они отличались на полпикселя, как
     решение это не читается, а неровность видна. И семнадцать мест были написаны
     числом мимо токенов, причём семь просто повторяли существующий токен. Теперь
     ЧИСЕЛ В КЕГЛЯХ НЕТ ВООБЩЕ: 59 объявлений переведены на токены, дробные
     сведены к ближайшей ступени, 19px и 24px — к 20. Новый кегль заводить только
     новым токеном с причиной, иначе шкала расползётся снова. */
  --fs-place: 26px;   /* место сцены, заголовок межсценового экрана */
  --fs-read: 16px;    /* всё, что читают: реплики, поле ответа, установка, свод */
  /* ⚠ НОВЫЙ ТОКЕН, И ВОТ ПРИЧИНА (правка владельца 25.08 — «этот текст хочется сделать
     более важным»). Между --fs-read и --fs-place на шкале участника не было ничего, а
     20px существовал только в ОПЕРАТОРСКОЙ шкале, мешать которую со шкалой участника
     запрещено правилом выше. Взять --fs-place (26px) значило бы набрать абзац кеглем
     заголовка межсценового экрана. Поэтому одна новая ступень — и ровно на одну роль:
     фраза под заголовком экрана до старта, ту, которую участник обязан прочитать. Если
     она понадобится где-то ещё, это и будет проверкой, что ступень настоящая. */
  --fs-lead: 20px;    /* фраза под заголовком экранов до старта — то, что читают первым */
  --fs-dense: 14px;   /* плотные списки: карточки портфеля, выписки, справка */
  --fs-util: 12px;    /* служебное: записки у кнопок, ссылки оглавления, статусы */
  /* Заголовок страницы и лого — не проза, у них своя роль и свой размер. Токены
     здесь для того, чтобы размер задавался ОДИН раз: до 07.08 кегль заголовка жил
     инлайном на двух страницах и «переезжал» сам собой. */
  --fs-hero: clamp(34px, 4.4vw, 60px);  /* h1 экранов до старта */
  --fs-hero-xl: clamp(38px, 5.6vw, 76px); /* h1 лендинга */
  /* Два заголовка жили числом мимо шкалы (сверка 04.10) — значения прежние, токен только
     даёт им имя: h2 экранов-заглушек (конец ассессмента, ошибки входа) и h1 экрана
     «Не с телефона», который по построению видят только на узком экране. */
  --fs-h2: clamp(28px, 3.2vw, 42px);
  --fs-hero-phone: clamp(30px, 8vw, 40px);
  --fs-logo: 18px;
  /* ОПЕРАТОРСКАЯ ШКАЛА — кабинет оценок и фасилитатор. У них плотные таблицы, и
     11–15 им действительно нужны; отдельные токены здесь потому, что мешать их со
     шкалой участника нельзя, а брать «12,5 из соседнего правила» — то, из-за чего
     кеглей стало тридцать. */
  --fs-op-xl: 20px;
  --fs-op-h: 15px;
  --fs-op: 13px;
  --fs-op-sm: 11px;
  --label-size: 11px; /* метка — и только метка, см. рецепт ниже */
  /* ПОДЗАГОЛОВОК РАЗДЕЛА («КАК ОТВЕЧАТЬ», «ТЕЗИСЫ», «СЛЕДУЮЩИЙ ЭТАП 3 ИЗ 7»).
     Отдельный токен, хотя число сейчас совпадает с --fs-read: у подзаголовка своя
     роль, и менять его надо будет отдельно от прозы. Решение владельца 07.08:
     подзаголовки обязаны читаться крупнее основного текста — прописными и жирным
     на 16px они и читаются, оставаясь тише заголовка этапа (26px). */
  --fs-sub: 16px;
  --label-weight: 600;
  --label-track: 0.1em;

  /* legacy aliases → вермилион (временные, убрать по мере миграции секций) */
  /* ЛЕГАСИ: --lime* остались с до-редизайна, но держат ВЕРМИЛИОН (не лайм). Алиас
     намеренный — чтобы не переписывать 30+ мест; значения = вермилион-палитра. */
  --lime: #ff4800;
  --lime-dim: #e63f00;
  --lime-tint: #fff2ec;
  --lime-line: #ffd7c7;
  --line: #181818;
}

/* СТРАНИЦА АССЕССМЕНТА: вся семья акцента — голубая. Правило стоит сразу за :root,
   потому что подменяет только значения токенов; ни одно правило ниже про это не
   знает и знать не должно. Обе семьи (--accent* и легаси --lime*) — иначе
   тридцать мест на --lime остались бы вермилионовыми. */
body.p-assess {
  --accent: #2f6bb0;        /* = --jb-ink */
  --accent-dim: #24558c;    /* ховер залитой кнопки */
  --accent-ink: #2f6bb0;
  --accent-tint: #eaf3fb;   /* = --band */
  --accent-line: #bcd9f2;   /* = --band-line */
  --lime: #2f6bb0;
  --lime-dim: #24558c;
  --lime-tint: #eaf3fb;
  --lime-line: #bcd9f2;
}

/* Диалоговые раунды (3/4/5): рабочая зона — узкая колонка чтения/письма, широкая
   текучая рамка там не занята ничем, и контролы шапки с язычками уезжали из поля
   зрения на большом мониторе. Рамка следует за типом контента (DESIGN.md):
   диалогам — 1120 (нижняя граница maxWidth), верстакам (раунды 1/2, карта,
   кабинет) — полная текучая. Всё, что сидит на var(--maxw) — шапка, тело,
   легенда, язычки, полоса времени, — стягивается автоматически.
   ⚠ Блок обязан стоять ПОСЛЕ закрытого :root и содержать ТОЛЬКО --maxw:
   первая вставка закрыла :root раньше времени и утащила сюда переменные
   шрифтов — все страницы без .frame-narrow упали в Times. */
/* ⚠ С 04.08 не применяется ни на одной странице: assessment.html его снял (см.
   комментарий там). Правило оставлено для будущих экранов-разговоров, но помните
   его цену — оно меняет ЗНАЧЕНИЕ --maxw, а не отменяет ограничение: экрану, тело
   которого на --maxw не сидит, оно только уменьшает разъезд шапки, а не убирает. */
body.frame-narrow {
  --maxw: 1120px;
}

* { box-sizing: border-box; }

/* Формы НЕ наследуют шрифт по умолчанию (браузер ставит свой) — принудительно
   наследуем всем, чтобы точечные textarea/input без явного font-family
   не выпадали из Inter Tight. */
input, textarea, select, button { font-family: inherit; }
/* Браузерный accent-color по умолчанию красит радио и галочки в системный синий.
   Один раз на всю платформу — чернила. (Наш Jordy Blue --jb несёт смысл «вы» и
   «служебное», а не «элемент управления», поэтому системный синий тут ни при чём.) */
input[type="radio"], input[type="checkbox"] { accent-color: var(--ink); }

html, body {
  margin: 0;
  padding: 0;
  background: var(--paper);
}

body {
  font-family: var(--ff-body);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
}

.frame {
  border: 0;
  /* минус хром демо — см. .station-shell; вне демо переменной нет → 100vh */
  min-height: calc(100vh - var(--demo-chrome, 0px));
  background: var(--paper);
}

.wrap {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 32px;
}

a { color: inherit; }

/* Единый рецепт метки. Стоит рано, чтобы правила ниже могли задавать только своё —
   отступы и цвет. Если когда-нибудь метке понадобится другой размер, менять надо
   токены выше, а не этот список. */
.kicker, .chat-name, .recap-q, .win-fixed, .win-label-past, .bl-over-tag, .dayside-kicker, .toc-title, .who-h, .toc-group, .bl-zone-h, .hdr-num {
  font-family: var(--ff-body);
  font-size: var(--label-size);
  font-weight: var(--label-weight);
  letter-spacing: var(--label-track);
  text-transform: uppercase;
  color: var(--muted-soft);
}

/* ⚠ РАЗДЕЛЕНИЕ РОЛЕЙ (решение владельца 07.08). Рецепт выше держит СЛУЖЕБНЫЕ отметки
   («ВЫ», «№ 000900», «✓ зафиксировано») — им 11px. Подзаголовки разделов — другая
   роль: они называют кусок экрана и обязаны читаться крупнее прозы под ними. */
.kicker, .recap-q, .dayside-kicker, .toc-title, .who-h, .toc-group, .bl-zone-h, .mx-title, .interlude-next {
  font-size: var(--fs-sub);
}
/* Числа внутри подзаголовка зон портфеля остаются служебными. */
.bl-zone-h b { font-size: var(--fs-util); }
/* Счётчик у заголовка зоны — тем же кеглем и разрядкой, что слово, только тише:
   это часть той же строки, а не отдельная метка. */
.bl-zone-h .bl-zone-n { font-size: inherit; font-weight: inherit; color: var(--muted-soft); }

/* ---------- nav ---------- */

.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 28px 0 24px;
}

/* Продукт-лок futureproof ▸ i(m)perfect. Стрелка — точный бренд-SVG из
   отчёта-референса (треугольник, не юникод). i(m)perfect — приглушённый серый. */
.logo {
  font-family: var(--ff-body);
  font-weight: 700;
  font-size: var(--fs-read);
  letter-spacing: -0.01em;
  text-decoration: none;
  color: var(--ink);
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.logo-arrow {
  display: inline-block;
  width: 12px;
  height: 12px;
  position: relative;
  top: 1px;
}
.logo-arrow svg { display: block; width: 100%; height: 100%; }

.logo-prod {
  margin-left: 3px;
  font-weight: 600;
  color: var(--muted-soft);
}

/* легаси: старый бокс-«m» больше не в разметке, но правило безвредно оставить пустым */
.logo span.mark { background: transparent; color: inherit; padding: 0; border-radius: 0; }
/* ---------- buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  font-family: var(--ff-body);
  font-weight: 700;
  font-size: var(--fs-read);
  padding: 14px 24px;
  border-radius: var(--radius);
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  transition: background 0.14s ease, border-color 0.14s ease, color 0.14s ease;
  white-space: nowrap;
}

.btn-primary {
  background: var(--accent);
  color: var(--paper);
}
.btn-primary:hover { background: var(--accent-dim); }

.btn-ghost {
  background: transparent;
  color: var(--ink);
  border-color: var(--hairline);
}
.btn-ghost:hover { border-color: var(--ink); }

.btn-block { width: 100%; }

.btn[disabled] {
  opacity: 0.4;
  cursor: not-allowed;
  pointer-events: none;
}

/* ---------- hero ---------- */

.hero {
  padding: 40px 0 72px;
  border-bottom: 1px solid #ececec;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: var(--fs-op);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--ink);
  background: var(--lime);
  padding: 7px 14px;
  border-radius: 999px;
  margin-bottom: 28px;
}

h1 {
  font-family: var(--ff-display);
  font-weight: 900;
  font-size: var(--fs-hero-xl);
  line-height: 1.02;
  letter-spacing: -0.02em;
  margin: 0 0 28px;
  max-width: 16ch;
  overflow-wrap: break-word;
}
.stat-row .k { color: var(--muted-soft); flex: none; white-space: nowrap; }
.stat-row .v { font-weight: 700; text-align: right; }

/* ---------- section shell ---------- */

section { padding: 72px 0; }
section + section { border-top: 1px solid #ececec; }
.kicker {
  margin: 0 0 10px;
}

h2 {
  font-family: var(--ff-display);
  font-weight: 800;
  font-size: var(--fs-h2);
  line-height: 1.08;
  letter-spacing: -0.01em;
  margin: 0;
  max-width: 20ch;
  overflow-wrap: break-word;
}

.section-lead {
  font-size: var(--fs-read);
  line-height: 1.6;
  color: var(--muted);
  max-width: 42ch;
}

/* ---------- skills grid ---------- */

.skills {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: #ececec;
  border: 1px solid #ececec;
  border-radius: var(--radius);
  overflow: hidden;
}

.skill {
  background: var(--paper);
  padding: 28px 22px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-height: 190px;
}

.skill .num {
  font-family: var(--ff-display);
  font-weight: 900;
  font-size: var(--fs-place);
  color: var(--lime-dim);
  -webkit-text-stroke: 1.5px var(--ink);
}

.skill h3 {
  font-family: var(--ff-body);
  font-size: var(--fs-read);
  font-weight: 700;
  line-height: 1.3;
  margin: 0;
}

.skill p {
  font-size: var(--fs-op);
  line-height: 1.5;
  color: var(--muted);
  margin: 0;
}

.skill.score2 { background: var(--ink); color: var(--paper); }
.skill.score2 .num { color: var(--lime); -webkit-text-stroke: 0; }
.skill.score2 h3 { color: var(--paper); }
.skill.score2 p { color: #b9bbbe; }
.case-body p.quote {
  font-family: var(--ff-display);
  font-weight: 600;
  font-size: var(--fs-op-xl);
  color: var(--ink);
  line-height: 1.4;
}/* .case-brief селектор поднимает специфичность выше .case-content p (0,1,1),
   иначе верхний отступ обнулялся и плашка липла к списку. Небольшой зазор. */
.case-brief .case-brief-note {
  margin: 14px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--lime-line);
  font-size: var(--fs-op);
  color: var(--muted);
}
/* ⚠ ДВА ПРАВИЛА .intro-note НА ОДИН КЛАСС — И ЭТО НАДО БЫЛО СВЕСТИ (найдено 26.08).
   Здесь стоял свой рецепт (--fs-dense, приглушённый), а ниже, у экранов до старта,
   второй — с --fs-read, линейкой и другим цветом. Действовал второй: он позже в файле,
   специфичность равная. Я правил цвет здесь и не увидел изменений на экране.
   Оставляем ОДИН рецепт — тот, что ниже; здесь только то, чего в нём нет. */
.intro-note { display: block; margin-top: 10px; }

/* Поле имени на экране установки. Ширина как у полей формы, а не во всю колонку:
   имя короткое, растянутый инпут читается как поле для абзаца. */
.intro-name input {
  display: block;
  width: 100%;
  max-width: 320px;
  margin-top: 12px;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  padding: 11px 13px;
  font: inherit;
  font-size: var(--fs-read);
  background: var(--paper);
}
.intro-name input:focus { outline: none; border-color: var(--jb-ink); }
/* ⚠ ПУСТОЕ ПОЛЕ ПОСЛЕ ПОПЫТКИ УЙТИ (правка владельца 25.08). Красным помечаем только
   после нажатия на «Приступить», а не сразу: подсвечивать поле, к которому человек
   ещё не подходил, значит ругать его до первой ошибки. Снимается на первом же вводе. */
.intro-name input.is-empty { border-color: var(--accent); }
.intro-name-warn {
  margin: 8px 0 0; font-size: var(--fs-util); color: var(--accent-ink);
}
.intro-name-warn[hidden] { display: none; }

/* ---------- steps / format ---------- */

.steps {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22px;
}

.step {
  border: 1px solid #ececec;
  border-radius: var(--radius);
  padding: 26px 24px;
  position: relative;
}

.step .step-no {
  position: absolute;
  top: -14px;
  left: 22px;
  background: var(--lime);
  border: 2px solid var(--ink);
  font-family: var(--ff-display);
  font-weight: 800;
  font-size: var(--fs-op);
  padding: 4px 10px;
  border-radius: 999px;
}

.step h3 {
  font-family: var(--ff-body);
  font-size: var(--fs-read);
  font-weight: 700;
  margin: 14px 0 10px;
}

.step p {
  font-size: var(--fs-dense);
  line-height: 1.55;
  color: var(--muted);
  margin: 0;
}
.logi {
  padding: 22px 0;
  border-top: 2px solid var(--ink);
}

.logi h4 {
  font-family: var(--ff-body);
  font-size: var(--fs-dense);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin: 0 0 10px;
}

.logi p {
  font-size: var(--fs-dense);
  line-height: 1.55;
  color: var(--muted);
  margin: 0;
}
.final-cta .btn-primary {
  background: var(--lime);
  color: var(--ink);
  border-color: var(--lime);
}
.final-cta .btn-primary:hover { box-shadow: 6px 6px 0 var(--paper); }

/* ---------- footer ---------- */

footer {
  padding: 32px 0 44px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: var(--fs-op);
  color: var(--muted); /* 7.13:1 — AA даже для меты футера */
  flex-wrap: wrap;
  gap: 12px;
}
.reg-side .logo { color: var(--paper); }
.reg-side .logo span.mark { background: var(--lime); color: var(--ink); }

.reg-side-top .eyebrow {
  background: transparent;
  border: 1px solid var(--lime);
  color: var(--lime);
  margin-top: 36px;
}
.reg-checklist li .dot {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--lime);
  margin-top: 6px;
}
.reg-form .section-lead {
  margin-bottom: 32px;
  max-width: none;
}
.field {
  margin-bottom: 20px;
}

.field label {
  display: block;
  font-size: var(--fs-op);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: 8px;
}

.field .req { color: var(--lime-dim); }

.field input[type="text"], .field input[type="email"], .field input[type="password"], .field select {
  width: 100%;
  font-family: var(--ff-body);
  font-size: var(--fs-op-h);
  padding: 14px 16px;
  border: 1.5px solid #d8dadd;
  border-radius: 10px;
  background: var(--paper);
  color: var(--ink);
  transition: border-color 0.15s ease;
}

.field input:focus, .field select:focus {
  outline: none;
  border-color: var(--ink);
}

/* --- малый вариант кнопки (вместо инлайн-патчей размеров/font-size) --- */
.btn-sm { padding: 11px 20px; font-size: var(--fs-dense); }
/* На тач-устройствах добираем до 44px тап-таргета (WCAG 2.5.5). */
@media (pointer: coarse) {
  .btn-sm { min-height: 44px; }
}

/* Компактные кнопки шапки станций (?, «Мои ответы», «Закрыть») и размер
   плашки-номера — были повторяющимся инлайном на station1/2/3 и в комнатах. */
.btn-xs { padding: 6px 12px; font-size: var(--fs-dense); }
/* иконки-кнопки в шапке станции («?» и «ⓘ») — равные квадраты независимо от
   глифа (иначе «ⓘ» шире «?»); button и a выравниваются одинаково */
.station-header-right .btn-xs { width: 32px; min-width: 32px; height: 32px; padding: 0; line-height: 1; }
/* .bib по умолчанию — крупная «нашивка» (30px, для отдельных экранов). В любой
   шапке она служебная и мелкая. Правило было заскоплено только на .station-header,
   поэтому на своём ряду экрана сборки Р6 номер вылезал во всю величину. */
.station-header .bib, .finalize-top .bib { font-size: var(--fs-dense); padding: 6px 12px; }
/* --- опасное действие: удаление (семантический красный, не бренд-акцент) --- */
.btn-danger { background: var(--ink); color: #ff7a6b; border-color: var(--ink); }
.btn-danger:hover { box-shadow: 6px 6px 0 #ff7a6b, 6px 6px 0 1px var(--ink); }

/* --- внутрисистемный тост (вместо native alert) --- */
.imp-toast {
  position: fixed; left: 50%; bottom: 28px; transform: translate(-50%, 12px);
  z-index: 4000; max-width: min(520px, calc(100vw - 32px));
  background: var(--ink); color: var(--paper);
  font-family: var(--ff-body); font-size: var(--fs-dense); line-height: 1.45;
  padding: 14px 18px; border-radius: var(--radius); border: 1px solid var(--ink);
  opacity: 0; transition: opacity .2s ease, transform .2s cubic-bezier(.2,.8,.2,1);
}
.imp-toast.is-in { opacity: 1; transform: translate(-50%, 0); }
.imp-toast.is-error { color: #ff8a7d; box-shadow: 6px 6px 0 #ff7a6b; }

/* --- внутрисистемный диалог подтверждения (вместо native confirm) --- */
.imp-confirm {
  position: fixed; inset: 0; z-index: 4001; padding: 24px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(10, 10, 10, 0.5);
}
.imp-confirm-card {
  background: var(--paper); color: var(--ink);
  border-radius: var(--radius); padding: 28px 28px 24px;
  max-width: 460px; width: 100%; border: 1px solid var(--hairline);
}
.imp-confirm-msg { font-family: var(--ff-body); font-size: var(--fs-op-h); line-height: 1.55; margin: 0 0 22px; }
.imp-confirm-actions { display: flex; gap: 12px; justify-content: flex-end; flex-wrap: wrap; }

@media (prefers-reduced-motion: reduce) {
  .imp-toast { transition: opacity 0.01s; transform: translate(-50%, 0); }
}

/* Видимый фокус для клавиатуры (WCAG 2.4.7). Только :focus-visible —
   мышиные клики не рисуют контур. Поля ввода сохраняют свою смену border. */
:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}
/* Строка таблицы фокусируется как единое действие — контур внутрь,
   чтобы не перекрывать соседние строки. */
.field input:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}
.field-hint {
  font-size: var(--fs-util);
  color: var(--muted); /* 7.13:1 — подпись поля должна проходить AA (используется и на register) */
  margin-top: 6px;
}
.links-intro p:not(.kicker) {
  font-size: var(--fs-op-h);
  line-height: 1.65;
  max-width: var(--w-read);
}
.tag-pill.is-active {
  background: var(--ink);
  color: var(--lime);
  border-color: var(--ink);
}
.s2-block {
  /* 44px было лендинговым ритмом: на рабочем экране блоки идут подряд, и такой шаг
     разрывал один разговор на несвязанные куски (замечание владельца 07.08). */
  margin-bottom: 26px;
}/* Реплики Агеева опознаёт жирная метка-имя (по DESIGN.md), а не боковая полоса. */
.s2-ageev b { color: var(--ink); }
.s2-act {
  border: 1px solid #d6d8d2;
  background: transparent;
  border-radius: 7px;
  font-size: var(--fs-util);
  padding: 3px 8px;
  cursor: pointer;
  font-family: inherit;
  white-space: nowrap;
}
.s2-act:hover { border-color: var(--ink); }

/* ---------- раунд 2 · бэклог решений менеджеров (ПР-1) ----------
   Двадцать чужих решений с ценой в людях и деньгах против остатка 500 / 22.
   Переподписка 5× по людям — если счётчик не показывать, ограничение
   ненаблюдаемо и ловушки бэклога не срабатывают. Выход за рамку не
   блокируется: превышение — наблюдаемый ответ, а не ошибка формы. */

/* Вся колонка разбора — одной шириной. Иначе строка растягивалась на всю рабочую
   область: текст кончался на 62ch, кнопки были прижаты к правому краю, и между
   ними оставалось полполосы пустоты. Ширина посчитана под содержимое: 62ch
   названия плюс зазор плюс две кнопки по 92px. */
.bl-sum, .bl-decided, .bl-list, .bl-hint { max-width: 880px; }

.bl-sum {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
  align-items: baseline;
  background: var(--paper);
  border-bottom: 1px solid var(--hairline);
  padding: 12px 0;
  margin: 18px 0 6px;
  font-size: var(--fs-dense);
  color: var(--muted);
}
.bl-sum b { font-size: var(--fs-read); color: var(--ink); font-variant-numeric: tabular-nums; }
.bl-sum-item.is-over b { color: var(--accent-ink); }
.bl-sum-item.is-over { color: var(--accent-ink); }
.bl-sum-left { margin-left: auto; color: var(--muted-soft); }
.bl-sum.is-over { border-bottom-color: var(--accent); }
.bl-actions .s2-act {
  font-size: var(--fs-dense);
  padding: 8px 14px;
  min-width: 92px;
  text-align: center;
  border-radius: var(--radius);
}
.bl-mini {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 6px 12px;
  align-items: baseline;
  padding: 8px 0;
  border-bottom: 1px solid var(--hairline);
  font-size: var(--fs-dense);
}
.bl-mini.is-open .bl-mini-title { color: var(--ink); font-weight: 600; }/* Пояснение живёт внутри строки отказа — второй копии списка нет. */
.bl-mini .bl-reason { grid-column: 1 / -1; margin-top: 2px; }/* «Моя» сторона разговора в раунде 2: пока шаг открыт — поля справа, той же
   ширины и в том же акценте, что и будущий пузырь ответа. Зафиксированный ответ
   рендерится обычным .chat-msg.me, поэтому переход «печатал → сказал» не меняет
   ни положение, ни цвет — меняется только рамка ввода на пузырь. */
/* СВОЯ КАРТОЧКА: внутри — левая выключка, сама карточка прижата вправо и не шире
   меры письма (--w-form). Мера, а не доля колонки: доля растёт вместе с экраном,
   и на 2560 карточка снова была бы во всю ширину. */
.s2-mine {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  /* Тот же ритм, что у .chat: 20px до следующей реплики, 8px внутри своей стороны. */
  margin: 0 0 20px;
  /* 3/4 колонки, прижато вправо: своё видно как своё. Но доля ограничена с двух
     сторон — мерой письма сверху (--w-form, шире строки не пишут) и 560px снизу
     (на узкой колонке 3/4 — это 476px, писать стратегию в такой полосе нельзя). */
  /* ⚠ 2/3 И ПОРОГ 400px (правка владельца 19.08). Было 3/4 при пороге 560px,
     и при открытой панели материалов колонка ~460px — доля не срабатывала ни разу,
     ответ всегда занимал всю ширину. С порогом 400px смещение вправо видно и на
     узкой колонке, а места писать по-прежнему хватает. */
  width: 66.6%;
  min-width: min(100%, 400px);
  margin-left: auto;
}
.s2-mine > * { width: 100%; max-width: none; }
/* «ВЫ» — НАД пузырём и справа, вне голубого (правка владельца 07.08). Внутри
   пузыря подпись и кнопка держали две пустые полосы — сверху и снизу. */
.chat-name-mine { display: block; text-align: right; margin: 0 0 6px; }
/* ⚠ Вермилионной рамки у поля ответа больше НЕТ. Она осталась от прежнего дизайна,
   где своё метили акцентом; сегодня своё метится голубым, и оранжевый контур на белом
   поле внутри голубой карточки читался как ошибка ввода. Акцент в системе помечает
   действие (DESIGN.md стр. 101), а не место для письма. */
.s2-mine textarea {
  border-color: var(--hairline);
  background: var(--paper);
}
.s2-mine textarea:focus { outline: none; border-color: var(--jb-ink); }
.s2-mine .s2-radio {
  justify-content: flex-start;
  margin: 0;
  padding: 9px 14px;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background: var(--paper);
}
.s2-mine .s2-radio:has(input:checked) {
  border-color: var(--jb-ink);
  background: var(--band);
  font-weight: 600;
}
@media (max-width: 700px) {
  .s2-mine > * { width: 100%; max-width: 100%; }
}

.bl-hint {
  margin: 16px 0 0;
  font-size: var(--fs-dense);
  line-height: 1.5;
  color: var(--accent-ink);
  max-width: var(--w-read);
}

@media (max-width: 700px) {  .bl-actions .s2-act { flex: 1; min-width: 0; }
  .bl-mini { grid-template-columns: 1fr auto; }  .bl-sum-left { margin-left: 0; width: 100%; }
}

/* ---------- ПП: конструктор этапов + барьеры/ресурсы (room-path.js) ---------- */

.pp-firstmove {
  border: 1px solid var(--accent-line);
  background: var(--accent-tint);
  padding: 8px 12px;
  margin: 0 0 14px;
  border-radius: var(--radius);
  font-size: var(--fs-dense);
  line-height: 1.5;
}
.pp-type-btn.is-on { background: var(--accent-tint); border-color: var(--accent); font-weight: 600; }
/* .gate-card.* (не просто .finalize-card/.dossier-card): .gate-card задаёт
   свой max-width:420px ниже по файлу — при равной специфичности выигрывало
   бы правило, идущее позже в файле (т.е. .gate-card), и оба этих модификатора
   молча схлопывались обратно в узкую 420px карточку независимо от заявленного
   здесь max-width. Составной селектор специфичнее одиночного класса — теперь
   порядок правил в файле не важен. */
/* Экран сборки Р6 — не карточка-сообщение, а рабочая страница: у .gate стоит
   align-items:center, и длинный документ стратегии «висел в воздухе» по центру с
   воздухом сверху и снизу, тогда как на всех рабочих экранах шапка прижата к
   верху. Прижимаем к верху и снимаем внешний воздух: экран выглядит как
   страница, а не как всплывшая карточка. Скроллит сам .gate (у него 100vh). */
#finalizeScreen {
  align-items: flex-start;
  padding: 0;
  /* Свой скролл-контейнер, как рабочее тело раунда: при min-height:100vh + высокая
     карточка скроллилась вся СТРАНИЦА, и шапка Р6 уезжала — та же болезнь, что
     чинили в раундах. Фиксируем высоту (минус хром демо) и скроллим внутри. */
  height: calc(100vh - var(--demo-chrome, 0px));
  min-height: 0;
  overflow-y: auto;
}
/* и шапка Р6 остаётся на месте при прокрутке документа стратегии */
.finalize-card .finalize-top {
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--paper);
}
.gate-card.finalize-card {
  max-width: var(--maxw);
  min-height: 100%;
  padding: 0 var(--frame-pad) 40px;
  border-radius: 0;
}
/* шапка Р6 прижата к верхнему краю, как .station-header у рабочих экранов */
.finalize-card .finalize-top { padding-top: 14px; }

/* Шапка экрана сборки Р6: .gate прячет шапку станции, а обещание установки
   («номер, ?, ⓘ под рукой») должно держаться и здесь. Геометрия — как у
   .station-header: тот же ряд, тот же hairline снизу, те же служебные размеры,
   чтобы шапка не читалась «половинчатой». Лого здесь fp ▸ stratos (финал —
   поверхность другого продукта), поэтому это свой блок, а не .station-header. */
.finalize-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  row-gap: 8px;
  padding-bottom: 14px;
  margin-bottom: 18px;
  border-bottom: 1px solid var(--hairline);
}
.finalize-top .station-sep { color: var(--hairline); }
.finalize-top .finalize-screen-name { font-size: var(--fs-op-h); font-weight: 700; margin: 0; }

/* «Ваша линия» — полоса решений под шапкой (spine.js), одинаковая на ст.2/3 и в
   комнатах. Приглушённая: серая подложка + волосяная линия, без лаймового сигнала
   (лайм бережём для акцентов). Значения — ink, метки — muted. */
.imp-spine {
  flex: none;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  padding: 8px 24px;
  border-bottom: 1px solid var(--hairline);
  background: #fafafa;
  font-size: var(--fs-util);
}

/* «Мои ответы» и «Кейс» — обычные кнопки ШАПКИ (case-ref.js кладёт их первыми
   в .station-header-right). Прежний вариант — вертикальные язычки плавающим
   рельсом у правого края — снят 2026-07-27: на диалоговых раундах справа от
   колонки ответов пусто, и рельс висел в этой пустоте вне композиции, плюс на
   него наезжал скроллбар. Все контролы экрана теперь в одном месте.
   Вид кнопок наследуется от .btn.btn-ghost.btn-sm — своих правил не нужно. */
.hdr-ref-group { display: inline-flex; align-items: center; gap: 8px; }
/* разделитель между справочными кнопками и служебным блоком (?, ⓘ, №) */
.hdr-ref-group::after {
  content: '';
  width: 1px;
  height: 20px;
  background: var(--hairline);
  margin-left: 8px;
}

/* Фолбэк: страница без шапки станции — язычки остаются плавающим рельсом.
   Вертикальная ориентация и тёмный вид живут ТОЛЬКО здесь. */
.dock-rail {
  position: fixed;
  right: max(0px, calc((100vw - var(--maxw)) / 2));
  top: auto;
  bottom: calc(28px + var(--demo-bottom, 0px));
  z-index: 70;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
}
.dock-rail .dossier-dock, .dock-rail .case-ref-dock {
  position: static;
  writing-mode: vertical-rl;
  padding: 16px 7px;
  background: var(--ink);
  color: var(--lime);
  border: none;
  border-radius: 12px 0 0 12px;
  font-family: var(--ff-body);
  font-size: var(--fs-op);
  font-weight: 600;
  letter-spacing: 0.04em;
  cursor: pointer;
}
.dock-rail .dossier-dock:hover, .dock-rail .case-ref-dock:hover { background: var(--lime-dim); color: var(--ink); }
.dock-rail .dossier-dock:focus-visible, .dock-rail .case-ref-dock:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

/* Плавающая кнопка продвижения раунда (снизу-справа): текст и панели скроллятся
   под ней, действие всегда под рукой на длинной странице. position:fixed внутри
   root'а фазы — прячется вместе с ним (display:none). */
/* НЕ ИСПОЛЬЗУЕТСЯ с 2026-07-27: продвижение раунда переехало в поток на всех
   экранах (ревизия единства контролов), плавающих кнопок в разметке не осталось.
   Правило сохранено на случай возврата паттерна; --demo-bottom рядом продолжает
   использоваться язычками. Кандидат на удаление после следующей волны.
   Кнопка прижата не к углу ОКНА, а к правому краю РАМКИ приложения: та же
   центрирующая математика (max-width + margin auto + var(--frame-pad)), что у шапки,
   поэтому по вертикали она встаёт под «← К карте» и не отлетает в пустое поле
   на широком мониторе. Сама полоса-обёртка прозрачна и не перехватывает клики —
   кликабельна только кнопка внутри.
   --demo-bottom задаёт demo.js: снизу в демо-режиме стоят полоса и записка,
   раньше кнопка уезжала прямо под них. Вне демо переменная не задана → 0. */
.round-fab {
  position: fixed;
  left: 0;
  right: 0;
  bottom: calc(24px + var(--demo-bottom, 0px));
  z-index: 60;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 var(--frame-pad);
  display: flex;
  justify-content: flex-end;
  pointer-events: none;
}
.round-fab .btn { box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18); }

/* Справочные кнопки доступны на ВСЕХ рабочих страницах, включая фазу чтения
   раунда 1 (решение 2026-07-27: одинаковые функции — одинаковая механика на
   каждой странице; пустое досье показывает заглушку).
   Пока открыт ящик, прячем ТОЛЬКО фолбэк-рельс (его перекрывал сам ящик).
   Кнопки в шапке НЕ прячем: они не перекрыты, а их исчезновение дёргало шапку
   на ~200px и «съедало» название раунда, пока панель открыта. */
body.imp-drawer-open .dock-rail { display: none; }

.gate-card.case-ref-card { max-width: 820px; }
#caseRefPanel .case-content { margin-top: 8px; }

/* Шпаргалка по лору в панели «Кейс». Свёрнута по умолчанию: тем, кто помнит
   сущности, она не мешает, а искать «кто такая Северова» в 22 тысячах знаков
   больше не нужно. Память на имена ни одна способность не измеряет — это шум. */
.cheat-block {
  margin: 10px 0 4px;
  border: 1px solid var(--hairline);
  border-radius: 10px;
  background: var(--soft);
}
.cheat-block > summary {
  cursor: pointer;
  padding: 10px 14px;
  font-size: var(--fs-op);
  font-weight: 600;
  list-style: none;
}
/* ⚠ СТРОКА «ЧТО МЕРИТ ЭТОТ ШАГ» — ТОЛЬКО ДЕМО (движок рисует её при isDemo).
   Намеренно неяркая и служебного вида: это подпись для фасилитатора, а не часть
   разговора, и спутать её с репликой нельзя. */
.sc-measures {
  margin: -2px 0 14px;
  font-size: var(--fs-op-sm);
  line-height: 1.5;
  color: var(--muted-soft);
  border-left: 2px solid var(--hairline);
  padding-left: 10px;
}
.sc-measures b { color: var(--ink); font-weight: 600; }

/* ══════════════════════════════════════════════════════════════════════════
   ПОЛОСА ДЕМО (18.08, решение владельца)
   Строка «что мерит этот шаг» переехала из-под заголовка вниз: фиксированная
   полоса во всю ширину, вермилион, места хватает на комментарии. Рабочая область
   не перекрывается — engine.js меряет высоту полосы и кладёт её в --demo-chrome
   и --demo-bottom, на которых уже сидят .frame, скролл рабочего тела и плавающие
   кнопки. Вермилион взят литералами семьи --accent* из :root: на body.p-assess
   вся семья подменена голубой, а полоса — хром вокруг продукта, не его часть.
   Участнику она не видна ни при каких условиях: рисуется только при isDemo.
   ══════════════════════════════════════════════════════════════════════════ */
.demo-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 90;
  background: #fff2ec; border-top: 2px solid #ff4800;
  padding: 12px max(16px, calc((100vw - var(--maxw)) / 2 + var(--frame-pad)));
  font-size: var(--fs-op-sm); line-height: 1.5; color: #7a3a22;
  max-height: 42vh; overflow-y: auto;
}
.demo-top { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin: 0 0 7px; }
.demo-tag {
  font-size: var(--fs-util); font-weight: 700; text-transform: uppercase;
  letter-spacing: var(--label-track); color: #fff; background: #ff4800;
  border-radius: 3px; padding: 2px 7px;
}
.demo-step { font-size: var(--fs-read); font-weight: 700; color: #c73500; }
.demo-where { color: #a3705c; }
.demo-p { margin: 0 0 5px; max-width: 92ch; font-size: var(--fs-dense); line-height: 1.55; color: #7a3a22; }
.demo-p b { color: #c73500; font-weight: 700; }
.demo-p-dim { color: #96604a; margin-bottom: 0; }
@media (max-width: 720px) { .demo-bar { max-height: 50vh; } }

.cheat-block > summary::-webkit-details-marker { display: none; }
/* ⚠ ТРЕУГОЛЬНИК — БРЕНД-ФОРМА, НЕ ЮНИКОД (правка владельца 12.08). Символы ▸ и ▾
   рисует шрифт: пропорция своя, вершина скруглена, и рядом со стрелкой futureproof в
   шапке это читалось как другая форма. Геометрия та же, что в логотипе (треугольник
   13×12 с вершиной по середине высоты), заданная clip-path: тогда открытое состояние
   — тот же треугольник, повёрнутый на 90°, а не другой символ. */
.cheat-block > summary::before {
  content: '';
  display: inline-block;
  width: 7px;
  height: 6.5px;
  margin-right: 7px;
  vertical-align: 1px;
  background: var(--muted);
  clip-path: polygon(0 0, 100% 50%, 0 100%);
  transition: transform .12s ease;
}
.cheat-block[open] > summary::before { transform: rotate(90deg); }
.cheat-body { padding: 2px 14px 12px; }
.cheat-h {
  margin: 10px 0 4px;
  font-size: var(--fs-op-sm);
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--muted);
}
.cheat-row {
  display: flex;
  gap: 10px;
  padding: 3px 0;
  font-size: var(--fs-op);
  line-height: 1.45;
  border-top: 1px solid var(--hairline);
}
.cheat-row:first-of-type { border-top: 0; }
.cheat-row b { flex: 0 0 168px; font-weight: 600; }
.cheat-row span { color: var(--muted); }
@media (max-width: 600px) {
  .cheat-row { flex-direction: column; gap: 1px; }
  .cheat-row b { flex: none; }
}

@media (max-width: 600px) {
  /* мобильный: только фолбэк-рельс; в шапке кнопки живут по .btn-sm и переносятся
     вместе с остальным правым блоком (.station-header flex-wrap) */
  .dock-rail .dossier-dock, .dock-rail .case-ref-dock { font-size: var(--fs-util); padding: 12px 6px; }
  /* разделитель после переноса строки выглядел бы висящей чертой — убираем */
  .hdr-ref-group::after { display: none; }
}

/* .dossier-overlay — в отличие от остальных .gate-экранов (полноэкранных,
   взаимоисключающих шагов раунда), эта панель должна уметь появиться ПОВЕРХ
   уже показанного .gate-экрана — например, поверх finishOverlay, где кнопка
   «Мои ответы» тоже есть. Обычный normal-flow .gate для этого не годится:
   оба блока были бы просто показаны один под другим на одной странице. */
.dossier-overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: rgba(10, 10, 10, 0.18);
  display: flex;
  align-items: stretch;
  justify-content: flex-end;
  padding: 0;
  overflow: hidden;
}

.gate-card.dossier-card {
  /* одна ширина у ОБОИХ ящиков («Мои ответы» и «Полный текст кейса»):
     разные ширины читались как разная механика, и более широкий кейс
     перекрывал язычки, когда узкий — нет. 860 — по потребности кейса
     (таблицы); ответы в той же ширине читаются нормально. */
  width: 68%;
  max-width: 860px;
  max-height: none;
  height: 100vh;
  margin: 0;
  border-radius: 0;
  box-shadow: -12px 0 40px rgba(0, 0, 0, 0.12);
  display: flex;
  flex-direction: column;
  overflow-y: auto; /* фолбэк: если внутренняя область не скроллится сама */
}
@media (max-width: 900px) {
  .gate-card.dossier-card { width: 100%; max-width: none; }
}
.dossier-card-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
}
.dossier-card .fac-detail-body {
  flex: 1;
  overflow-y: auto;
  padding: 0;
  margin-top: 18px;
}/* единое видимое фокус-кольцо для клавиатурной навигации (WCAG 2.4.7) — доборка к точечным :focus-visible */
.btn:focus-visible, a.hub-room-card:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.finalize-actions .btn-primary { flex: 1; }

@media (max-width: 600px) {  .finalize-actions .btn { width: 100%; }
}

.consent {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  margin: 26px 0 28px;
}

.consent input {
  margin-top: 3px;
  flex: none;
  width: 18px;
  height: 18px;
  accent-color: var(--ink);
}

.consent label {
  font-size: var(--fs-op);
  line-height: 1.5;
  color: var(--muted);
}
.device-warning.show { display: flex; }

.form-error {
  font-size: var(--fs-op);
  color: #c4362b;
  margin-top: -10px;
  margin-bottom: 16px;
  display: none;
}

.form-error.show { display: block; }

.confirm {
  display: none;
  text-align: left;
}

.confirm.show { display: block; }

.confirm .big-check {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--lime);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--fs-op-xl);
  margin-bottom: 20px;
}

.confirm h2 { margin-bottom: 12px; }
.confirm p { color: var(--muted); font-size: var(--fs-op-h); line-height: 1.6; margin-bottom: 28px; }
.round-card.round2 { background: var(--ink); color: var(--paper); }
.round-card.round2 .round-meta { color: #b9bbbe; }
.round-card.round2 p { color: #c7c9cc; }
.round-card.round2 .round-meta { border-top-color: #2a2b2e; }

/* ---------- route: 6 stations of round 1 ---------- */

.route {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0;
}

.route::before {
  content: '';
  position: absolute;
  left: 23px;
  top: 8px;
  bottom: 8px;
  width: 2px;
  background: repeating-linear-gradient(to bottom, var(--ink) 0 6px, transparent 6px 12px);
}
.tag {
  font-size: var(--fs-util);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 4px 9px;
  border-radius: 999px;
  border: 1px solid #d8dadd;
  color: var(--muted-soft);
  white-space: nowrap;
}

.tag.tag-key { border-color: var(--hairline); background: var(--soft); color: var(--ink); }
.tag.tag-moves { border-color: #d8d2f5; background: #f5f2ff; color: #6247aa; }
.tag.tag-none { border-color: #e5e5e5; background: #fafafa; color: var(--muted-soft); }
.role {
  background: var(--paper);
  padding: 22px 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-height: 170px;
}

.role .role-tag {
  font-family: var(--ff-display);
  font-weight: 900;
  font-size: var(--fs-op-h);
}

.role p {
  font-size: var(--fs-util);
  line-height: 1.5;
  color: var(--muted);
  margin: 0;
}
.axis {
  background: var(--paper);
  padding: 18px 22px;
  display: grid;
  grid-template-columns: 1fr 2fr;
  gap: 18px;
  align-items: center;
}

.axis .axis-name {
  font-size: var(--fs-op);
  font-weight: 700;
}

.axis .axis-opts {
  font-size: var(--fs-op);
  color: var(--muted);
}

.axis .axis-opts b { color: var(--ink); font-weight: 600; }
.timing-row .t-min { font-weight: 700; font-family: var(--ff-display); }
/* Номер участника. Базовое правило осталось с до-редизайна (30px, радиус 12px,
   рамка 3px) и переопределялось только в шапках раундов и Р6 — а в карточке
   кабинета применялось как есть: номер шёл огромным блоком и наезжал на
   «Обновить». Приводим базу к системе; scoped-правила теперь совпадают с ней. */
.bib {
  font-family: var(--ff-display);
  font-weight: 900;
  font-size: var(--fs-dense);
  background: var(--ink);
  color: var(--lime);
  border: 1px solid var(--ink);
  border-radius: var(--radius);
  padding: 6px 12px;
  letter-spacing: 0.02em;
  white-space: nowrap;
}
.board-tab.active { color: var(--ink); background: var(--soft); }
/* ---------- station screen (round 1 stations) ---------- */

.gate {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--paper);
  padding: 24px;
}

/* переход перед комнатами — структурно самый крупный стык раунда 1
   (конец эталонных станций, начало рубрики ходов), поэтому темнее и
   тяжелее остальных лёгких gate-экранов */
/* Финиш-оверлей раунда — светлый брендовый экран (по утверждённому макету
   станции 3): белый лист, вермилионовый kicker-«галочка», дисплей-заголовок,
   письмо Агеева editorial-курсивом. Тёмная «арена»-версия убрана. */
.gate-finish { background: var(--paper); }
.gate-finish .gate-card .kicker { color: var(--accent); }

.gate-card {
  background: var(--paper);
  border-radius: var(--radius);
  padding: 44px 40px;
  /* 420px рвали заголовки финиш-экранов («Дашу зовут к стойке» переносилось) и
     резали баблы прощания на строки по четыре слова. 560 — заголовок в одну
     строку, а карточка всё ещё уже колонки чтения (--w-read), т.е. не превращается
     в полосу текста. */
  max-width: 560px;
  width: 100%;
}
/* h2 в gate-карточках имел margin:0 (общий сброс), а тексты под ним — mt:0,
   поэтому заголовок склеивался со следующим абзацем на всех gate/финиш-экранах.
   Один отступ здесь чинит везде. Элементы с инлайновым margin (напр. h2 в шапке
   досье) не затрагиваются — инлайн специфичнее. */
.gate-card h2 { margin: 0 0 16px; }

.station-frame {
  padding: 0;
  border-width: 0;
  /* та же поправка на хром демо, что у .station-shell: min-height:100vh поверх
     padding'ов body давал странице лишние 77px и уводил шапку при скролле */
  min-height: calc(100vh - var(--demo-chrome, 0px));
}

.station-shell {
  display: flex;
  flex-direction: column;
  /* минус хром демо (--demo-chrome ставит demo.js): иначе 100vh + padding'и body
     делали страницу выше экрана, она скроллилась целиком и шапка уезжала вверх
     вместе со справочными кнопками. Вне демо переменной нет → чистые 100vh. */
  height: calc(100vh - var(--demo-chrome, 0px));
  background: var(--paper);
  /* система координат для экрана легенды (.station-intro) — см. комментарий там */
  position: relative;
}

.station-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  /* боковой отступ — тот же var(--frame-pad), что у тела раунда: иначе лого в
     шапке не встаёт по левому краю колонки контента (было 24 против 32 = разъезд 8px) */
  padding: 14px var(--frame-pad);
  /* Подстраховка: если страница всё же прокрутится (низкий экран, чужой хром),
     шапка остаётся на месте — справочные кнопки и номер должны быть достижимы
     из любой точки, это было главное достоинство прежних плавающих язычков. */
  position: sticky;
  top: 0;
  z-index: 75;
  /* ⚠ ФОН ОБЯЗАТЕЛЕН ПРИ sticky. Его тут не было, и содержимое страницы при
     прокрутке уезжало ПОД шапку и просвечивало сквозь лого, номер и кнопки.
     Видно на всех экранах со station-header: ассессмент, кабинет, харнесс,
     разбор описаний. Токен тот же, что у .frame, — иначе шапка читалась бы
     наклейкой поверх страницы, а не её краем. */
  background: var(--paper);
  /* был литерал #ececec — параллельный hairline на пять единиц светлее токена.
     Под шапкой дня он стоял вплотную к border-top у .day-grid, и стык читался
     двойной линией из двух разных серых (DESIGN.md стр. 128: глубина — только
     hairline, одной). */
  border-bottom: 1px solid var(--hairline);
  flex: none;
  /* единая рамка: шапка той же ширины, что и контент (var(--maxw)), по центру —
     чтобы на всех экранах шапка и рабочая область совпадали по ширине */
  max-width: var(--maxw);
  width: 100%;
  margin: 0 auto;
}

.station-header-left {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}

.station-header-left .logo { font-size: var(--fs-logo); }

.station-sep { color: var(--muted-soft); }

.station-name {
  font-size: var(--fs-dense);
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin: 0; /* сбрасываем дефолтные поля h1 — это визуально метка в шапке */
  /* ⚠ И max-width ТОЖЕ СБРАСЫВАЕМ (найдено 25.08). Общее правило h1 ставит
     max-width: 16ch — мера строки для крупного заголовка страницы. Здесь h1 по
     разметке, но по смыслу это метка в шапке, и шестнадцать знаков её режут.
     Прежний текст «Искра» · ассессмент стоял ровно на этой границе (147px из 147),
     поэтому обрезки не было видно; полное имя дня уехало в «Ассессмент стратег…».
     Обрезка по месту остаётся: nowrap + ellipsis выше и min-width:0 у родителя —
     на узком экране заголовок укорачивается сам, но не по числу знаков. */
  max-width: none;
}

.station-header-right {
  display: flex;
  align-items: center;
  gap: 16px;
  flex: none;
}

.station-hint {
  font-size: var(--fs-util);
  color: var(--muted-soft);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  white-space: nowrap;
}

/* На узком экране правый блок шапки не помещается рядом с несжимаемым
   логотипом и наезжал на него — разрешаем перенос на вторую строку. */
@media (max-width: 600px) {
  /* шапка переносится на две строки, поэтому она выше — легенда должна лечь под неё */
  :root { --hdr-h: 96px; }
  .station-header { flex-wrap: wrap; row-gap: 8px; padding: 12px var(--frame-pad); }
  /* Счётчик участников на мобиле избыточен (то же видно в списке) —
     убираем, чтобы логотип и «Обновить» уместились в одну строку. */
  #facCount { display: none; }
}
.station-intro-inner .kicker { margin-bottom: 10px; }

/* ══════════════════════════════════════════════════════════════════════════
   БЕЛЫЙ ЛИСТ «ВВЕДЕНИЕ В РОЛЬ» (решение владельца 25.08)
   Первое, что участник видит внутри ассессмента: над листом шапка дня, под
   заголовком — роль, справа внизу переход к материалам. Лист занимает место тела
   (flex:1) и потому сам встаёт ровно ниже шапки и выше полосы демо, без замеров.
   Тело дня при этом скрыто, а не перекрыто: перекрытие требовало бы z-index и
   знания высоты шапки, а она разная в демо и вне его.
   Мера строки — как у чтения материалов: роль читают, а не сверяются с ней.
   ══════════════════════════════════════════════════════════════════════════ */
.role-sheet {
  flex: 1; min-height: 0; overflow-y: auto; background: var(--paper);
  display: flex; align-items: center; justify-content: center;
  padding: 40px var(--frame-pad);
}
/* ⚠ МЕРА ШИРЕ ЧТЕНИЯ КЕЙСА, И ЭТО НАМЕРЕННО. --w-read (60ch) рассчитан на колонку
   рядом с другими колонками; здесь на экране нет ничего, кроме этого текста, и узкая
   мера превращала два абзаца в рваную ленту (правка владельца 25.08: «текст плывёт,
   надо дать больше воздуха»). 80ch — уже принятая в этой системе ширина, не выдумка.
   Воздух добавлен не кеглем, а интерлиньяжем и отступом между абзацами: кегль чтения
   в продукте один (--fs-read), и роль не повод разводить второй. */
.role-sheet-in { width: 100%; max-width: 80ch; }
.role-sheet-t {
  /* ⚠ КАПС И ВЫКЛЮЧКА ВЛЕВО — как у заголовков двух экранов до старта (.intro-hero h1).
     Было: строчными и по центру. Капс я просто забыл, а центр оказался хуже по делу:
     короткий заголовок над выключенным влево текстом не даёт общей кромки, и блок
     читается как съехавший (замечание владельца 25.08). Одна левая кромка у заголовка
     и текста — и «в центре экрана» остаётся верно про сам блок: его центрирует лист. */
  margin: 0 0 26px; text-align: left;
  font-family: var(--ff-display); font-weight: 800; font-size: var(--fs-hero);
  text-transform: uppercase; letter-spacing: -0.015em; line-height: 1.02;
  color: var(--ink); max-width: none;
}
/* ⚠ display ВОЗВРАЩАЕМ ЯВНО. Блок .read-role скрыт по умолчанию и показывается
   только внутри .day-grid.is-reading — он заводился как врезка над пакетом. У листа и
   у вкладки своего .is-reading нет, поэтому текст роли приезжал пустым (поймано на
   первом же прогоне). Мера строки снимается там же: её задаёт лист и вкладка. */
.role-sheet-body .read-role, #supRole .read-role { display: block; max-width: none; }
/* ⚠ СЕЛЕКТОР С .read-role ВНУТРИ — НЕ ЛИШНЕЕ ЗВЕНО. Правило .read-role p стоит в этом
   файле НИЖЕ и при равной специфичности перебивало интерлиньяж и отступы (замер: ждали
   28px, получали 25,92px — то есть 1,62 из .read-role). Здесь нужен вес больше, а не
   !important: важность спрятала бы конфликт вместо того, чтобы его назвать. */
.role-sheet-body .read-role p {
  font-size: var(--fs-read); line-height: 1.75; color: var(--ink); margin: 0 0 1.15em;
  /* Рваный правый край выравнивает браузер: без этого строки кончались на очень разной
     длине, и абзац читался «плывущим». Где не поддерживается — просто обычный перенос. */
  text-wrap: pretty;
}
.role-sheet-body .read-role p:last-child { margin-bottom: 0; }
/* Приписка про пакет («что лежит ниже») остаётся служебной и в листе: она не часть
   рассказа о роли, а подпись к переходу, который стоит сразу под ней. */
.role-sheet-body .read-role .read-role-lead { color: var(--muted); }
/* ⚠ РЯД ПОДВАЛА: ЗАПИСКА СЛЕВА, КНОПКА СПРАВА (правка владельца 25.08). Оговорка про
   вымышленность материалов переехала сюда со второй страницы: её место — там, где
   кончается рассказ о роли и начинается сам кейс, а не среди объяснений устройства.
   Геометрия та же, что у ряда действия в разговоре и на экранах до старта: главное
   действие у правого края, служебная строка слева.
   Линейку над рядом рисует .read-role (border-bottom) — своей здесь не заводим. */
.role-sheet-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  margin-top: 22px;
}
.role-sheet-note { margin: 0; font-size: var(--fs-util); color: var(--muted-soft); max-width: 52ch; }
.role-sheet-foot .btn { flex: none; }
/* ⚠ ТЕЛО ДНЯ — .day-grid, А НЕ .station-body. Второе есть у экранов станции, а в
   ассессменте под шапкой лежит именно сетка дня (поймано замером: у оболочки дети
   HEADER, лист и DIV.day-grid). Ошибка селектора оставляла день видимым под листом. */
.station-shell.is-role .day-grid { display: none; }

.station-body {
  flex: 1;
  display: grid;
  /* навигация у́же, колонка чтения кейса получает больше веса, чем рабочая область
     (та полупустая, пока нет карточек) — иначе на ноутах чтение жалось при делении 1:1. */
  /* 226px + отступ рамки: колонка навигации шире ровно на тот отступ, который
     .case-nav отдаёт слева под выравнивание с лого — полезная ширина ссылок
     остаётся прежней (212px), а текст встаёт по колонке контента. */
  grid-template-columns: calc(226px + var(--frame-pad)) minmax(0, 1.5fr) minmax(0, 1fr);
  min-height: 0;
  /* та же рамка, что у шапки и прочих экранов */
  max-width: var(--maxw);
  width: 100%;
  margin: 0 auto;
}
/* меньшие ноуты (до слома в 1 колонку на 980): ещё у́же навигация, ещё больше чтению */
@media (max-width: 1180px) {
  .station-body { grid-template-columns: calc(196px + var(--frame-pad)) minmax(0, 1.6fr) minmax(0, 1fr); }
}
.case-nav {
  border-right: 1px solid #ececec;
  /* левый отступ = var(--frame-pad), тот же, что у шапки: иначе «Материалы» стоят
     левее лого над ними. Ширина самой колонки увеличена на ту же величину
     (см. .station-body), поэтому полезная ширина ссылок не теряется. */
  padding: 20px 14px 20px var(--frame-pad);
  overflow-y: auto;
  font-size: var(--fs-op);
}

.case-nav-title {
  font-size: var(--fs-op-sm);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted-soft);
  padding: 6px 10px 4px;
}
/* Группы оглавления отделены волоском — так же, как «Справка по терминам»
   отделена от приложений. Без него список из семнадцати ссылок читался одним
   потоком, и было не видно, где кончается обращение к читателю, где сам пакет,
   а где приложения. Линию получает любой заголовок, ПЕРЕД которым уже есть
   ссылки; самый первый элемент списка её не получает — над ним ничего нет. */
.case-nav-link ~ .case-nav-title {
  margin-top: 16px;
  border-top: 1px solid var(--hairline);
  padding-top: 14px;
}

/* «Справка по терминам» — отдельный блок в самом низу навигации: это служебный
   справочник, не приложение кейса. Текст — в стиле заголовков групп
   (МАТЕРИАЛЫ / ПРИЛОЖЕНИЯ), но остаётся ссылкой: hover и отметка «прочитано» (✓)
   наследуются от .case-nav-link. */
.case-nav-link.case-nav-ref {
  margin-top: 14px;
  border-top: 1px solid var(--hairline);
  padding-top: 12px;
  font-size: var(--fs-op-sm);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted-soft);
  border-radius: 0;
}

.case-nav-link {
  display: block;
  padding: 8px 10px;
  border-radius: 8px;
  text-decoration: none;
  color: var(--muted);
  line-height: 1.35;
  font-size: var(--fs-op);
}

.case-nav-link:hover { background: #f5f5f5; color: var(--ink); }

.case-nav-link.is-partial {
  color: var(--ink);
}

.case-nav-link.is-partial::after {
  content: '·';
  float: right;
  font-weight: 900;
  color: var(--accent);
}

.case-nav-link.is-opened {
  color: var(--ink);
  font-weight: 600;
}

.case-nav-link.is-opened::after {
  content: '✓';
  float: right;
  color: var(--lime-dim);
}

/* .case-nav-progress удалён 2026-07-27: элемента #appxProgress в разметке нет —
   счётчик «N/8 приложений» убран намеренно, «изучено» трекается для кабинета. */

/* средняя колонка: вкладки сверху, под ними прокручиваемый текст или заметки */
.case-main {
  display: flex;
  flex-direction: column;
  min-height: 0;
  border-right: 1px solid #ececec;
}
.case-tab.is-active {
  color: var(--ink);
  border-bottom-color: var(--ink);
}
.case-content {
  overflow-y: auto;
  padding: 32px 40px 20px;
  flex: 1;
}
/* Потолок читаемой ширины кейса: на очень широких экранах строки не растягиваются
   в нечитаемо длинные; на ноутах колонка уже потолка — правило не мешает. */
/* та же ширина чтения, что в раундах 2–5: на широком мониторе колонка кейса
   вырастает, но строка держится в --w-read (60ch с 04.08) */
.case-content article { margin-bottom: 40px; max-width: var(--w-read); }

.case-content h2 {
  font-family: var(--ff-display);
  font-size: var(--fs-logo);
  font-weight: 800;
  margin: 0 0 16px;
}
.case-content p {
  font-size: var(--fs-dense);
  line-height: 1.68;
  color: var(--muted);
  margin: 0 0 14px;
}

.case-content p b { color: var(--ink); }
blockquote.letter, blockquote.dialogue {
  margin: 0 0 14px;
  padding: 18px 22px;
  background: #fafafa;
  border: 1px solid var(--hairline);
  border-radius: 12px;
}

blockquote.letter p, blockquote.dialogue p { font-size: var(--fs-dense); margin: 0 0 12px; }
blockquote.letter p:last-child, blockquote.dialogue p:last-child { margin-bottom: 0; }
/* ── ЗАГОЛОВОК ПАКЕТА И ЗАГОЛОВОК ПРИЛОЖЕНИЙ ──
   ⚠ ЛИНИЯ ПОД ЗАГОЛОВКОМ, А НЕ НАД (правка владельца 28.08). Она стояла сверху с
   пометкой 07.08 «под разделителем сразу идёт первый раздел со своей линейкой —
   получались две линии с пустотой». Довод верный, но выбрана была не та линия:
   заголовок называет то, что идёт ЗА ним, и черта его открывает, как шапку таблицы.
   Сверху заголовок оказывался под чертой — оторванным от своего списка и приклеенным
   к чужому. Тот же разбор владелец сделал 28.08 для заголовков блоков справки
   (.who-h), и правило здесь то же: паузу между блоками держит увеличенный отступ
   сверху, а не линия. Двойной линии не возникает: полоса действий ниже отбивает
   черту от первой свёртки.
   ⚠ КЕГЛЬ ВЫШЕ ПОДЗАГОЛОВКОВ (та же правка). Стоял --fs-util, 12px, — то есть
   заголовок пакета был ВДВОЕ тише названий разделов под ним (те берут кегль тела
   кейса, 16px). Это вторая настоящая роль ступени --fs-lead: её комментарий в шкале
   просит проверить, нужна ли она где-то ещё, — нужна. 20px против 16px у детей. */
.appx-divider {
  font-family: var(--ff-display);
  font-weight: 900;
  font-size: var(--fs-lead);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--muted-soft);
  margin: 34px 0 0;
  padding-bottom: 8px;
  border-bottom: 2px solid var(--ink);
}
.appx-divider:first-child { margin-top: 0; }
/* ── «РАЗВЕРНУТЬ ВСЁ» / «СВЕРНУТЬ ВСЁ» — СВОЯ СТРОКА ПОД ЧЕРТОЙ ──
   Решение владельца 28.08: «развернуть и свернуть всё нужно оставить под этой чертой,
   и отдельно на приложения и текст кейса сделать». С 25.08 действия жили в строке
   заголовка справа, и пара была одна на весь документ — «развернуть всё» открывало
   и семь разделов, и десять приложений разом, хотя приложения намеренно свёрнуты
   (правка 07.08). Теперь пара своя у каждого из двух блоков и стоит под его чертой:
   действие принадлежит списку, а не заголовку. Строки вставляет engine.js — кейс
   правится только новой версией файла. */
.case-acts { display: flex; gap: 14px; margin: 10px 0 20px; }

/* appendices read as distinct attached documents you open on purpose —
   collapsed by default, so a stray scroll can't silently "read" one for you */

.appx-doc {
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  margin-bottom: 22px;
  background: var(--paper);
}

.case-content article[id^="appx-"]:last-of-type .appx-doc { margin-bottom: 0; }

/* Приложения кейса v6 раскрыты по умолчанию: не <details>, а обычная секция с
   шапкой. Ни раскрытия, ни статуса прочтения здесь нет сознательно — и то и
   другое было сигналом, который у человека и у модели устроен по-разному (модели
   кейс приходит целиком в system, «открыть приложение» у неё не событие), а
   значит мерило браузер, а не мышление. Классы .appx-doc-badge / .appx-sentinel
   и правила для summary УДАЛЕНЫ 12.08: они держались «пока живы старые раунды», а
   round1…round5.html не существует с переезда на imp.v3. Внутри жил последний юникодный
   «▾» продукта — и он никому не показывался, потому что <summary> в кейсах нет ни одного. */
.appx-doc-open > .appx-doc-head {
  padding: 20px 24px;
  display: flex;
  align-items: center;
  gap: 12px;
  border-bottom: 1px solid #ececec;
  font-family: var(--ff-display);
  font-weight: 800;
  font-size: var(--fs-read);
}

.appx-doc-open > .appx-doc-head::before {
  content: '📎';
  font-size: var(--fs-dense);
  flex: none;
}

.appx-doc-open > .appx-doc-head h3 {
  margin: 0;
  font-size: var(--fs-read);
}

.appx-body {
  padding: 22px 24px 26px;
}
.tbl-wrap { overflow-x: auto; margin: 14px 0; }

table {
  border-collapse: collapse;
  width: 100%;
  font-size: var(--fs-op);
}

table th, table td {
  border: 1px solid #ececec;
  padding: 8px 10px;
  text-align: right;
  white-space: nowrap;
}

table th:first-child, table td:first-child {
  text-align: left;
  white-space: normal;
  min-width: 180px;
  color: var(--ink);
}

table th { background: #fafafa; font-weight: 700; }

/* ---------- отметка в кейсе ↔ цитата в карточке: один объект, один материал ----------
   Связь несёт КРАСКА: бледная заливка плюс вермилионовый штрих под словами. Это
   буквально одно объявление на оба конца — разъехаться при будущих правках им негде.
   Раньше общего не было ничего: в тексте плашка с рамкой, в карточке серая строка
   в ёлочках, и связь приходилось додумывать.

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

   Штрих сделан text-decoration, а не рамкой: он сам рисуется на каждой строке
   переноса и не трогает метрику строки. Прежняя inset-тень замыкалась на каждом
   строчном фрагменте — фраза, перенесённая на три строки, выглядела как три
   отдельные отметки. box-decoration-break намеренно по умолчанию (slice): при
   clone каждая строка получила бы свои скругления и снова читалась бы отдельно.

   Штрих несущий, а не украшение: заливка к бумаге даёт 1.1:1, сама по себе
   отметка глазом не находится. Толщину и --accent не менять без пересчёта 1.4.11
   (вермилион к бумаге 3.4:1, к заливке 3.1:1). */
mark.hl, .card .problem-quote .quote-ink {
  background: var(--accent-tint);
  text-decoration: underline var(--accent) 2px;
  text-underline-offset: 3px;
  /* padding даёт краске воздух, отрицательный margin возвращает его разметке.
     Без компенсации отметка в ячейке двигала колонку — из-за этого и существовало
     исключение `table mark.hl { padding: 0 }`. Причина снята, поэтому снято и
     исключение: метка в таблице теперь выглядит так же, как в абзаце. */
  padding: 1px 2px;
  margin: 0 -2px;
  border-radius: var(--radius);
}

/* В кейсе отметка поднимает фразу до полного ink — видно, что фраза «взята».
   cursor: pointer, а не grab: перетаскивания в раунде 1 не существует (ни
   draggable, ни dragstart), а клик ведёт к карточке. Одинаковое поведение на
   обоих концах связи обязано иметь одинаковый курсор. */
mark.hl {
  color: var(--ink);
  cursor: pointer;
}

/* Внутри отметки может оказаться ссылка на приложение, а у неё своё ink-подчёркивание.
   Два подчёркивания в два яруса читаются как дефект вёрстки: внутри отметки линию
   несёт отметка. */
mark.hl .appx-ref { text-decoration: none; }

/* Наведение — та же краска, просто плотнее: ни outline, ни второй рамки.
   color: ink здесь не косметика, а требование — --muted на --accent-line даёт 3.85:1. */
mark.hl:hover, .card .problem-quote:hover .quote-ink {
  background: var(--accent-line);
  color: var(--ink);
}

/* Вспышка «вот этот фрагмент» — один язык на обоих концах связи. Раньше их было
   полтора: чёрный контур у отметки и НИЧЕГО у карточки — правила .problem-card.flash
   в CSS не существовало, хотя round1.js вешает класс на 900 мс. Половина
   двусторонней связи просто не рисовалась, и это читалось как «связь односторонняя».
   У кадров задан только from: краска наливается вермилионом и оседает до
   собственной заливки — пик заметен, пятна на экране не остаётся. 900 мс совпадает
   с таймерами в round1.js (менять только парой). */
@keyframes imp-hl-flash {
  from { background-color: var(--accent); }
}
mark.hl.flash, .problem-card.flash .problem-quote .quote-ink {
  color: var(--ink);   /* 5.2:1 на вермилионе — вспышка остаётся читаемой */
  animation: imp-hl-flash 900ms ease-out;
}
@media (prefers-reduced-motion: reduce) {
  mark.hl.flash, .problem-card.flash .problem-quote .quote-ink {
    animation: none;
    background: var(--accent-line);
  }
}
.rationale-block textarea, .card textarea, .card input[type="text"] {
  width: 100%;
  font-family: var(--ff-body);
  font-size: var(--fs-dense);
  padding: 10px 12px;
  border: 1.5px solid #d8dadd;
  border-radius: 10px;
  background: var(--paper);
  color: var(--ink);
  resize: vertical;
}

.rationale-block textarea:focus, .card textarea:focus, .card input[type="text"]:focus, .card select:focus {
  outline: none;
  border-color: var(--ink);
}
.fork-options .consent { margin: 0; }
.card {
  border: 1px solid #ececec;
  border-radius: 14px;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  position: relative;
}
/* Цитата-источник в карточке проблемы. Своего правила не было, поэтому blockquote
   брал браузерный дефолт margin:1em 40px — отсюда лишний воздух и сдвиг вправо
   относительно метки и поля под ним (ср. blockquote.letter/.dialogue, где UA-отступ
   тоже занулён явно). Цитата — это опора, а не главное в карточке: формулировка
   участника важнее, поэтому она компактнее и тише. */
/* Цитата несёт ТОТ ЖЕ материал, но не тот же голос: 13px и --muted (4.57:1 на
   заливке — AA проходит) против 16px ink в кейсе. Материал делает связь очевидной,
   кегль и цвет удерживают цитату на вторых ролях — главное в карточке формулировка
   участника. Приглушать до --muted-soft нельзя: на заливке это 4.28:1.
   align-self: краска обнимает фразу, а не растягивается на всю колонку.
   line-height 1.7 вместо 1.45 — при 1.45 штрих первой строки почти касается второй. */
.card blockquote.problem-quote {
  margin: 0;
  align-self: flex-start;
  max-width: 100%;
  font-size: var(--fs-op);
  line-height: 1.7;
  color: var(--muted);
  cursor: pointer;
}

/* «Вывод без цитаты» краски не несёт СОЗНАТЕЛЬНО: в тексте нет фразы, к которой
   он вёл бы, и клик никуда не ведёт — отсутствие материала здесь и есть смысл
   строки. Раньше два вида карточек были почти неотличимы. */
.card .problem-quote-none {
  margin: 0;
  font-size: var(--fs-util);
  line-height: 1.45;
  color: var(--muted-soft);
  font-style: italic;
}

/* Поля в карточках растут под текст: при rows="2" третья строка уходила во
   внутренний скролл, и участник не видел целиком то, что сам написал.
   Высоту выставляет JS (growTextarea), здесь — нижняя граница и отсутствие
   собственной полосы прокрутки. */
.card textarea {
  overflow-y: hidden;
  min-height: 68px;
}

.card label {
  display: block;
  font-size: var(--fs-op-sm);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted-soft);
  margin-bottom: 5px;
}
.card.is-locked textarea, .card.is-locked input, .card.is-locked select { background: #fafafa; pointer-events: none; }
.sel-toolbar.show { display: flex; }
.hl-popover.show { display: block; }
.card input[data-field="anchor"].is-drop-target {
  border-color: var(--lime-dim);
  background: var(--soft);
}

/* ---------- facilitator cabinet ---------- */

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

/* «в процессе» — вермилион (текущее/активное); «завершена» — НЕЙТРАЛЬНАЯ,
   чтобы участник не читал её как оценку (см. решение по станции 3). */
/* пилюля-предупреждение (кросс-контроль выше своей комнаты и т.п.) — вермилион */
/* карточка задания/комнаты, требующая внимания судьи: вермилионовая полоса слева
   + тёплая шапка — видно СРАЗУ, куда листать (не только флаг в конце) */

/* ---- отметки на ОСНОВНОМ списке (не только в карточке) ---- */
/* панель «откуда вывод об ИИ-помощи» в карточке */
.ai-sig { display: flex; flex-direction: column; gap: 2px; margin-top: 4px; }
.ai-sig-row { display: grid; grid-template-columns: 140px minmax(0, 1fr); gap: 4px 12px; align-items: baseline; padding: 5px 0; border-bottom: 1px solid var(--hairline); }
.ai-sig-k { font-size: var(--fs-util); font-weight: 600; color: var(--muted); }
.ai-sig-v { font-size: var(--fs-op); font-weight: 600; color: var(--ink); }
.ai-sig-h { grid-column: 2; font-size: var(--fs-util); color: var(--muted-soft); }

/* Разбор участника — боковой drawer: панель справа, список слева остаётся виден. */
/* зоны в «Управлении»: Доступ (обычная) + Сброс/Удаление (боксы-деструктив) */

.fac-detail-body {
  padding: 24px 28px 32px;
  overflow-y: auto;
}

.fac-detail-body h4 {
  font-size: var(--fs-op);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted-soft);
  margin: 24px 0 12px;
}

.fac-detail-body h4:first-child { margin-top: 0; }

.fac-detail-text {
  font-size: var(--fs-op);
  line-height: 1.6;
  color: var(--muted);
  margin: 0;
}

/* Блок кнопки «Сформировать отчёт» в карточке участника — кнопка + пояснение. */

.fac-detail-loading {
  font-size: var(--fs-op);
  color: var(--muted-soft);
  text-align: center;
  padding: 40px 0;
}

/* Компактная разбивка по навыкам в строке списка */

/* флаг-нарушение — настоящее предупреждение, остаётся акцентным */

/* «Ход раунда» (мониторинг) vs «Регистрации и потоки» (админ-задачи) —
   разный темп работы, поэтому разнесены, а не разложены колонками в одной строке. */

/* компактный статус на станцию — точка + инициал, полная расшифровка в title
   и в карточке участника по клику, не здесь */

/* Не-цветовой признак статуса (WCAG 1.4.1): форма-глиф в дополнение к цвету. */      /* ✓ */  /* ◐ */      /* ○ */

/* ---------- responsive ---------- */

@media (max-width: 980px) {  .skills { grid-template-columns: repeat(2, 1fr); }
  .skill { min-height: 0; }  .steps { grid-template-columns: 1fr; }  .axis { grid-template-columns: 1fr; gap: 4px; }
  /* minmax(0, 1fr), а не 1fr: у «1fr» минимум = auto, поэтому дорожка растягивалась
     до min-content навигации (391px в окне 375) и колонка вылезала за экран —
     station-body прятал это во внутренний горизонтальный скролл. */
  .station-body { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto 1fr 1fr; overflow-y: auto; }
  .case-nav { border-right: none; border-bottom: 1px solid #ececec; }
  .case-content { border-right: none; border-bottom: 1px solid #ececec; }
}

@media (max-width: 600px) {
  .wrap { padding: 0 20px; }
  .skills { grid-template-columns: 1fr 1fr; }  .nav { flex-wrap: wrap; row-gap: 10px; }  .nav-links a:not(.btn) { display: none; }
  .nav-links .btn { padding: 8px 14px !important; }}

/* Низкие экраны (ноуты ~768px по высоте): ужимаем вертикальные отступы шапки,
   вступлений, гейтов и верх контента, чтобы плотные экраны меньше требовали скролла.
   В конце файла — чтобы перебить базовые правила (напр. .case-content ниже по исходнику). */
@media (max-height: 760px) {
  /* ужимается только ВЕРТИКАЛЬ; боковой отступ остаётся var(--frame-pad) — иначе
     шапка и тело снова разъезжаются по левому краю (было 24 против 32). */
  :root { --hdr-h: 58px; } /* шапка ниже из-за padding 8px — легенда должна лечь ровно под неё */
  .station-header { padding: 8px var(--frame-pad); }
  .gate-card { padding: 26px 34px; }  .case-content { padding: 18px 40px 16px; }
}

/* ── Чат-формат диалоговых раундов (3 и 5) ────────────────────────────────
   Раунды 3 и 5 — чистые разговоры без структурных полей, поэтому они читаются
   как переписка: реплика собеседника слева, ответ участника справа, ввод снизу.
   Ответ, отданный собеседнику, превращается в баббл и больше не редактируется —
   необратимость раунда становится видимой, а не только описанной в легенде. */
.chat { display: flex; flex-direction: column; gap: 14px; }
/* В раунде 4 каждая реплика — свой .chat (между ними идёт форма), поэтому gap
   внутри контейнера их не разделяет: нужен внешний отступ, иначе подпись второй
   реплики прилипает к пузырю первой. */
.chat + .chat { margin-top: 0; }
.chat { margin-bottom: 20px; }            /* перед формой нужен воздух */
.chat:has(+ .chat) { margin-bottom: 8px; } /* между репликами — теснее */
/* ⚠ ПРОДОЛЖЕНИЕ ТОГО ЖЕ ГОЛОСА — тот же зазор, что между пузырями одной реплики.
   Снимаем сверху, а не задаём снизу: зазор принадлежит margin-bottom предыдущего
   блока, а тот лежит в своём .s2-block и селектором отсюда не достаётся. Число —
   пара к зазору между голосами: замер 21.08 — между разными голосами 26px, между
   пузырями одного голоса внутри реплики 8px, значит снять надо 18. Меняется только
   вместе с margin-bottom выше. */
.chat.is-cont { margin-top: -18px; }
/* ⚠ ПУЗЫРЬ ПО РАЗМЕРУ РЕПЛИКИ (правка владельца 19.08). Ширина была ровно 76%
   у любой строки, и короткое «Бывает.» растягивалось в ту же полосу, что абзац. */
.chat-msg { max-width: 76%; width: fit-content; }
.chat-msg.them { align-self: flex-start; }
.chat-msg.me { align-self: flex-end; }
/* Имя персонажа — метка (DESIGN.md стр. 157 «имя-метка»), поэтому размер, вес и
   разрядка приходят из единого рецепта метки. До 04.08 здесь стояло 13px/700/0.06em
   с обоснованием «тот же шаг, что у .chat-note и .chat-act рядом»; после сведения
   имя стало мельче ремарки — и это правильно: ремарка это проза, имя это метка. */
.chat-name {
  display: block;
  margin: 0 0 4px 2px;
}
.chat-msg.me .chat-name { text-align: right; margin-right: 2px; }
/* Служебное — ВНЕ пузыря: в пузыре только прямая речь. Уточнение, кто это, —
   обычным текстом в скобках; действие и реакция — курсивом. Иначе ремарки
   («фыркает», «ставит стакан») читались как часть реплики. */
.chat-note, .chat-act {
  font-family: var(--ff-body);
  font-size: var(--fs-dense);
  line-height: 1.45;
  color: var(--muted);
}
/* Ремарка — своя строка курсивом под именем (решение владельца 07.08). Скобок
   больше нет: строка отделена сама собой, и скобки внутри курсива читались шумом. */
.chat-note { display: block; text-transform: none; letter-spacing: 0; font-weight: 400; font-style: italic; margin: 0 0 6px 2px; }
.chat-act { font-style: italic; margin: 0 0 4px 2px; }
.chat-after { font-family: var(--ff-body); font-size: var(--fs-dense); font-style: italic; color: var(--muted-soft); margin: 4px 0 0 2px; }
.chat-bubble {
  font-size: var(--fs-read);
  line-height: 1.55;
  padding: 12px 16px;
  border-radius: var(--radius);
  border: 1px solid var(--hairline);
  background: var(--paper);
  white-space: pre-wrap;
  /* ⚠ ПУЗЫРЬ МЕРИТСЯ ПО СВОЕМУ ТЕКСТУ, А НЕ ПО СОСЕДУ (правка владельца 28.08).
     .chat-msg выше — fit-content, то есть шириной по САМОМУ ШИРОКОМУ ребёнку, а
     ремарка («на столе распечатка ваших наблюдений, местами подчёркнуто») лежит в
     нём же и бывает длиннее первой реплики. Пузырь как обычный блок растягивался
     на всю эту ширину: «Проходите, {name}. Садитесь.» — 505px текста в коробке
     823px, то есть 318px пустоты после точки. Видно это только у первого пузыря
     реплики: остальные ремарки не имеют. Своя мера обрезается той же max-width
     родителя (76%), поэтому длинные пузыри переносятся как прежде. */
  width: fit-content;
}
.chat-msg.them .chat-bubble { background: var(--soft); }
/* ПУЗЫРИ ОСТАЮТСЯ — решение владельца 04.08: формат переписки читаем и общеизвестен,
   и менять его на editorial-цитату мы не будем (я предлагал обратное, ссылаясь на
   DESIGN.md стр. 157; владелец подтвердил формат после возражения — спор закрыт).
   Сменился только цвет своей стороны: был вермилион-тинт с вермилионовой рамкой,
   стал голубой band. Причина: вермилион в системе помечает одно главное действие
   (стр. 101), и залитый им уже написанный ответ сообщал «вот тут важно» там, где
   важно другое.
   Следствие было названо: голубой раньше означал «диапазон ИИ» в отчёте, а маркер
   «вы» был вермилионовым. Владелец решил обменять роли, а не откатывать цвет
   реплики: теперь голубой — это «вы» на всех экранах, вермилион в словаре
   сравнения перешёл на ИИ-референс (DESIGN.md, Colors, решение 04.08).
   Классы .chat* использует только движок дня (проверено), поэтому правка сюда
   больше ничего не задевает. */
.chat-msg.me .chat-bubble { background: var(--band); border-color: var(--band-line); }
/* появление последней реплики — короткое, чтобы не заставлять ждать */
.chat-msg.is-new { animation: chatIn 340ms cubic-bezier(0.22, 1, 0.36, 1) both; }
/* Реплики одного шага появляются по очереди, а не одновременно: задержку ставит
   render() по индексу (см. round3.js / round5.js). Пауза короткая — участник
   ждёт ответа, а не смотрит анимацию. */
@keyframes chatIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .chat-msg.is-new { animation: none; }
}/* отправка — справа: и у мессенджеров так, и ответы участника в переписке справа */
.chat-input .btn { display: block; margin-left: auto; }

/* ── Кнопка продвижения раунда — всегда справа ────────────────────────────
   В диалоговых раундах отправка ответа стоит справа (как в мессенджерах), а в
   остальных кнопки «Дальше», «Ответить», «Завершить» оставались слева — разнобой
   на переходах между раундами. Правило собирает их к правому краю рабочей
   области. Вспомогательные кнопки внутри карточек и списков («+ добавить этап»,
   «в приоритеты», «скопировать якорь») не затрагиваются: они .btn-ghost или
   лежат глубже в разметке. */
.s2-block > .btn-primary, .s2-body > div > .btn-primary, .links-body .conn-actions > .btn-primary, .btn-advance.btn-primary, #finishBtn.btn-primary {
  display: block;
  margin-left: auto;
}
/* .btn-advance — метка «кнопка продвижения вперёд» для тех кнопок, что стоят в
   разметке страницы, а не собираются JS внутри известного контейнера. Появилась
   после реального дефекта: правило было написано на #finishBtn, а на раунде 1
   кнопок завершения две (#finishBtn / #finishBtn2), и вторая осталась слева —
   на одном экране одна кнопка справа, другая слева. Новую кнопку продвижения
   помечать этим классом, а не дописывать сюда очередной идентификатор. */
@media (max-width: 600px) { .chat-msg { max-width: 92%; } }
/* на финиш-экранах карточка и так узкая — ограничение в 76% там только зажимает */
.gate-card .chat-msg { max-width: 100%; }
/* .section-lead ограничен 42ch для страничной прозы; внутри карточки это делало
   абзац заметно уже самой карточки и баблов — здесь тянем по её ширине */
.gate-card .section-lead { max-width: none; }

/* ---------- переносы строк ---------- */
/* Браузер рвёт строку по последнему пробелу и не смотрит, что получилось:
   заголовок в две строки выходит «семь слов / одно», у абзаца последняя строка —
   одно слово. balance выравнивает длину строк в коротком блоке, pretty убирает
   висячие слова в прозе. Неразрывные пробелы после предлогов ставит js/typo.js —
   этого CSS не умеет. */
h1, h2, h3, .gate-card h2, .hub-room-title, .chat-name {
  text-wrap: balance;
}
p, li, .section-lead, .chat-bubble, .chat-act, .chat-after, label {
  text-wrap: pretty;
}
/* В полях ввода и в тексте кейса — обычный перенос: там участник пишет и читает
   документ, выравнивание строк только мешает попадать в свою же строку. */
textarea, input, #caseContent, #caseContent p, #caseContent li, .appx-doc p, .appx-doc li {
  text-wrap: wrap;
}
.wchip-num.is-active { color: var(--accent-ink); border-color: var(--accent); background: var(--accent-tint); }
.deep { border: 1px solid var(--hairline); border-radius: var(--radius); padding: 12px 14px; margin-top: 10px; }
.deep textarea { width: 100%; min-height: 68px; }
/* Левое поле навигации: было var(--frame-pad) = 56px, чтобы «Материалы» стояли
   ровно под лого в шапке. Но справа у рабочей области теперь 24px, и разница
   в поле читалась как перекос. Выравниваем на 24 с обеих сторон: колонка при
   этом сужается ровно на ту же величину, полезная ширина ссылок (226px)
   сохраняется, а высвобожденные 32px уходят колонке чтения.
   Плата: «Материалы» больше не стоят под лого — сознательный размен. */
.case-nav { padding-left: 24px; }
@media (min-width: 981px) {
  .station-body { grid-template-columns: 250px minmax(0, 1.5fr) minmax(0, 1fr); }
}
/* Заголовок рабочей области упирался в общее ограничение h2 { max-width: 20ch }
/* Метки трёх блоков рабочей области — чернилами, а не серым: серый .kicker
   читается как служебная надпись над одним потоком, а здесь это заголовки
   трёх разных работ, между которыми участник ходит туда-обратно. */
.wblock-head .kicker { color: var(--ink); }
/* ═══════════════════════════════════════════════════════════════════════════
   ПЛАТФОРМА v2 — «шесть открытых вопросов» (assessment.html + js/engine.js)
   Оформление берём от текущей платформы: пузыри разговора (.chat*), блоки
   (.s2-block), портфель (.bl-*), гейты (.gate) переиспользуются как есть.
   Ниже — только то, чего в v1 не было: шапка сцены, подпись окна, свод дня,
   установка дня и статус записи в шапке.
   ═════════════════════════════════════════════════════════════════════════ */

/* Шапка сцены: где мы и который это разговор из шести. Маршрут линейный, карты-
   хаба нет, поэтому счётчик здесь — единственная навигация, и она честная:
   вперёд, назад нельзя. */
.sc-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 14px;
  margin: 24px 0 16px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--hairline);
}
.s2-body > .sc-head:first-child { margin-top: 8px; }
/* .sc-head-count (вермилионовое «РАЗГОВОР 3 ИЗ 6») удалён 04.08: прогресс дня по
   СПЕК §4.4 живёт только на межсценовом экране, а здесь он висел над полем ответа
   всё время, пока участник пишет. Осталось место и день — «Лифтовый холл ·
   понедельник, 9 февраля», — потому что «где я» не измеряется ни одной
   способностью, а без него экран читается как оборванный. */
.sc-head-name {
  font-family: var(--ff-display);
  font-weight: 800;
  font-size: var(--fs-read);
  color: var(--ink);
}
/* margin-left: auto убран вместе со счётчиком: без него в ряду оставались две
   вещи, разогнанные по краям колонки, и они перестали читаться как одна строка. */
.sc-head-sep { font-size: var(--fs-util); color: var(--muted-soft); }
.sc-head-where { font-size: var(--fs-util); color: var(--muted-soft); }

/* Подпись окна ответа. В v1 подписи полей жили в разметке пяти страниц; здесь
   она приходит из scenes.js — тем же текстом, который получает модель. */
/* Ширина подписи повторяет ширину самого поля (.s2-body textarea ограничена
   --w-form, а не 76% своей стороны), иначе подпись висит по своему левому краю,
   а поле по своему — и они не читаются как одно целое. */
.win-label {
  display: block;
  width: 100%;
  max-width: var(--w-form);
  font-size: var(--fs-util);
  font-weight: 600;
  color: var(--muted);
  margin: 0 0 8px;
}
/* Поле ответа рисуется здесь целиком. ⚠ Раньше оно опиралось на `.s2-body textarea`,
   но в раскладке разговора никакого .s2-body нет (assessment.html стр. 122–126) —
   и поле оставалось браузерным: прямые углы, отступ 2px, кегль 13.33px.
   Рецепт тот же, что у .mx-input, кегль — читаемый (--fs-read). */
.win-input {
  /* ⚠ min-height: 200px УБРАН (правка владельца 19.08). Девять строк перебивали
     rows="3", и на одном экране соседние поля отличались втрое. Высоту задаёт
     только rows и рост под текст (autoGrow). */
  width: 100%;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  padding: 7px 9px;
  font-family: inherit;
  font-size: var(--fs-dense);
  line-height: 1.55;
  color: var(--ink);
  background: var(--paper);
  resize: vertical;
}

/* Номер позиции в СПИСКЕ (свод дня, «Мои ответы»): свой класс, потому что здесь
   номер стоит колонкой и должен выравниваться по ней — отсюда min-width. В
   карточках портфеля номер идёт первым элементом флекс-ряда, там это .bl-n.
   Оба показывают порядковый 1–20 (СПЕК §4.5); раньше здесь печатался сырой id,
   и участник видел у одной позиции два разных номера. Класс назывался .bl-id —
   переименован 04.08 вместе с правкой, чтобы имя не обещало id. */
.bl-num {
  display: inline-block;
  min-width: 2.2em;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: var(--fs-util);
  color: var(--muted-soft);
}
.bl-locked {
  font-size: var(--fs-dense);
  color: var(--muted);
  padding: 12px 0;
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
}
.bl-locked b { color: var(--ink); font-variant-numeric: tabular-nums; }
/* «За рамкой» — состояние разбора, а не действие: вермилион в системе помечает
   только действие (DESIGN.md стр. 101). Метка держится кеглем и разрядкой. */
.bl-over-tag {
  color: var(--ink);
}
.recap-item { margin: 0 0 22px; }
.recap-q {
  margin-bottom: 6px;
}
.recap-a {
  font-size: var(--fs-read);
  line-height: 1.6;
  color: var(--ink);
  max-width: var(--w-read);
  border-left: 1px solid var(--hairline);
  padding-left: 14px;
}

/* ── ОТВЕТ ШАГА — ЛИСТ В РАМКЕ, СВЁРНУТЫЙ (правка владельца 28.08) ──
   Тот же вид, что у разбора заявок на печати: белое поле, рамка, скруглённые углы.
   Свёрнуто по умолчанию — во вкладку приходят за одним ответом, а не за всеми сразу;
   на переходе к следующей встрече последний лист раскрывается сам. */
.recap-doc {
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  margin: 0 0 12px;
  box-shadow: 0 1px 2px rgba(24, 24, 24, .04);
}
.recap-sum {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 18px; cursor: pointer; list-style: none;
}
.recap-sum::-webkit-details-marker { display: none; }
.recap-sum .recap-q { margin: 0; }
/* Треугольник свёртки — свой, справа: у нативного маркера нет управления местом. */
.recap-sum::after {
  content: ''; margin-left: auto; flex: none;
  width: 7px; height: 7px;
  border-right: 1.5px solid var(--muted); border-bottom: 1.5px solid var(--muted);
  transform: rotate(45deg); transition: transform .15s ease;
}
.recap-doc[open] > .recap-sum::after { transform: rotate(-135deg); }
.recap-doc[open] > .recap-sum { border-bottom: 1px solid var(--hairline); }
.recap-doc > .recap-a {
  border-left: 0; padding: 14px 18px 18px; max-width: none;
}
/* Подпись шага внутри листа этапа: лист теперь один на этап, и внутри у него может быть
   до пяти шагов — без подписи они слились бы в один текст. */
.recap-step {
  margin: 18px 0 6px; font-family: var(--ff-display); font-size: var(--fs-util);
  font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted);
}
.recap-a > .recap-step:first-child { margin-top: 0; }

/* ── ПИСЬМО ПРАВЛЕНИЮ В ЛИСТЕ ОТВЕТОВ ──
   Форма та же, что у письма Агеева в кейсе (blockquote.letter). Внутри листа своя
   рамка была бы рамкой в рамке, поэтому здесь только фон и отступы: границу держит
   сам лист. Шапка «От/Кому/Дата/Тема» отделена линией, как в бумажном письме. */
.recap-a > blockquote.letter-mine { margin: 0; border: 0; border-radius: 8px; }
.recap-a > blockquote.letter-mine > p:first-child {
  padding-bottom: 12px; margin-bottom: 14px; border-bottom: 1px solid var(--hairline);
  color: var(--muted);
}
.recap-a > blockquote.letter-mine > p:first-child b { color: var(--ink); }
.recap-list { margin: 0; padding-left: 18px; font-size: var(--fs-dense); line-height: 1.55; }
.recap-list li { margin-bottom: 4px; }
/* Номер участника в шапке дня. Свой класс, а не общий .bib: тот рисует тёмную
   плашку с вермилионовым текстом — элемент брендированных экранов (DESIGN.md
   стр. 143), а день — тихий экран рассуждения, где вермилион занят единственным
   главным действием (стр. 101). Номер нужен участнику (назвать организатору,
   продолжить на другом устройстве), поэтому он остаётся — служебной меткой в том
   же ряду, что «сохранено» и «Скрыть материалы». Цифры моноширинно: номер
   шестизначный и не должен дёргаться при смене состояния. */
/* Размер, вес, разрядка и цвет приходят из единого рецепта метки (см. начало файла);
   здесь остаётся только своё: номер не переносится и цифры моноширинно. */
.hdr-num { white-space: nowrap; font-variant-numeric: tabular-nums; }

/* Статус записи в шапке. В v1 он жил в полосе времени (progress.js), которая
   знала имена файлов раундов; здесь маршрут один, поэтому статус — свой. */
.hdr-save { font-size: var(--fs-util); color: var(--muted-soft); white-space: nowrap; }
.hdr-save.is-pending { color: var(--muted); }
.hdr-save.is-failed { color: var(--accent-ink); font-weight: 600; }

/* ── ТАЙМЕР И ПОЛОСА ЭТАПОВ В ШАПКЕ (решение владельца 03.10, стрим 00) ──
   Два счёта с подписью словами («на этап осталось», «весь ассессмент · осталось») —
   одно голое «24 мин» было непонятно, к чему относится. Полоса — последний ряд шапки на
   всю ширину: отрезок этапа по его времени, пройденные залиты, сэкономленные минуты —
   штриховкой на текущем. У будущих этапов только номер: карту дня не показываем
   (решение 06.08). Вермилиона внутри ассессмента нет (07.08) — предупреждение синее.
   ⚠ КЕГЛИ — ИЗ ОБЩЕЙ ШКАЛЫ (решение владельца 05.10, вариант «а»): 10,5 → метка 11,
   22 → --fs-lead 20, 13 → --fs-util 12 в овале (с 14 овал упирался в общий таймер),
   12,5 → --fs-util 12. Чисел в кеглях шапки больше нет. */
/* ⚠ ПОЛОСА В ОДНОМ РЯДУ С ШАПКОЙ (владелец 03.10: «сделать воздушнее, сократить по длине,
   в конце — блок с общим таймером»): лого · полоса · общий таймер · номер. */
#assessRoot .station-header { flex-wrap: nowrap; gap: 32px; }
#assessRoot .station-header-left { order: 1; flex: none; }
#assessRoot .station-header-right { order: 4; flex: none; }
.tmr { display: flex; align-items: center; gap: 28px; min-width: 0; order: 3; flex: none; }
.tmr:empty { display: none; }
.tmr-blk { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.tmr-k { font-size: var(--label-size); font-weight: 600; letter-spacing: .09em; text-transform: uppercase; color: var(--muted); white-space: nowrap; }
.tmr-v { display: flex; align-items: baseline; gap: 8px; white-space: nowrap; }
.tmr-big { font-size: var(--fs-lead); font-weight: 700; line-height: 1; color: var(--ink); font-variant-numeric: tabular-nums; }
.tmr-of { font-size: var(--fs-util); color: var(--muted); }
.tmr-rail { order: 2; flex: 1 1 auto; min-width: 0; margin: 0 8px; }

/* На листе «Введение в роль» ни этапов, ни времени нет (решение владельца 03.10): они
   появляются с экрана материалов — отсчёт и начинается с кнопки «К пакету материалов». */
.station-shell.is-role .tmr, .station-shell.is-role .tmr-rail { display: none; }
.tmr-rail:empty { display: none; }
/* ⚠ КРУЖКИ ЭТАПОВ (владелец 04.10): линия по центру шапки на всю свободную ширину — линии
   между кружками гибкие; текущий этап — овал с заливкой по мере расхода; под линией серым —
   откуда время этапа. Длина этапов не рисуется (было непонятно, почему отрезки разные). */
.tmr-steps { display: flex; align-items: center; gap: 6px; }
.tmr-ln { flex: 1 1 auto; min-width: 8px; height: 2px; background: var(--hairline); }
.tmr-dot { flex: none; width: 22px; height: 22px; border-radius: 50%; display: inline-flex; align-items: center;
  justify-content: center; font-size: var(--label-size); font-weight: 700; background: var(--soft); color: var(--muted); }
.tmr-dot.is-done { background: var(--jb-ink); color: var(--paper); }
.tmr-now { position: relative; flex: 0 1 320px; min-width: max-content; display: inline-flex; align-items: center; gap: 8px;
  padding: 4px 12px 4px 4px; border-radius: 999px; background: var(--band); overflow: hidden; }
.tmr-now > i { position: absolute; left: 0; top: 0; bottom: 0; background: var(--band-line); transition: width .8s linear; }
.tmr-now.is-warn > i { background: #9cc2ea; }
.tmr-now .tmr-dot { position: relative; background: var(--jb-ink); color: var(--paper); }
.tmr-now-t { position: relative; font-size: var(--fs-util); font-weight: 600; color: var(--ink); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
.tmr-cap { margin-top: 6px; text-align: center; font-size: var(--fs-util); line-height: 1.35; color: var(--muted); text-wrap: balance; }
.tmr-steps.is-plain .tmr-now { flex: none; }
.tmr-k2 { font-size: var(--fs-util); color: var(--muted); white-space: nowrap; }
.tmr-total { align-items: flex-end; gap: 2px; }
/* межэтапный экран: откуда минуты */
.interlude-time { display: grid; grid-template-columns: auto auto; justify-content: start; gap: 6px 24px;
  margin: 0 0 22px; padding-top: 16px; border-top: 1px solid var(--hairline); font-size: var(--fs-dense); }
.interlude-time:empty { display: none; }
.interlude-time b { font-variant-numeric: tabular-nums; }
.interlude-time .is-plus { color: var(--jb-ink); font-weight: 600; }
.interlude-time .is-sum { font-size: var(--fs-lead); }
/* ссылки на инструкцию — в конце «Справки» (03.10) */
.ref-setup { margin: 28px 0 8px; padding-top: 14px; border-top: 1px solid var(--hairline); font-size: var(--fs-util); color: var(--muted); }
.ref-setup a { color: var(--muted); }
.ref-setup a:hover { color: var(--ink); }

/* Экран чтения пакета — первый шаг дня (акт kind:'case'). Разговора на нём нет:
   на экране только материалы, как в бумажной папке, которую принесли в пятницу. */
.case-read {
  display: flex;
  flex-direction: column;
  min-height: 0;
  padding: 0 var(--frame-pad, 56px);
}
.case-read-head .kicker { margin: 0 0 8px; }
.case-read-head .section-lead { margin: 0 0 6px; }
.case-read #caseReadHost { padding-bottom: 28px; }
/* Кнопка перехода липнет к низу: пакет длинный, и «дальше» не должно требовать
   прокрутки до конца. Прочитать до конца никто не заставляет — чтение не
   измеряется, и заслонка «точно дочитали?» означала бы обратное. */
.case-read-foot {
  position: sticky;
  bottom: 0;
  z-index: 3;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 16px;
  padding: 14px 0 18px;
  background: var(--paper);
  border-top: 1px solid var(--hairline);
}
/* Необратимость перехода — словами, рядом с кнопкой, а не догадкой по тому, что
   поле пропало. Плюс отметка времени на зафиксированном ответе. */
.win-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 14px;
  margin-top: 12px;
}
.win-note { font-size: var(--fs-util); color: var(--muted-soft); }
/* ⚠ Отметка выключена ВПРАВО — и это обратный ход к решению 04.08, когда её
   выключили влево. Тогда она стояла над полем ответа, а поле было выключено влево;
   с 07.08 она стоит ПОД пузырём участника, а пузырь прижат вправо, — и метка снова
   обязана быть у того края, к которому относится (правка владельца). */
.win-fixed {
  margin: -12px 2px 0 0;
  text-align: right;
}

/* ── Кабинет оценок v2 (cabinet.html + js/cabinet.js) ────────────────────── */
/* ⚠ ТЕЛО ЖИВЁТ В ТЕХ ЖЕ КООРДИНАТАХ, ЧТО ШАПКА. У .station-header стоит
   max-width: var(--maxw) с margin:0 auto, а у тела ограничения не было — на широком
   мониторе шапка оставалась колонкой по центру, а таблица растекалась во всю ширь
   экрана. Выглядело как две разные страницы, и колонки раздувались до бессмыслицы:
   «Николай» и «не начинал» уезжали друг от друга на пол-экрана. */
.cab-body, .cab-tabs {
  max-width: var(--maxw);
  width: 100%;
  margin: 0 auto;
}
.cab-body { padding: 22px var(--frame-pad, 56px) 64px; }
.cab-tabs { padding: 0 var(--frame-pad, 56px); }
.cab-status { font-size: var(--fs-op-sm); color: var(--muted-soft); }
.cab-status.is-bad { color: var(--accent-ink); font-weight: 600; }

.cab-table { width: 100%; border-collapse: collapse; margin-top: 18px; font-size: var(--fs-op); }
.cab-table th {
  text-align: left;
  font-size: var(--fs-op-sm);
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted-soft);
  /* Верхний отступ обязателен: без него подписи колонок прилипали к тому, что
     стоит над таблицей, — к ряду отметок или к вкладкам. */
  padding: 12px 12px 8px;
  border-bottom: 1px solid var(--hairline);
}
.cab-table td { padding: 12px 12px; border-bottom: 1px solid var(--hairline); vertical-align: middle; text-align: left; }
/* ⚠ ОТСТУП У ВСЕХ ЯЧЕЕК, ВКЛЮЧАЯ ПЕРВУЮ И ПОСЛЕДНЮЮ. Сначала стояло
   padding-left: 0 на всех ячейках — содержимое начиналось ровно на границе колонки,
   вплотную к рамке поля в соседней. Потом ноль остался у крайних, чтобы таблица
   вставала заподлицо с лого в шапке, — и номер в первой колонке всё равно оказывался
   прижат к краю. Выравнивание по лого того не стоит: таблица — блок с воздухом
   внутри, а не сетка, натянутая на края страницы. */
/* Служебные колонки не переносятся и не тянутся: номер, поток, полоска шагов,
   навыки и итог занимают ровно свою ширину, а свободное место достаётся «Сейчас»
   и «Нужен человек» — единственным двум колонкам со связным текстом. Без этого
   таблица делила ширину поровну и короткие значения расползались по пол-экрана. */
.cab-table td:first-child, .cab-table th:first-child { white-space: nowrap; }
.cab-table .cab-progress, .cab-table .cab-col-tight { white-space: nowrap; width: 1%; }
.cab-table tbody tr { cursor: pointer; }
.cab-table tbody tr:hover { background: var(--soft); }
.cab-row-ai td:first-child { box-shadow: inset 2px 0 0 var(--accent); }
.cab-dim { color: var(--muted-soft); }
.cab-total { font-size: var(--fs-op-h); font-variant-numeric: tabular-nums; }
/* .cab-flag убран вместе со значком ⚑ в «Итоге»: о флагах теперь говорит словом
   колонка «Нужен человек», и второй язык для того же только заставлял сверять. */
/* .cab-runner убран вместе со значком ⚙: прогон модели помечен словом «модель». */
.cab-ai, .cab-stale {
  font-size: var(--fs-op-sm); font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
}
.cab-ai { color: var(--accent-ink); }
.cab-stale { color: var(--accent-ink); }

/* Ход: клетка на шаг маршрута v4.4.f — двенадцать шагов, семь верстаков и пять
   свободных окон. Прежние .cab-dot убраны вместе с показом по числу заполненных
   окон q1…q8: точки были безымянными и у всех пустыми. */
.cab-progress { white-space: nowrap; }
.cab-step {
  display: inline-block; width: 8px; height: 8px; margin-right: 3px;
  border-radius: 2px; border: 1px solid #d8dadd; vertical-align: middle; cursor: help;
}
.cab-step.is-done { background: var(--ink); border-color: var(--ink); }
/* «Не спрашивали» — НЕ пустая клетка, а её отсутствие. Условный шаг, который не
   сработал, пустой клеткой читался бы как пропуск, и его пошли бы искать. */
.cab-step.is-skipped {
  width: 8px; height: 1px; border: 0; border-radius: 0;
  background: #d8dadd; position: relative; top: -1px;
}
.cab-fin { color: var(--accent-ink); font-weight: 700; }

/* «Нужен человек»: причина словом, а не значком. Значок сообщал, что что-то есть,
   но не что именно, и карточку приходилось открывать у всех подряд. */
.cab-need {
  display: inline-block; padding: 2px 6px; border-radius: 3px; margin-right: 2px;
  background: var(--soft); color: var(--accent-ink); cursor: help; white-space: nowrap;
  font-size: var(--fs-op-sm); font-weight: 700; letter-spacing: .03em;
}
.cab-filter {
  display: inline-flex; align-items: center; gap: 8px; margin: 0 0 16px;
  font-size: var(--fs-op); color: var(--muted-soft); cursor: pointer; user-select: none;
}
.cab-filter input { width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; }
.cab-filters { display: flex; flex-wrap: wrap; gap: 22px; margin: 0 0 4px; }
.cab-filters .cab-filter { margin: 0; }

/* ── один кабинет: день и ростер вкладками ──
   Ростер, волны и пароли переехали из facilitator.html: там они лежали рядом с
   показом хода по станционным листам прежнего маршрута, и участник, проходящий
   день сейчас, выглядел бездействующим. */
/* margin здесь только снизу: центрирование по колонке шапки задано выше вместе
   с .cab-body, и полный margin его бы затёр. */
.cab-tabs { display: flex; gap: 4px; margin-bottom: 4px; border-bottom: 1px solid var(--hairline); }
.cab-tab {
  appearance: none; background: none; border: 0; cursor: pointer;
  padding: 10px 14px; margin-bottom: -1px;
  font-size: var(--fs-op); font-weight: 600; color: var(--muted-soft);
  border-bottom: 2px solid transparent;
}
.cab-tab:hover { color: var(--ink); }
.cab-tab.is-on { color: var(--ink); border-bottom-color: var(--accent); }

.cab-admin { margin: 0 0 34px; }
.cab-admin h3 { margin: 0 0 12px; }
.cab-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; margin: 14px 0 0; }
.field-inline { display: flex; flex-direction: column; gap: 4px; font-size: var(--fs-op-sm); color: var(--muted-soft); }
.field-inline.field-check { flex-direction: row; align-items: center; gap: 7px; }
.field-inline input[type="checkbox"] { width: 15px; height: 15px; accent-color: var(--accent); }
.cab-inp {
  padding: 7px 9px; border: 1px solid var(--hairline); border-radius: 4px;
  font-size: var(--fs-op); color: var(--ink); background: #fff; min-width: 90px;
}
.cab-inp:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
.cab-table-tight th { padding: 10px 12px 8px; }
.cab-table-tight td { padding: 8px 12px; }

/* ── ДИСЦИПЛИНА КОЛОНОК ──
   У таблицы auto-раскладка, и без явных ширин браузер делил место поровну: у волн
   и ростера числа, галочки и пароли разъезжались на пол-экрана, а ряд кнопок
   скакал от строки к строке. Правило одно: служебные колонки занимают ровно своё
   («width:1%» + nowrap заставляет их сжаться до содержимого), а всю слабину
   забирают колонки со связным текстом — название волны и имя человека. */
.cab-col-num, .cab-col-tight, .cab-col-acts { white-space: nowrap; width: 1%; }
.cab-col-acts { text-align: right; }
.cab-center, th.cab-center { text-align: center; }
.cab-nums { font-variant-numeric: tabular-nums; line-height: 1.35; }
/* Ряд действий: одинаковые слоты во всех строках. Где действие невозможно, кнопка
   выключена, а не убрана, — иначе колонка теряет общую границу. */
.cab-col-acts .btn { margin-left: 6px; }
.cab-col-acts .btn:disabled { opacity: .4; cursor: not-allowed; }
.cab-issue { display: inline-flex; align-items: center; gap: 4px; }
/* min-width у .cab-inp — 90px, и без сброса поле на три цифры занимало столько же,
   сколько поле под название волны. */
.cab-inp-num { width: 56px; min-width: 0; text-align: center; font-variant-numeric: tabular-nums; }
.cab-inp-wide { width: 100%; min-width: 120px; }
.cab-inline-check { display: inline-flex; align-items: center; gap: 5px; cursor: pointer; }
.cab-inline-check input { width: 14px; height: 14px; accent-color: var(--accent); }
.cab-tag {
  display: inline-block; padding: 1px 5px; border-radius: 3px; background: var(--soft);
  color: var(--muted-soft); font-size: var(--fs-op-sm); font-weight: 600; white-space: nowrap;
}
.cab-table tbody tr.is-archived, .cab-table tbody tr.is-off { opacity: .55; }
/* Строки волн и ростера не кликабельны целиком — кликают по кнопкам внутри. */
.cab-waves tbody tr, .cab-roster tbody tr { cursor: default; }
.cab-waves tbody tr:hover, .cab-roster tbody tr:hover { background: none; }

/* Пустое состояние учит экрану, а не сообщает «ничего нет». */
.cab-empty { max-width: 62ch; margin: 18px 0 0; color: var(--ink); font-size: var(--fs-op); line-height: 1.6; }

.cab-search input { min-width: 200px; }
.cab-vh {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.cab-more { margin: 26px 0 0; }
.cab-more summary { cursor: pointer; font-size: var(--fs-op); font-weight: 600; color: var(--muted-soft); }
.cab-more summary:hover { color: var(--ink); }
.cab-more[open] summary { color: var(--ink); margin-bottom: 4px; }

/* Только что выданные номера: единственный момент, когда номер и пароль нужны
   вместе, чтобы их раздать. Поэтому блок отделён фоном, а не просто вставлен. */
.cab-issued { margin: 18px 0 0; padding: 14px 16px; background: var(--soft); border-radius: var(--radius, 8px); }
.cab-issued-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.cab-issued .cab-table { margin-top: 10px; }
/* Широкую таблицу прокручиваем ВНУТРИ её места, иначе горизонтальный скролл
   уезжает на всю страницу и шапка с вкладками уходит из вида вместе с ней. */
#cabList, #cabRoster, #cabWaves, #cabIssueOut { overflow-x: auto; }
.cab-row-acts { white-space: nowrap; }
/* Пароль набирается табличными цифрами: его диктуют вслух и сверяют по одному знаку. */
.cab-pw { font-variant-numeric: tabular-nums; letter-spacing: .04em; }

/* Решение человека по уровню: стоит РЯДОМ с мнением судьи, не вместо него.
   Помечено фоном, а не цветной полосой слева: полоса-язычок сбоку — приём, который
   ничего не сообщает сверх фона, и вермилион на --accent-tint даёт 4.9:1 против
   3.1:1 у самого акцента, то есть подпись под ней ещё и читается. */
.cab-ability.is-overridden {
  background: var(--accent-tint);
  border-radius: var(--radius);
  padding: 12px 14px;
}
.cab-ov { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 9px; }
.cab-ov .cab-ov-reason { flex: 1 1 220px; min-width: 160px; }
.cab-ov-why { margin-top: 6px; font-size: var(--fs-op); color: var(--ink); }
.cab-ovmark {
  font-size: var(--fs-op-sm); font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--accent-ink);
}

/* Шаг в карточке: непройденный и неспрошенный гасятся, чтобы взгляд шёл по тому,
   что человек сделал, а не спотыкался на равновесных пустотах. */
.cab-answer.is-wait, .cab-answer.is-skipped { opacity: .5; }
.cab-answer.is-legacy { padding-left: 12px; box-shadow: inset 1px 0 0 var(--hairline); }
/* Сырой объект верстака — путь на случай, когда форма механики изменилась после
   записи строки. Шрифт тот же (система намеренно одношрифтовая), читаемость даёт
   разметка пробелами и табличные цифры. */
.cab-raw {
  margin: 0; padding: 10px 12px; background: var(--soft); border-radius: 4px;
  font-size: var(--fs-op-sm); line-height: 1.55; white-space: pre; overflow-x: auto;
  font-variant-numeric: tabular-nums;
}

.cab-skill { display: inline-block; margin-right: 9px; font-size: var(--fs-op-sm); color: var(--muted-soft); }
.cab-skill b { display: inline-block; margin-left: 3px; font-size: var(--fs-op); color: var(--ink); font-variant-numeric: tabular-nums; }

/* ── карточка ── */
.cab-card { max-width: 900px; }
.cab-actions { display: flex; align-items: center; gap: 12px; margin: 16px 0 6px; }
.cab-block { margin-top: 26px; }
.cab-block h3 { font-size: var(--fs-op-h); margin: 0 0 6px; }
.cab-note { font-size: var(--fs-op); color: var(--muted-soft); margin: 0 0 12px; max-width: var(--w-read); }
.cab-warn { font-size: var(--fs-op); color: var(--accent-ink); font-weight: 600; margin: 10px 0; }
.cab-warn-inline { color: var(--accent-ink); }
.cab-k { font-weight: 600; color: var(--muted); }

.cab-skills-row { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0 14px; }
.cab-skill-box {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  min-width: 62px; padding: 10px 12px;
  border: 1px solid var(--hairline); border-radius: var(--radius); background: var(--paper);
}
.cab-skill-box span { font-size: var(--fs-op-sm); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted-soft); }
.cab-skill-box b { font-size: var(--fs-op-xl); font-variant-numeric: tabular-nums; }
.cab-skill-box i { font-size: var(--fs-op-sm); color: var(--muted-soft); font-style: normal; }
.cab-skill-box.is-total { border-color: var(--ink); }
/* Неровный навык виден до наведения курсора: §9.5 требует показать разрыв внутри пары,
   а не только сумму, которая его прячет. Рамка, а не цвет: флаг — приглашение перечитать,
   не ошибка участника. */
.cab-skill-box.is-asym { border-color: var(--accent-ink); }
.cab-skill-box.is-asym i { color: var(--accent-ink); }

/* Оценка стоит первым блоком карточки (правка 12.08), и штатные 72 пикселя сверху
   читались как дырка под кнопкой «Пересудить». Первому блоку отступ сверху меньше. */
.fac-detail-body .cab-block:first-of-type { padding-top: 14px; }

/* ── СПОСОБНОСТЬ В КАРТОЧКЕ: СВЁРНУТАЯ СТРОКА ─────────────────────────────────
   Внутри одной строки лежит всё, что нужно для решения: обоснование судьи, ответ, по
   которому оно дано, контроль и флаги. Свёрнуто по умолчанию — иначе десять способностей
   с текстами ответов превращают карточку в километровое полотно (правка 12.08). */
.cab-ab { border-top: 1px solid var(--hairline); }
/* ⚠ FLEX, А НЕ GRID. В grid-контейнере псевдоэлемент ::before становится ЧЕТВЁРТЫМ
   элементом сетки и забирает первую колонку целиком — название уезжало к правому краю
   (поймано на живой карточке). Во flex он просто первый в ряду. */
.cab-ab > summary {
  cursor: pointer; list-style: none; padding: 11px 0;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px;
}
.cab-ab > summary::-webkit-details-marker { display: none; }
.cab-ab > summary::before {
  content: ''; display: inline-block; width: 6px; height: 5.5px; margin-right: 8px;
  background: var(--muted-soft); clip-path: polygon(0 0, 100% 50%, 0 100%);
  transition: transform .12s ease; vertical-align: 1px;
}
.cab-ab[open] > summary::before { transform: rotate(90deg); }
.cab-ab > summary:hover { background: var(--soft); }
.cab-ab-name { font-size: var(--fs-op); font-weight: 600; flex: 1 1 auto; }
.cab-ab-line { flex: 0 0 100%; font-size: var(--fs-op-sm); color: var(--muted-soft); padding-left: 14px; }
.cab-ab-flag {
  font-size: var(--fs-op-sm); font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--accent-ink); background: var(--accent-tint); padding: 2px 7px; border-radius: 4px;
}
.cab-ab.has-flag > summary { background: var(--accent-tint); }
.cab-ab-body { padding: 2px 0 16px 14px; }
.cab-ab-h {
  font-size: var(--fs-op-sm); font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted-soft); margin: 14px 0 6px;
}
.cab-ab-why { font-size: var(--fs-op); line-height: 1.55; max-width: var(--w-read); white-space: pre-wrap; }

/* Крупные блоки карточки ниже оценки — тоже свёрнуты. */
.cab-fold { border-top: 1px solid var(--hairline); margin-top: 18px; }
.cab-fold > summary {
  cursor: pointer; list-style: none; padding: 13px 0;
  font-size: var(--fs-op-h); font-weight: 700; letter-spacing: -0.01em;
}
.cab-fold > summary::-webkit-details-marker { display: none; }
.cab-fold > summary::before {
  content: ''; display: inline-block; width: 7px; height: 6.5px; margin-right: 9px;
  background: var(--ink); clip-path: polygon(0 0, 100% 50%, 0 100%);
  transition: transform .12s ease; vertical-align: 2px;
}
.cab-fold[open] > summary::before { transform: rotate(90deg); }

.cab-ability { padding: 10px 0; border-top: 1px solid var(--hairline); }
.cab-ability-head { display: flex; align-items: baseline; gap: 10px; }
.cab-ability-name { font-size: var(--fs-op); font-weight: 600; }
.cab-level { margin-left: auto; font-size: var(--fs-op-h); font-weight: 700; font-variant-numeric: tabular-nums; }
.cab-jitter { color: var(--accent-ink); }
/* Свидетельства по гейтам: цитата — основание уровня, поэтому читается как цитата,
   а не как строка данных. Ширина по колонке чтения: длинные цитаты иначе тянутся
   на всю карточку и глазом не берутся. */
.cab-evid { list-style: none; margin: 6px 0 0; padding: 0; max-width: var(--w-read); }
.cab-evid li { font-size: var(--fs-op); line-height: 1.55; padding: 6px 0 6px 10px;
  border-left: 2px solid var(--hairline); margin-bottom: 6px; }
.cab-evid li b { font-variant-numeric: tabular-nums; }
.cab-evid-un { font-size: var(--fs-op); color: var(--muted); margin-top: 6px; max-width: var(--w-read); }
.cab-reasoning summary { cursor: pointer; font-size: var(--fs-op); color: var(--muted); margin-top: 4px; }
.cab-reasoning > div { font-size: var(--fs-op); line-height: 1.55; color: var(--ink); margin-top: 6px; max-width: var(--w-read); }
.cab-control { margin-top: 14px; padding: 12px 14px; border: 1px solid var(--hairline); border-radius: var(--radius); background: var(--soft); font-size: var(--fs-op); }
.cab-control p { margin: 0 0 8px; }
.cab-flags { margin: 0; padding-left: 18px; font-size: var(--fs-op); line-height: 1.55; }
/* ⚠ ЗЕЛЁНЫЙ ФЛАГ — ПОЛОЖИТЕЛЬНАЯ ПОМЕТКА (11.09). Собственного зелёного в палитре нет,
   и заводить его ради одной строки значило бы расширить систему цветов на четвёртый.
   Берём читаемый синий, который уже живёт в системе для информационных пометок, и
   отделяем подписью: в списке рядом не должно быть сомнения, что это не «перечитать». */
.cab-flags-green { margin-top: 8px; color: var(--jb-ink); }
.cab-flags-green::before { content: 'Сильная сторона'; display: block; margin-left: -18px;
  font-size: var(--fs-op-sm); font-weight: 700; letter-spacing: .05em; text-transform: uppercase; }

.cab-answer { padding: 14px 0; border-top: 1px solid var(--hairline); }
.cab-answer-head { display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: baseline; margin-bottom: 6px; }
.cab-answer-label { font-size: var(--fs-op-sm); font-weight: 700; letter-spacing: .05em; text-transform: uppercase; }
.cab-answer-head .cab-dim { font-size: var(--fs-op-sm); margin-left: auto; }
.cab-answer-text { font-size: var(--fs-op); line-height: 1.6; max-width: var(--w-read); }
.cab-answer-text ul { padding-left: 18px; }

/* ═══════════════════════════════════════════════════════════════════════════
   ПЛАТФОРМА v2 · РАБОЧИЙ СТОЛ (assessment.html + js/engine.js, ревизия 2026-08-03)
   Лента разговора заменена на две зоны: слева опора, которая никуда не уходит,
   справа один текущий вопрос. Причина не косметическая: модель на каждом шаге
   получает кейс и всю историю бесплатно, а человек в прежней версии платил за это
   прокруткой и памятью — налог, которого нет ни в одной рубрике.
   ═════════════════════════════════════════════════════════════════════════ */

/* ТРИ КОЛОНКИ (СПЕК §4.1): оглавление · память · работа. Двухзонная раскладка
   заменена, потому что кейс и разговор делили одну ширину и мешали друг другу:
   34 тысячи знаков в колонке на 44% читались хуже, чем в v1 на полном экране.
   Замер на живом тексте: 66 знаков в строке на 1440 и 1280, 57 на 1100 — вся
   вилка попадает в комфортную полосу 55–75. */
.day-grid {
  flex: 1;
  display: grid;
  /* КОЛОНКА ОГЛАВЛЕНИЯ ШИРЕ РОВНО НА ОТСТУП РАМКИ, и этот отступ она отдаёт слева
     (см. .dayside-head / .dayside-body). Иначе лого в шапке стоит на 56px, а
     «Разделы» под ним — на 14px, и шапка читается приклеенной отдельно от экрана
     (DESIGN.md стр. 138). Полезная ширина ссылок оглавления при этом не меняется —
     ровно тот приём, которым это решено для колонки материалов в v1 (.case-nav).
     Замер после правки: лого и «Разделы» на 56px, колонки 266/587/587 при 1440. */
  --toc-col: calc(var(--toc-w, 210px) + var(--frame-pad));
  /* ⚠ ОПОРА УЖЕ РАБОЧЕЙ КОЛОНКИ (решение владельца 28.08): «вспомогательное окно не может
     быть таким же, как основная рабочая область, на которой участник должен быть
     сфокусирован». До этого доли были равные, и при 1680 обе колонки выходили по 707px —
     то есть панель материалов заявляла о себе ровно столько же, сколько разговор.
     Доля, а не пиксели: колонка обязана дышать вместе с экраном. Замер при 1680 —
     работа 786, опора 628. Трек лежит в токене, потому что раскладок с тремя колонками
     шесть (рабочие экраны, чтение и по два состояния оглавления), и разъехаться им нельзя.
     calc здесь невозможен: fr — не длина, поэтому в токене весь трек целиком. */
  --side-col: minmax(0, .8fr);
  /* ⚠ ЛЕВОЙ КОЛОНКИ БОЛЬШЕ НЕТ (решение владельца 03.10, стрим 00), её ширина — --toc-col —
     ПОРОВНУ уходит работе и материалам. Доли 1 : .8 из решения 28.08 держатся на остальной
     ширине, поэтому работа по-прежнему шире опоры: работа = (W − toc) / 1,8 + toc / 2,
     опора — остаток. Проценты в треке грида считаются от ширины контейнера; fr здесь
     нельзя — к нему не прибавить длину. Замер при 1440: 785 / 655 (было 266 / 652 / 522). */
  --work-col: minmax(0, calc((100% - var(--toc-col)) / 1.8 + var(--toc-col) / 2));
  grid-template-columns: var(--work-col) minmax(0, 1fr);
  position: relative;
  /* Строку задаём явно. Без неё единственный auto-ряд считался по содержимому, и
     колонка опоры получала 291 px из 694 доступных: на чтение пакета оставалась
     щель в 61 px. Ровно тот дефект, из-за которого кейс и выглядел «впаянным». */
  grid-template-rows: minmax(0, 1fr);
  min-height: 0;
  /* border-top снят 04.08: у .station-header уже есть border-bottom, и две
     соседние линии давали 2px. Линия под шапкой — одна, и она шапкина. */
}

/* РАМКА ДНЯ — ОКНО ЦЕЛИКОМ, И ШАПКА СИДИТ НА НЕЙ ЖЕ (DESIGN.md стр. 138:
   «шапка и тело обязаны сидеть на одной рамке… самый частый дефект в этом
   проекте»). Тело дня — это грид выше, и на var(--maxw) он не сидит: ширины
   колонок замерены по окну (66 знаков в строке на 1440 и 1280). Пока шапка
   стояла на var(--maxw) и центрировалась, лого уезжало от левого края
   оглавления на 216px при 1440 и на 456px при 1920 — считано, не оценено.
   Если однажды решим стянуть день к рамке 1120–1560, снимать надо ЭТО правило
   и заново мерить знаки в строке, а не возвращать body.frame-narrow. */
#assessRoot .station-header { max-width: none; }
/* Свёртки колонки этапов и её автоматического ухода ниже 1360 больше нет вместе с
   самой колонкой (03.10). Режим чтения — те же две колонки: пакет на месте работы. */
.day-grid.is-reading { grid-template-columns: var(--work-col) minmax(0, 1fr); }

/* Кейс в середине, панель справа (класс .is-casewide ставит engine.js). На время чтения
   тело кейса и кнопка «Прочитал» переезжают в среднюю колонку; панель остаётся со своими
   вкладками, вкладка «Кейс» скрыта. */
/* ⚠ padding: 0 обязателен: .casewide это <section>, и на него падает лендинговое
   section { padding: 72px 0 } — 73px пустоты над содержимым. */
.casewide { display: none; padding: 0; }
.day-grid.is-casewide > .casewide {
  display: flex; flex-direction: column; min-height: 0; min-width: 0;
  grid-column: 1; background: var(--paper);
  /* шов «пакет | панель» — там же, где на рабочих экранах шов «разговор | материалы» */
  border-right: 1px solid var(--hairline);
}
.day-grid.is-casewide > .support { grid-column: 2; }
/* Тело кейса внутри средней колонки видно всегда: правило .support-body:not(.is-on)
   его бы спрятало, а вкладки «Кейс» на этом экране нет. */
.day-grid.is-casewide > .casewide > .support-body { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.day-grid.is-casewide .support-tab[data-tab="case"] { display: none; }
/* Ниже 1360 переезда нет: пакету нужна вся ширина, кейс читается вкладкой. */
/* На ноутбуке оглавление в режиме чтения ОСТАЁТСЯ: колонки работы здесь нет, и
   266px из 1280 оставляют пакету 1014 — больше, чем он получает в три колонки на
   1920. Было grid-template-columns: 1fr, и на ≤1360 участник читал пакет из
   двадцати с лишним разделов вообще без оглавления, причём вернуть его было
   нечем — кнопка снимает класс, а скрывал колонку медиазапрос. */
/* Ниже 1360 третьей колонки нет: 1280 минус столбик этапов оставляют 1014, и делить
   их надвое значило бы читать пакет в 450px — это уже ниже нормы набора (45 знаков в
   строке). Здесь пакет занимает всё свободное место, как и рабочая область на этих
   ширинах. Порог тот же, что у остальных правил раскладки (см. выше). */
@media (max-width: 1360px) {
  .day-grid.is-reading { grid-template-columns: minmax(0, 1fr); }
  .day-grid.is-reading > .support { grid-column: 1; border-right: none; }
}
.day-grid.is-reading > .talk { display: none; }

/* Левой колонки (.dayside, .toc-restore, маршрут .route-*) больше нет — 03.10, стрим 00. */

/* ── опора ── */
.support {
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
  /* ⚠ БОКОВОЙ ЛИНИИ ЗДЕСЬ НЕТ — и это следствие перестановки колонок 05.08.
     Опора теперь ПОСЛЕДНЯЯ колонка, её правый край = правый край окна: линия
     справа рисовалась бы по краю экрана отдельной ниткой. Шов «работа | опора»
     держит .talk своим border-right, шов «оглавление | работа» — .dayside.
     Правило: линию рисует ЛЕВЫЙ сосед шва, тогда у последней колонки её нет. */
  background: var(--paper);
}
.support-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  padding: 10px var(--frame-pad, 24px) 0;
  border-bottom: 1px solid var(--hairline);
}
.support-tab {
  border: none;
  background: none;
  padding: 8px 12px 10px;
  font: inherit;
  font-size: var(--fs-util);
  color: var(--muted-soft);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.support-tab:hover { color: var(--ink); }
.support-tab.is-on { color: var(--ink); font-weight: 600; border-bottom-color: var(--accent); }
/* Вкладки видны и на экране чтения; скрыта только «Кейс», и только когда пакет
   раскрыт в середине (.is-casewide). */

.support-body { display: none; min-height: 0; flex: 1; overflow: hidden; }
.support-body.is-on { display: flex; flex-direction: column; }
/* Пометки и справка, уехавшие в колонку чтения (#readSide): видимы независимо от
   выбранной вкладки — вкладок в этом состоянии нет вовсе. */
.support-body.is-aside { display: flex; flex-direction: column; overflow-y: auto; padding: 12px var(--frame-pad, 24px) 18px; }
/* #supNotes и #supWho — мёртвые идентификаторы от прежней раскладки опоры; из-за
   них справка (#supRef) осталась без прокрутки и без отступов: девять терминов,
   восемь людей и девять продуктов упирались в край и обрезались снизу. Поймано
   04.08, когда владелец поставил справку второй вкладкой. */
/* ⚠ #supRole В ЭТОМ ЖЕ ПРАВИЛЕ (правка владельца 25.08). Пятая вкладка приехала без
   отступов вовсе — текст упирался в край панели, и на фоне подписей вкладок он читался
   «слишком крупным», хотя по замеру кегль тот же, что у заметок и ответов (16px). Дело
   было не в кегле, а в том, что строка шла во всю ширину панели от самого края.
   Отступ здесь один на все вкладки-списки: разойтись им негде. */
#supAnswers.is-on, #supRef.is-on, #supRole.is-on { overflow-y: auto; padding: 16px var(--frame-pad, 24px) 28px; }
/* Врезка роли заводилась НАД пакетом, поэтому несёт линейку и отступ снизу — она
   отделяла себя от текста кейса. Во вкладке под ней ничего нет, и линейка висела
   в пустоте (видно на снимке владельца). Интерлиньяж — как у соседних вкладок. */
#supRole .read-role { border-bottom: none; padding-bottom: 0; margin-bottom: 0; }
#supRole .read-role p { line-height: 1.55; }
/* ── ОПОРА НАБИРАЕТСЯ НА СТУПЕНЬ ТИШЕ РАБОЧЕЙ ОБЛАСТИ (правка владельца 28.08) ──
   «Блок со справкой, заметками и ответами вспомогательный и не должен забирать на себя
   внимание из-за размеров шрифтов». До этой правки три вкладки набирались ровно тем же
   кеглем, что и рабочая область: лист ответа и проза роли — 16px (--fs-read), заголовки
   блоков и листов — 16px прописными (--fs-sub), термины, цитаты пометок и письмо — 14px.
   ⚠ И ЭТО ВТОРОЙ ЗАХОД. 25.08 та же жалоба («слишком крупный») была объяснена отступами
   — см. комментарий выше, — и отступы действительно были нужны, но одних их не хватило:
   рядом с репликой того же кегля опора читается как второй главный текст, а не как
   справка под рукой.
   Новых кеглей не заводим (правило шкалы в начале файла): каждый элемент переезжает на
   СВОЮ СОСЕДНЮЮ ступень той же шкалы участника — 16 → 14, 14 → 12. Ниже 12 ступени в
   этой шкале нет, поэтому служебные строки (подпись шага в листе, счётчики, «показать в
   материалах») остаются на месте: они и так самые тихие, а 11px принадлежит операторской
   шкале, мешать её со шкалой участника запрещено.
   ⚠ ВКЛАДКА «О КОМПАНИИ» СЮДА НЕ ВХОДИТ НАМЕРЕННО. На этапе чтения пакет и есть рабочая
   область — на него участник тратит 30–40 минут; уменьшить его кегль значило бы уменьшить
   сам кейс. Владелец назвал три вкладки, и правило ровно на них. */
/* Сдвиг делаем ПОДМЕНОЙ ТОКЕНОВ, а не перечислением элементов. Первый заход перечислял
   («.who-h, .recap-a, .who-row, .mark-quote…») и пропустил рамку-напоминание во вкладке
   заметок: у неё свой font-size: var(--fs-read), и владелец сразу это увидел — «кейс
   написан таким же, как пояснение на странице». Перечисление промахнётся снова, как только
   в опоре появится новый элемент. Подмена ловит всё, что берёт кегль из шкалы.
   Почему в два правила, а не в одно: --fs-read: var(--fs-dense) на самом контейнере
   разрешается по ЕЩЁ НЕ подменённому --fs-dense, то есть по 14px из :root, — это и нужно.
   Если подменить --fs-dense там же, ссылка уехала бы на две ступени вниз. Поэтому 14 → 12
   объявляется потомкам, где значение уже не участвует в первой подстановке. */
#supRef, #supMarks, #supAnswers {
  font-size: var(--fs-dense);
  --fs-read: var(--fs-dense);   /* проза, лист ответа, рамка-напоминание: 16 → 14 */
  --fs-sub:  var(--fs-dense);   /* заголовки блоков справки и листов: 16 → 14 */
}
#supRef *, #supMarks *, #supAnswers * {
  --fs-dense: var(--fs-util);   /* плотные строки: термины, цитаты, списки, письмо: 14 → 12 */
}
/* ⚠ РАМКА-НАПОМИНАНИЕ ВО ВКЛАДКЕ ЗАМЕТОК ТЕПЕРЬ ТОЖЕ ТИШЕ. На её правиле стоит пометка
   07.08: «кегль читаемый, не служебный: её читают, а не сверяются с ней». Решение владельца
   28.08 её перебивает — «всё в этом блоке мельче, чем основной рабочий блок», — и рамка
   сравнивалась глазом именно с текстом кейса, который рядом и остался 16px. */

.support-note { font-size: var(--fs-util); line-height: 1.5; color: var(--muted-soft); margin: 0 0 14px; max-width: var(--w-read); }
.toc-link {
  display: block; width: 100%; text-align: left; border: none; background: none;
  padding: 4px 0; font: inherit; font-size: var(--fs-util); color: var(--muted); cursor: pointer;
}
.toc-link:hover { color: var(--ink); }
.toc-link.is-on { color: var(--ink); font-weight: 600; }

/* Точка привязки для плавающей кнопки «вернуться к чтению» (.case-back). */
#supCase { position: relative; }
#supCaseText { flex: 1; min-height: 0; overflow-y: auto; padding: 20px var(--frame-pad, 24px) 40px; }
/* Одна колонка документа. DESIGN.md стр. 148: всё влево внутри колонки, сама колонка —
   по центру окна. Таблицы приложений лежат в .tbl-wrap со своей прокруткой. */
/* Мера строки — 80 знаков (решение владельца 06.08), кегль растёт с окном (fluid type).
   ⚠ Рамку экрана чтения по --maxw не ограничивать: шапка живёт во всю ширину
   (#assessRoot .station-header, решение 04.08), и тело без неё отрывается от лого. */
/* КЕГЛЬ КЕЙСА В ПАНЕЛИ — 16px, А НЕ 14,5.
   14,5px стояло у .case-content p с прежних раундов, где кейс был справкой на
   полстраницы. Здесь это двадцать две тысячи знаков основного чтения: норма для
   длинного текста — 16px и выше, и она же снимает половину жалобы на «сосиску»
   (при 14,5px мера 60 знаков давала колонку 435px в панели на 590). Правило узкое,
   только для панели ассессмента: .case-content живёт ещё на трёх страницах, и общий
   кегль там менять незачем. Наследование через 1em, чтобы кегль задавался ОДИН раз
   на контейнере, а абзацы, списки и таблицы шли от него. */
#supCaseText { font-size: var(--fs-read); }
#supCaseText p, #supCaseText li, #supCaseText td, #supCaseText th { font-size: 1em; }
/* ⚠ Прокручивается КОЛОНКА, меру держат ДЕТИ — это разные элементы. Ползунок рисуется
   по правому краю прокручиваемого блока: если ограничить по ширине его, ползунок
   окажется посреди экрана. Дети выключены влево. */
#supCaseText > * { max-width: 80ch; margin-inline: 0; }
/* Мера держится КОНТЕЙНЕРОМ, а не каждой статьёй: у .case-content article стоит
   max-width: var(--w-read) в 60ch, и внутри свёртки это давало вторую, более
   узкую рамку — заголовок свёртки шёл по одной ширине, текст по другой. */
#supCaseText .case-block > article { max-width: none; }

.day-grid.is-reading #supCaseText {
  /* 1280 → 16px, 1440 → 16,5, 1920 → 18, 2560 → 19 (дальше не растёт) */
  font-size: var(--fs-read);
  padding-left: var(--frame-pad, 56px);
  padding-right: var(--frame-pad, 56px);
  /* ⚠ КОЛОНКА ЧТЕНИЯ СТАЛА ШИРЕ (03.10: левой колонки нет, её место ушло работе и
     материалам), и мера, которую раньше держала ширина колонки, поползла к 85 знакам.
     Держим её здесь же, на теле с базовым шрифтом: правое поле добирает всё сверх 66ch.
     Процент в padding — от ширины колонки, ch — от кегля этого элемента. */
  padding-right: max(var(--frame-pad, 56px), calc(100% - 66ch - var(--frame-pad, 56px)));
  /* ⚠ ch считается по шрифту САМОГО элемента, а не страницы. У .appx-divider
     дисплейная гарнитура 13px, и 60ch там = 433px против 534px у прозы — то есть
     раздача max-width каждому ребёнку давала три разные ширины. Поэтому мера
     задаётся ОДИН раз здесь, на теле с базовым шрифтом, а дети берут 100%. */
  /* Мера — на детях (см. #supCaseText > * выше), а не на прокручиваемой колонке:
     иначе ползунок уезжает в середину экрана. 66ch, а не 60: 60 было опущено 04.08
     замером на 16px, где 68ch давали 81 знак. ch считается по СОБСТВЕННОМУ кеглю
     элемента, поэтому мера в знаках не плывёт от того, что кегль растёт с окном. */
}
.day-grid.is-reading #supCaseText > * { width: 100%; max-width: none; }
/* В режиме чтения оглавление ложится строкой во всю ширину: вертикальным списком
   оно съедало 200 px из 840, то есть четверть экрана чтения. */
.day-grid.is-reading .case-toc {
  display: flex; flex-wrap: wrap; gap: 2px 20px;
  max-height: none; padding-left: var(--frame-pad, 56px); padding-right: var(--frame-pad, 56px);
}
.day-grid.is-reading .toc-title { width: 100%; }
.day-grid.is-reading .toc-link { width: auto; }

/* ВВЕДЕНИЕ В РОЛЬ — на странице чтения, а не на экране установки (решение
   владельца 04.08: «смешалось всё — и введение в кейс, и технические
   комментарии»). Установка осталась про устройство дня, роль переехала туда, где
   человек садится читать пакет. Тот же текст (S.system.lead) — данные не менялись,
   значит паритет с моделью, которая получает этот блок в system, сохранён. */
/* Виден только на странице чтения: в разговоре вкладка «Кейс» — это тот же узел
   DOM, и введение там отнимало бы прокрутку у материалов, за которыми в него
   пришли. Текст никуда не пропадает — страницу чтения можно открыть снова. */
.read-role { display: none; }
.day-grid.is-reading .read-role { display: block; }
.read-role { border-bottom: 1px solid var(--hairline); padding-bottom: 24px; margin-bottom: 28px; }
.read-role p { font-size: var(--fs-read); line-height: 1.62; margin: 0 0 14px; }
.read-role p:last-child { margin-bottom: 0; }
.read-role .read-role-lead { color: var(--muted); font-size: var(--fs-dense); }

/* Кнопка перехода в разговор живёт только в режиме чтения, липнет к низу опоры.
   Прижата ВПРАВО тем же правилом, что и кнопка ответа в .work-act: место главного
   действия на экране дня одно — правый низ, — и прыгать между экранами оно не
   должно (решение владельца 04.08). Порядок в разметке [записка, кнопка], значит
   flex-end ставит кнопку у самого края, а записка читается слева от неё. */
/* Подвал переезжает вместе с телом кейса: выше 1360 — .casewide, ниже — панель. */
.support > .case-read-foot, .casewide > .case-read-foot {
  flex: none;
  position: static;
  justify-content: flex-end;
  border-top: 1px solid var(--hairline);
  padding: 14px var(--frame-pad, 56px) 18px;
  background: var(--paper);
}
.support > .case-read-foot .win-note, .casewide > .case-read-foot .win-note { max-width: 340px; }
/* Пустое примечание не должно держать место и зазор рядом с кнопкой. */
.win-note:empty { display: none; }
/* ⚠ ЗАГОЛОВОК БЛОКА ОТДЕЛЁН ЧЕРТОЙ ОТ СВОЕГО СПИСКА (правка владельца 28.08).
   Заголовки склеивались со списком: строки терминов разделены волосяной линией, а у
   заголовка своей линии не было вовсе. Линия цветом текста и в два пиксела: она обязана
   читаться СИЛЬНЕЕ тех, что делят термины между собой.
   ⚠ ЧЕРТА ПОД ЗАГОЛОВКОМ, А НЕ НАД НИМ. Сначала я поставил её сверху — как границу между
   блоками, — и владелец сразу это поймал: заголовок оказывался ПОД чертой, оторванным от
   собственного списка и приклеенным к чужому. Логика простая: заголовок называет то, что
   идёт за ним, черта его открывает, как шапку таблицы. Паузу между блоками держит
   увеличенный отступ сверху, а не линия. */
.who-h { margin: 34px 0 0; padding-bottom: 8px; border-bottom: 2px solid var(--ink); }
.who-h:first-child { margin-top: 0; }
/* Введение в роль — не список, а абзацы: под заголовком блока им нужен свой отступ,
   а последний абзац не должен прижимать следующую черту. */
.who-role { padding: 10px 0 6px; }
.who-role .read-role > p:last-child { margin-bottom: 0; }
/* ⚠ ВНУТРИ СПРАВКИ ЭТОТ БЛОК ПОКАЗЫВАЕМ ЯВНО (дефект от 28.08, найден 28.08 замером).
   .read-role скрыт по умолчанию (правило ниже) и открывается только на экране чтения
   .day-grid.is-reading — это от той поры, когда блок был врезкой над пакетом материалов.
   С правкой 28.08 он ещё и ПЕРВЫЙ блок «Справки», а справку открывают как раз на рабочих
   экранах: там display оставался none, и заголовок «Введение в роль» стоял над пустотой —
   ровно тот пустой заголовок, который владелец уже ловил однажды.
   Линейку и отступ снизу гасим по той же причине, что и у прежней вкладки роли: черту под
   заголовком рисует .who-h, вторая была бы второй чертой об одном. */
#supRef .who-role .read-role { display: block; max-width: none; border-bottom: none; padding-bottom: 0; margin-bottom: 0; }
#supRef .who-role .read-role p { line-height: 1.55; }
/* ⚠ Мера строки одна на всю платформу — 80 знаков на всех бегущих строках: кейс,
   справка, пометки, свои ответы. Исключения: таблицы приложений (читают по столбцам)
   и колонка терминов в справке (ярлык, не текст). */
.who-row { display: grid; grid-template-columns: minmax(120px, 34%) minmax(0, 1fr); gap: 4px 12px; padding: 8px 0; border-bottom: 1px solid var(--hairline); font-size: var(--fs-dense); line-height: 1.45; }
.who-row b { font-weight: 600; }
.who-row span { color: var(--muted); max-width: 80ch; }

/* ── разговор (ЦЕНТРАЛЬНАЯ колонка с 05.08) ── */
.talk {
  /* ⚠ padding: 0 обязателен: .talk это <section>, и на него падает лендинговое
     section { padding: 72px 0 }
. */
  padding: 0;
  display: flex; flex-direction: column; min-height: 0; min-width: 0;
  /* Шов «работа | опора». Линию рисует левый сосед шва (см. .support): работа
     стоит между оглавлением и опорой, поэтому линия у неё справа. В режиме
     чтения пакета работа скрыта целиком — линия уходит вместе с ней, и шов
     «оглавление | опора» остаётся один, от .dayside. */
  border-right: 1px solid var(--hairline);
}
/* ⚠ МЕСТО ПОД ПОЛОСУ ПРОКРУТКИ ЗАНЯТО ВСЕГДА (правка владельца 28.08). При overflow
   auto полоса заводится в тот момент, когда содержимое переросло колонку, и отнимает
   свою ширину у текста — строки перевёрстываются на ходу. Это вторая половина жалобы
   на «появление ползунка»: дёргается не только он сам, но и весь набор рядом. На macOS
   полоса наложенная и ширины не занимает, поэтому видимой цены у правила здесь нет. */
.talk-scroll { flex: 1; min-height: 0; overflow-y: auto; scrollbar-gutter: stable; padding: 18px var(--frame-pad, 40px) 24px; }
/* ⚠ У РАЗГОВОРА ЕСТЬ МЕРА (правка владельца 19.08). Колонка тянулась во всю
   доступную ширину, и со свёрнутым столбиком этапов она доходила до 1900px:
   строка реплики в полторы тысячи пикселей не читается, а блок ответа, прижатый
   к правому краю такой колонки, отрывался от разговора на целый экран пустоты.
   Мера письма (--w-form) — верхняя граница и для разговора: всё, что участник
   читает и пишет, лежит в одной колонке текста, а не расползается по монитору. */

/* Первая шапка сцены в колонке не отбивается сверху: 38px нужны как РАЗДЕЛИТЕЛЬ
   между разговорами, а над первым разговором отбивать нечего — там край колонки. */
#talkCurrent > .sc-head:first-child { margin-top: 4px; }

/* прошлые разговоры — строкой, а не двенадцатью экранами прокрутки */
.talk-past { border-bottom: 1px solid var(--hairline); }
.talk-past > summary {
  list-style: none; cursor: pointer; display: flex; align-items: baseline; gap: 8px;
  padding: 10px 2px; font-size: var(--fs-dense); color: var(--muted);
}
.talk-past > summary::-webkit-details-marker { display: none; }
.talk-past > summary:hover { color: var(--ink); }
.talk-past-mark { color: var(--accent-ink); font-weight: 700; }
.talk-past-meta { margin-left: auto; font-size: var(--fs-util); color: var(--muted-soft); }
.talk-past-body { padding: 6px 0 18px; }
.recap-pointer { border-top: 1px solid var(--hairline); padding-top: 18px; }
/* Указатель, а не проза: 42ch резали одну строку на четыре куска по случайным
   местам. Здесь строка идёт по ширине рабочей области. */
.recap-pointer .section-lead { max-width: none; }
.recap-cost { display: block; font-size: var(--fs-util); color: var(--muted-soft); font-variant-numeric: tabular-nums; }

/* остаток ресурса рядом с набранным: арифметику «сколько ещё влезает» участник не
   должен делать в голове — её не меряет ни одна способность */
.bl-sum-item i { display: block; font-style: normal; font-size: var(--fs-util); color: var(--muted-soft); }
.bl-sum-item.is-over i { color: var(--accent-ink); }
.bl-mini-who { display: block; font-size: var(--fs-util); color: var(--muted-soft); }
.bl-locked-hint { color: var(--muted-soft); font-size: var(--fs-util); }
/* липкость счётчика — на обёртке: у самой .bl-sum высота равна высоте обёртки,
   двигаться внутри неё было некуда, и счётчик уезжал с восьмой позиции */
.bl-sum-host { position: sticky; top: 0; z-index: 3; background: var(--paper); }
.bl-host .bl-sum { position: static; }

@media (max-width: 1100px) {
  /* На узком экране паритет опоры хуже по построению: две зоны рядом не помещаются.
     Опора становится верхним слоем на всю ширину, разговор — под ней. Записано как
     ограничение, а не как решение: день рассчитан на компьютер. Блокировки нет —
     предупреждение (СПЕК §4.1). */
  .day-grid { grid-template-columns: minmax(0, 1fr) !important; grid-template-rows: minmax(0, 42%) minmax(0, 1fr); }
  /* ⚠ Здесь стояло .is-collapsed { grid-template-rows: 0 minmax(0, 1fr) } — правило
     писалось для колонки этапов, но на этой ширине колонки нет: первый ряд занимает
     ОПОРА (order: -1), и свёрнутые этапы обнуляли высоту пакета. Экран чтения со
     свёрнутыми этапами выглядел пустым: одна кнопка «Прочитал» на белом. */
  /* На экране чтения колонка работы скрыта (.is-reading > .talk), значит рядов
     остаётся два: пакет и этапы. Пакету — вся свободная высота, этапам — по
     содержимому; иначе пакет читался в 42% окна, а под ним висела пустота. */
  .day-grid.is-reading { grid-template-rows: minmax(0, 1fr); }
  /* ⚠ Колонка одна: явные grid-column от рельса надо снять, иначе работа и опора
     уезжают во вторую, неявную колонку. */
  .day-grid > .talk, .day-grid > .support { grid-column: 1 !important; }
  /* ⚠ ЗДЕСЬ ОПОРА ВОЗВРАЩАЕТСЯ НАВЕРХ — order, а не порядок узлов. Перестановка
     колонок 05.08 поставила работу перед опорой в DOM, и на узком экране это дало
     бы работу в первом ряду (42%), а опору во втором (58%): печатать в меньшей
     половине, читать пакет в большей — ровно наоборот к тому, что нужно. Ряды
     здесь неравные, поэтому решает не «центр» (его нет — колонка одна), а размер:
     работе достаётся 58%. Решение «опора сверху» принято раньше и не отменялось. */
  .support { order: -1; border-bottom: 1px solid var(--hairline); }
  /* линия шва «работа | опора» вертикальная — в один столбец ей нечего делить */
  .talk { border-right: none; }
  .talk-scroll { padding-left: 20px; padding-right: 20px; }
}

/* ═════════════════════════════════════════════════════════════════════════
   ЭКРАН v2, ревизия СПЕК §4 (2026-08-03). Действие справа и вне прокрутки;
   межсценовый экран поверх рабочей области; портфель компактными карточками
   с двумя столбиками результата.
   ═════════════════════════════════════════════════════════════════════════ */

/* ── ЗАПРЕТ С ТЕЛЕФОНА и требование к прохождению ──
   Не предупреждение: с телефона ассессмент не проходят. Планшет разрешён. */
.phone-block { max-width: 30rem; }
.phone-block h1 {
  font-family: var(--ff-display); font-weight: 800; font-size: var(--fs-hero-phone);
  line-height: 1.05; letter-spacing: -.015em; text-transform: uppercase; margin: 14px 0 0;
}
.phone-lead { font-size: var(--fs-read); line-height: 1.55; margin: 18px 0 0; }
.phone-tail { font-size: var(--fs-dense); line-height: 1.55; color: var(--muted); margin: 14px 0 0; }
.entry-req {
  font-size: var(--fs-dense); line-height: 1.55; color: var(--ink); margin: 16px 0 0; max-width: 42ch;
  padding: 12px 14px; background: var(--accent-tint); border: 1px solid var(--accent-line);
  border-radius: var(--radius);
}

/* ── ПОМЕТКИ: выписки из материалов, доступные на любом шаге ──
   Не указатель в текст, а сам фрагмент: смена версии кейса их не ломает. */
.tab-count { font-variant-numeric: tabular-nums; color: var(--muted-soft); }
.support-tab.is-on .tab-count { color: inherit; }
#supMarks.is-on { overflow-y: auto; padding: 16px var(--frame-pad, 24px) 28px; }

.mark-bar {
  flex: none; display: flex; align-items: center; gap: 12px;
  padding: 10px var(--frame-pad, 24px) 12px;
  border-top: 1px solid var(--hairline); background: var(--accent-tint);
}
.mark-bar-q {
  font-size: var(--fs-util); line-height: 1.4; color: var(--accent-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mark-bar .btn { margin-left: auto; flex: none; }

/* ── КНОПКА ОТМЕТКИ У ВЫДЕЛЕНИЯ ──
   position: fixed, потому что панель кейса прокручивается: позиционируй её внутри
   потока — уехала бы при первом колесе. Кегль служебный, вермилион не занимаем:
   главное действие на экране одно (DESIGN.md стр. 101), и это «Прочитал». */
.mark-pop { position: fixed; z-index: 40; }
.mark-pop-act {
  border: 1px solid var(--ink); background: var(--ink); color: var(--paper);
  border-radius: var(--radius); cursor: pointer; padding: 5px 12px;
  font: inherit; font-size: var(--fs-util); font-weight: 600;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .18);
}
.mark-pop-act:hover { background: var(--accent); border-color: var(--accent); }

/* ── ВОЗВРАТ ИЗ ПРИЛОЖЕНИЯ НА СТРОКУ ЧТЕНИЯ ──
   Липнет к верху панели: после прыжка в приложение глаз наверху, и кнопка должна
   быть там же, а не в конце документа. */
/* Возврат к чтению — ПЛАВАЮЩАЯ КНОПКА У НИЖНЕГО КРАЯ, поверх текста (решение
   владельца 06.08). Микрополоса вверху колонки этой работы не делала: уводила глаз
   от места, где он читает, и не читалась как действие. Кнопка не в потоке, поэтому
   текст под ней не сдвигается; position: sticky здесь не годится — прокручивается
   колонка целиком, и липкий низ ей недоступен. */
.case-back {
  position: absolute; z-index: 6; left: 0; right: 0; bottom: 18px;
  display: flex; justify-content: center; pointer-events: none;
}
.case-back-act {
  pointer-events: auto;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .18);
}

/* Ссылка на приложение в тексте кейса. Начертание то же, что задумано в самом
   кейсе (.appx-ref там уже описан), здесь только курсор и поведение ссылки без
   адреса — переход делает движок, а href="#" нужен для доступности с клавиатуры. */
#supCaseText .appx-ref { cursor: pointer; }
/* ⚠ ВНУТРИ ОТМЕТКИ ЛИНИЮ НЕСЁТ ОТМЕТКА. Ровно то же правило, что у mark.hl в
   кейсе: подчёркивание ссылки и штрих отметки в два яруса читаются как дефект
   вёрстки. Два селектора, потому что вложенность бывает обеих сторон — отметка
   красит текстовые узлы, а ссылки на приложения расставляются своим проходом, и
   кто окажется снаружи, зависит от порядка. Подчёркивание наследуется вниз и
   ребёнком не снимается, поэтому у внешней ссылки его снимаем через :has. */
#supCaseText .case-mk .appx-ref,
#supCaseText .appx-ref:has(.case-mk) { text-decoration: none; }

/* ── ШАПКА ПАКЕТА НА ЭКРАНЕ ЧТЕНИЯ ──
   Что за пакет и как работают пометки. Только здесь: в панели рядом с разговором
   это была бы инструкция на месте, где нужен текст. */
/* Шапка пакета лежит ПЕРВЫМ узлом внутри прокрутки и уезжает вместе с текстом:
   инструкцию читают один раз, а верх панели нужен всегда. Отступов по бокам у неё
   нет — их уже держит сам контейнер (.case-content padding), иначе врезка стояла бы
   уже текста на двойной отступ. */
.case-intro { margin: 0 0 18px; }
/* Кегль тот же, что у текста под ней: мера задана в ch, а ch считается по
   СОБСТВЕННОМУ кеглю элемента — при разных кеглях шапка и текст встали бы по разным
   границам, и это видно глазом (снимок 06.08: расхождение 20px). */
.case-intro-lead, .case-intro-marks { max-width: none; }
.case-intro-lead { margin: 0 0 10px; font-size: var(--fs-read); line-height: 1.6; color: var(--ink); }
/* Рамка-напоминание: во вкладке заметок и над письмом. Кегль читаемый, не
   служебный (правка владельца 07.08): её читают, а не сверяются с ней. */
.case-intro-marks {
  margin: 0 0 14px; padding: 14px 16px; border: 1px solid var(--hairline); border-radius: var(--radius);
  background: var(--soft); font-size: var(--fs-read); line-height: 1.55; color: var(--muted);
}
.case-intro-marks:empty { display: none; }
/* ⚠ В ВЕРСТАКЕ ЭТА РАМКА — УКАЗАТЕЛЬ, А НЕ ЧТЕНИЕ (правка владельца 21.08). Во
   вкладке заметок в ней абзац, который читают, — там кегль читаемый и остаётся.
   Над письмом в ней одна строка «где лежат прежние ответы»: на неё смотрят
   мельком, и читаемым кеглем она спорила с самим письмом. */
.mx-host .case-intro-marks { font-size: var(--fs-dense); }

/* Мера — та же, что у кейса и справки (см. .who-row): выписка и своя строка это
   бегущий текст, и на широком окне они шли на 110 знаков в строке. Поле под выписку
   не шире самой выписки: иначе оно обещает строку, которую неудобно читать. */
.mark-item { padding: 12px 0; border-bottom: 1px solid var(--hairline); }
/* ⚠ Мера — на самих строках, не на .mark-item: ch считается по кеглю элемента. */
.mark-quote {
  margin: 0 0 8px; padding-left: 12px; border-left: 2px solid var(--accent);
  font-size: var(--fs-dense); line-height: 1.55; color: var(--ink); max-width: 80ch;
}
.mark-note {
  width: 100%; max-width: 80ch; resize: vertical; padding: 8px 10px; border: 1px solid var(--hairline);
  border-radius: var(--radius); font: inherit; font-size: var(--fs-dense); line-height: 1.5;
  background: var(--paper);
}
.mark-acts { display: flex; align-items: center; gap: 12px; margin-top: 6px; }
.mark-act {
  border: none; background: none; cursor: pointer; padding: 2px 0; font: inherit;
  font-size: var(--fs-util); color: var(--muted-soft); text-decoration: underline;
}
.mark-act:hover { color: var(--ink); }/* короткая подсветка найденного места — вместо стрелки «вот здесь» */
.mark-flash { background: var(--accent-tint); transition: background .4s ease; }

/* Отмеченный фрагмент в тексте: подсветка тинтом акцента, набор не меняется.
   Вермилион не годится — он помечает действие (DESIGN.md стр. 101), а это след участника.
   ⚠ ШТРИХ БЫЛ ВЕРМИЛИОНОМ ВПРИТИРКУ ЧИСЛОМ (правка владельца 21.08). Приписка выше
   про «вермилион не годится» стояла над двумя жёсткими rgba(255,72,0, …): подмена
   семьи акцента на голубую (body.p-assess) их не видела, и отмеченный фрагмент
   оставался оранжевым — единственным оранжевым на всей странице ассессмента.
   ⚠ НАВЕДЕНИЯ БОЛЬШЕ НЕТ. Отметка тянется через несколько строк, и смена заливки
   под курсором давала мельтешение при каждом движении мыши по тексту. Отметка —
   это состояние («фраза взята»), а не кнопка: она обязана стоять неподвижно.
   Что фрагмент кликабельный, говорит курсор. */
.case-mk {
  background: var(--accent-tint); color: inherit;
  border-bottom: 1px solid var(--accent);
  cursor: pointer; border-radius: 2px;
}
/* Клик по подсветке подводит к своей выписке, и она мигает. */
.mark-item.is-hit { background: var(--accent-tint); transition: background .5s ease; }

/* Мера строки в режиме чтения. Таблицы приложений остаются во всю ширину. */
.day-grid.is-reading #supCaseText > .case-doc, .day-grid.is-reading #supCaseText article > p, .day-grid.is-reading #supCaseText article > h2, .day-grid.is-reading #supCaseText article > h3, .day-grid.is-reading #supCaseText article > ul, .day-grid.is-reading #supCaseText article > ol, .day-grid.is-reading #supCaseText article > blockquote {
  max-width: 80ch;
}

/* ── действие: у нижнего края колонки, справа, вне прокрутки ──
   Раньше кнопка лежала внутри прокручиваемого тела и уходила за край на 54px:
   до главного действия надо было доскроллить. Замер прототипа. */
.work-act {
  flex: none;
  display: flex; align-items: center; justify-content: flex-end;
  flex-wrap: wrap-reverse; gap: 8px 14px;
  padding: 12px var(--frame-pad, 24px) 16px;
  background: var(--paper); border-top: 1px solid var(--hairline);
}
.work-act:empty { display: none; }
/* wrap, а не wrap-reverse: разметка теперь [записка, кнопка], и при переносе
   кнопка обязана оставаться ПОД запиской, а не над ней. С wrap-reverse строки
   менялись местами, и порядок зависел от того, влезли они в одну строку или нет —
   отсюда и брался прыгающий вид. */
.work-act .win-foot { display: flex; align-items: center; justify-content: flex-end; gap: 8px 14px; flex-wrap: wrap; margin: 0; }
/* text-align: right снят: выключка только влево (DESIGN.md стр. 124). Сама
   записка прижата вправо раскладкой ряда (justify-content: flex-end), а текст
   внутри неё читается по левому краю. */
.work-act .win-note { max-width: 340px; }

/* ── межсценовый экран: перекрывает ТОЛЬКО работу ──
   Кейс и оглавление остаются на месте и читаются во время перехода; пустой
   экран на всю ширину прерывал бы чтение без нужды (СПЕК §4.4). */
.talk { position: relative; }
.interlude {
  position: absolute; inset: 0; z-index: 6; background: var(--paper);
  display: flex; flex-direction: column; overflow-y: auto;
}
/* Текст перехода стоит по центру рабочей области, а действие — в правом низу, в той
   же геометрии, что кнопка ответа (.work-act). До 04.08 кнопка «дальше» на этом
   экране висела слева посреди текста: за один день участник видел действие то
   слева, то справа, то в середине и искал его заново на каждом шаге. */
.interlude-body {
  /* ⚠ Заглушка между этапами центрируется по обеим осям (решение владельца 06.08):
     это пауза, а не экран с содержимым, и пустота вокруг текста — её форма. */
  flex: 1; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; justify-content: center;
  padding: 22px var(--frame-pad, 24px) 24px;
}
.interlude-in { max-width: var(--w-read); margin-inline: auto; width: 100%; }
.interlude-act {
  flex: none; display: flex; align-items: center; justify-content: flex-end;
  padding: 12px var(--frame-pad, 24px) 16px;
  border-top: 1px solid var(--hairline); background: var(--paper);
}
/* «✓ Ответ зафиксирован · ЧЧ:ММ». Был зелёный #2f7d32 — единственный цвет вне
   палитры DESIGN.md на всём экране дня. Та же галочка в ленте разговора и в
   строке прочитанного пакета уже стоит --accent-ink (.talk-past-mark,
   .case-done-mark): один знак — один цвет. */
/* Размер — как у заголовка следующего этапа (--fs-place): отметка закрывает
   предыдущий этап, а заголовок открывает следующий, и это одна пара. */
.interlude-mark { font-size: var(--fs-place); font-weight: 600; color: var(--accent-ink); margin: 0 0 26px; }
/* font-weight был не задан: дисплейная гарнитура наследовала 400 от body, то есть
   крупнейший текст экрана перехода рисовался светлым (DESIGN.md стр. 119: title — 700). */
.interlude-where { font-family: var(--ff-display); font-weight: 700; font-size: var(--fs-place); line-height: 1.15; margin: 0 0 6px; }
.interlude-when { font-size: var(--fs-dense); color: var(--muted-soft); margin: 0 0 26px; }
/* «Следующий этап N из 7:» — служебная строка над названием этапа (правка
   владельца 07.08). Тем же рецептом метки, что и остальные служебные строки. */
.interlude-next {
  font-family: var(--ff-body); font-weight: var(--label-weight);
  letter-spacing: var(--label-track); text-transform: uppercase; color: var(--muted-soft);
  margin: 0 0 6px;
}
/* .interlude-lead удалён 07.08 вместе со строками настроя (просьба владельца). */

/* ── портфель: компактные карточки, два ряда по десять ──
   Замер: 2×10 с доводом под «почему» — 2,6 экрана прокрутки; 1×20 с доводами —
   5,5; подробный вариант во всю ширину — 3,0 и без кейса. Выиграл компактный. */
.bl-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 12px; }
/* Карточка заявки — голубая, как поля ввода (решение владельца 07.08): всё, с чем
   участник работает руками, читается одним цветом. Свой вариант отличается рамкой
   (--jb-ink), а не заливкой. */
/* ⚠ НАПОМИНАНИЕ ПЕРЕД ПОЛЯМИ ОТВЕТА (решение владельца 26.08). Карточка отказанной
   заявки на шаге «разговор у выхода»: тот же вид, что в разборе заявок, но стоит она не
   в сетке, а одна над вопросами, поэтому нужна своя мера и воздух под ней. */
.win-card-ref { margin: 0 0 20px; max-width: 68ch; }
.win-card-ref .kicker { margin: 0 0 8px; }

.bl-card {
  border: 1px solid var(--band-line); border-radius: var(--radius);
  padding: 8px 12px; display: flex; flex-direction: column; gap: 6px; background: var(--band);
}
.bl-card-top { display: flex; align-items: baseline; gap: 8px; }
.bl-n { font-size: var(--fs-util); font-weight: 700; color: var(--muted-soft); font-variant-numeric: tabular-nums; }
.bl-card-cost {
  margin-left: auto; font-size: var(--fs-util); color: var(--muted-soft);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.bl-card-title {
  /* 600, а не 500: в системе четыре веса — 400/600/700/800 (DESIGN.md стр. 116) */
  font-size: var(--fs-dense); line-height: 1.35; font-weight: 600;
  /* ⚠ Обрезки в две строки здесь БОЛЬШЕ НЕТ (решение владельца 07.08). Заголовок
     заявки — то, по чему принимают решение; разворачивал его класс .bl-card.is-open,
     который ставила ссылка «почему», а её сняли вместе с прятаньем обоснований. */
}
.bl-card-who { font-size: var(--fs-util); color: var(--muted-soft); }
.bl-card-arg { font-size: var(--fs-util); line-height: 1.45; color: var(--muted); margin: 0; }
.bl-card-acts { display: flex; gap: 6px; align-items: center; }
.bl-why {
  margin-left: auto; border: none; background: none; cursor: pointer; padding: 4px 2px;
  font: inherit; font-size: var(--fs-util); color: var(--muted-soft); text-decoration: underline;
}
.bl-why:hover { color: var(--ink); }
/* решённая карточка уезжает не мгновенно: без этого следующая прыгает под курсор
   и второй клик попадает не туда (проверено на прототипе) */
@keyframes blLeave { to { opacity: 0; transform: translateY(-4px); } }
.bl-card.is-leaving { animation: blLeave .18s ease forwards; }

/* два столбика результата: портфель собирается на глазах, и перед вопросом
   «почему эти» листать список обратно не нужно */
.bl-cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 14px; align-items: start; }
.bl-col-head {
  /* ⚠ КРУПНЕЕ СВОИХ СТРОК (правка владельца 19.08). Стоял 12-м при строках 14-м
     и читался подписью к предыдущему блоку. Ступени 13 и 14 не чинят — они не выше
     строки; первая работающая ступень шкалы 16. */
  font-size: var(--fs-read); font-weight: 600; padding: 0 0 8px; margin-bottom: 8px;
  border-bottom: 1px solid var(--hairline);
}
.bl-col-head span { font-weight: 400; color: var(--muted-soft); }
.bl-row {
  display: grid; grid-template-columns: 20px 1fr auto; gap: 8px; align-items: baseline;
  padding: 8px 0; border-bottom: 1px solid var(--soft); font-size: var(--fs-util); line-height: 1.35;
}
.bl-row-t { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.bl-row-back {
  border: none; background: none; cursor: pointer; padding: 0 2px; font: inherit;
  font-size: var(--fs-util); color: var(--muted-soft); text-decoration: underline;
}
.bl-row-back:hover { color: var(--ink); }
/* Строка в стопке несёт две строки текста — заголовок и «автор · цена», — поэтому
   обрезка на двух строках срезала бы заголовок до одной. Три: два на заголовок,
   один на подпись. */
.bl-row-t:has(.bl-mini-who) { -webkit-line-clamp: 3; }
/* Переезд между стопками: две возможности в столбик, чтобы строка не растягивалась
   по ширине и стопка оставалась стопкой. */
.mx-row-moves { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }
.bl-zone-h {
  display: flex; align-items: baseline; gap: 8px; margin: 18px 0 8px;
}
.bl-zone-h b { font-size: var(--fs-util); letter-spacing: 0; text-transform: none; color: var(--ink); }
.bl-empty { font-size: var(--fs-util); color: var(--muted-soft); padding: 8px 0; }
/* «Почему именно так» после списка заявок: у .mx-card margin-top: 0, и карточка
   прилипала к последней заявке. */
.bl-list + .mx-card { margin-top: 18px; }
@media (max-width: 1360px) {
  /* колонок стало две, работа шире — карточки остаются в два ряда */
  .bl-grid { gap: 10px 14px; }
}
@media (max-width: 1100px) {
  .bl-grid, .bl-cols { grid-template-columns: minmax(0, 1fr); }
}

/* ═════════════════════════════════════════════════════════════════════════
   MX- — ОБЩИЕ ПЕРВОЭЛЕМЕНТЫ МЕХАНИК (js/mechanics.js, лор v4.4.f).
   Платформа держит классы по механике: bl- у разбора заявок. Семь механик лора
   делят карточку, группу полей и счётчик нормы, поэтому у общего — префикс mx-.
   Классы прототипа (.mech, .slot, .fan-ray, .table3, .years, .gauge) сюда НЕ
   переехали: прототип собрал свой параллельный словарь рядом с платформенным, и
   смысл «совместить с дизайном» ровно в том, чтобы словарь остался один.
   Ни одного нового цвета и размера: только токены системы.
   ═════════════════════════════════════════════════════════════════════════ */
.mx-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin: 18px 0 8px; }
.mx-title {
  font-family: var(--ff-body); font-weight: var(--label-weight);
  letter-spacing: var(--label-track); text-transform: uppercase; color: var(--muted-soft);
}
.mx-count { font-size: var(--fs-util); color: var(--muted-soft); font-variant-numeric: tabular-nums; }
/* ⚠ ЧИСЛО-СЧЁТЧИК НАБРАН КАК ЗАГОЛОВОК, ЧЕРЕЗ ТОЧКУ (правка владельца 23.08). Было
   мельче и другим цветом, да ещё со словом перед числом, которое повторяло сам
   заголовок: «Ваши рекомендации · рекомендаций: 1». Точка рисуется здесь, а не в
   разметке: так она не попадёт в текст, который читают сборщики подписей и судья.
   Отдельный класс, а не общий .mx-count: у счётчиков с пояснением («1 · рекомендуем
   до 12», «по желанию — можно не отвечать») кегль остаётся служебным. */
/* Кегль берём тем же токеном, что и заголовок внутри верстака: inherit тянул размер
   от строки-обёртки (16px), а заголовок там 14px, и счётчик выходил крупнее. */
/* ⚠ КЛАСС mx-tally, А НЕ mx-num: последний уже занят числовым ПОЛЕМ ВВОДА — рамка,
   ширина 6em, отступы. Я налетел на него 23.08, и у счётчика появилась обводка. */
/* Тем же шрифтом — значит и кегль, и вес, и цвет: иначе число читается как чужое.
   Вес берём из того же токена метки, что у заголовка.
   ⚠ ЦИФРЫ ПРОПОРЦИОНАЛЬНЫЕ, А НЕ ТАБЛИЧНЫЕ. У .mx-count стоят tabular-nums — они
   нужны там, где числа стоят в столбик и не должны прыгать. Здесь счётчик последний
   в строке, за ним ничего не сдвигается, а табличная цифра шире пропорциональной:
   у «1» появлялись боковые пробелы, и она читалась как набранная другим шрифтом. */
.mx-host .mx-count.mx-tally, .mx-ansbox .mx-count.mx-tally {
  font-size: var(--fs-dense); font-weight: var(--label-weight);
  font-variant-numeric: normal;
}
/* ⚠ ЛЕВОГО ПОЛЯ У ТОЧКИ НЕТ — ЕГО УЖЕ ДАЁТ FLEX. Замер 23.08: gap у .mx-head 10px
   плюс margin-left 8px давали 18px до точки и 8px после. Слева отступ рисует gap,
   справа — margin, поэтому справа ровно столько же, сколько в gap. */
.mx-title + .mx-count.mx-tally::before { content: "·"; margin: 0 10px 0 0; }
/* ⚠ НОРМА ВНУТРИ СЧЁТЧИКА — ЗАМЕЧАНИЕ, А НЕ ВЕЛИЧИНА (правка владельца 25.08).
   «(рекомендуем до 12)» лежит внутри .mx-tally, чтобы не получить flex-gap между
   числом и скобкой, — и поэтому наследует от него кегль заголовка и вес метки.
   Возвращаем ей служебный вид: число читается как часть заголовка, примечание — нет. */
.mx-count.mx-tally .mx-norm {
  font-size: var(--fs-util); font-weight: 400; color: var(--muted-soft);
  /* ⚠ ОТСТУП, А НЕ ПРОБЕЛ (правка владельца 25.08). Между числом и скобкой стоял
     обычный пробел, и при кегле 14px он давал 2,95px по замеру — против 10px у точки
     это читалось как склейка. Пробел не настраивается, поэтому он убран из разметки,
     а зазор задан здесь: 6px — заметно больше словесного пробела и заметно меньше
     тех 10px, что отделяют число от заголовка. Иерархия остаётся читаемой:
     «Наблюдения · 1 (примечание)», а не три равноудалённые части. */
  margin-left: 6px;
}

/* ══════════════════════════════════════════════════════════════════════════
   ОТВЕТ В ВЕРСТАКЕ = ОТВЕТ В ДИАЛОГЕ (решение владельца 19.08)
   Подпись поля вынесена НАД голубой карточкой, а сама карточка встала так же,
   как своя реплика в разговоре: три четверти колонки, прижата вправо, снизу
   ограничена 560px, сверху мерой письма. Раньше подпись лежала внутри голубого
   вместе с полем, и вопрос платформы выглядел частью ответа участника.
   Обёртка нужна, чтобы заголовок ехал вправо вместе с карточкой: иначе он
   оставался бы у левого края в отрыве от своего поля.
   ══════════════════════════════════════════════════════════════════════════ */
.mx-ansbox {
  /* ⚠ 2/3 И ПОРОГ 400px (правка владельца 19.08). Было 3/4 при пороге 560px,
     и при открытой панели материалов колонка ~460px — доля не срабатывала ни разу,
     ответ всегда занимал всю ширину. С порогом 400px смещение вправо видно и на
     узкой колонке, а места писать по-прежнему хватает. */
  width: 66.6%;
  min-width: min(100%, 400px);
  /* Воздух сверху: заголовок «Почему именно так» подходил вплотную к карточкам
     разбора и читался как подпись к последней из них. */
  margin: 22px 0 20px auto;
}
.mx-ansbox .mx-head { margin-top: 0; }
/* ⚠ ПОДПИСЬ ПОЛЯ — САМАЯ МЕЛКАЯ МЕТКА И БЕЗ КАПСА (правка владельца 21.08).
   Общий рецепт .mx-title поднимает подзаголовки до --fs-sub (16px) и ставит капс:
   это верно для НАЗВАНИЯ куска экрана («Наблюдения», «Варианты»), но подпись поля
   ответа — не название раздела, а метка, и в разговоре на три-четыре поля подряд
   она перекрикивала и реплику собеседника, и то, что участник в это поле пишет.
   --label-size (11px) — токен, прямо описанный как «метка, и только метка».
   Разрядка снята вместе с капсом: 0.1em держит строчные врозь и без капса читается
   как дефект набора. Сами подписи в реестре механик написаны с заглавной — значит
   снять text-transform достаточно, дописывать ничего не нужно. */
/* ⚠ ВСЕ заголовки верстака, а не только подписи полей: на экране цели рядом стоят
   подпись поля и заголовок ползунка («О каком периоде времени вы говорите?»), и два
   разных начертания на одном экране читаются как недоделка. Названия разделов
   («Наблюдения», «Варианты») тем же начертанием — они здесь такого же ранга. */
/* ⚠ ДВА СЕЛЕКТОРА, А НЕ ОДИН. .mx-host покрывает верстаки, но у окна на несколько
   вопросов (три вопроса Штерна) верстака нет вовсе — там карточки рисует движок,
   и по .mx-host они не попадали: подписи остались капсом в 16px, пока рядом на
   других шагах уже были строчными. Общее у обоих — .mx-ansbox. */
.mx-host .mx-title, .mx-ansbox .mx-title {
  /* ⚠ КЕГЛЬ ТЕКСТА В САМОМ ПОЛЕ (правка владельца 21.08). Сначала взяли самый
     мелкий в системе — --label-size (11px), — и подпись оказалась МЕЛЬЧЕ того, что
     участник в это поле пишет: вопрос читался тише ответа. Подпись обязана быть
     не мельче своего поля, поэтому --fs-dense: тот же кегль, что у .mx-input.
     Отличают её вес и цвет, а не размер. */
  font-size: var(--fs-dense);
  text-transform: none;
  letter-spacing: normal;
}
.mx-ansbox > .mx-card { margin-bottom: 0; }

/* Черта между разбором и разговором на экране печати. Волосяная, а не --line:
   --line в этой теме чёрный (#181818), и черта читалась как рамка. */
.mx-rule { border-top: 1px solid var(--hairline); margin: 22px 0 18px; }

/* Карточка заявки: номер в строку с названием, тем же кеглем и цветом и с точкой —
   иначе он читается как отдельная метка, а не как «третья заявка». Цена — внизу
   слева, по краю карточки, как итог под заявкой. */
.bl-card-title > .bl-n {
  color: inherit; font-size: inherit; font-weight: inherit;
  margin: 0 6px 0 0; font-variant-numeric: tabular-nums;
}
.bl-card-title > .bl-n::after { content: '.'; }
.bl-card-foot { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-top: auto; padding-top: 8px; }
.bl-card-foot .bl-card-cost { margin: 0 auto 0 0; }
.bl-card-foot .mx-acts { margin-left: 0; }
/* Автор заявки — курсивом: это подпись под названием, голос человека, а не факт
   о заявке. Цена — чёрным: это величина, по которой участник считает бюджет,
   и тише названия она быть не должна. */
.bl-card-who { font-style: italic; }
.bl-card-foot .bl-card-cost { color: var(--ink); }

/* ── КАРТОЧКА-ОТВЕТ СО СВОИМ НОМЕРОМ ──
   Номер стоит СНАРУЖИ голубого: внутри он занимал строку или отжимал поле, а это
   порядковый номер ответа, а не его часть. Подписи полей уехали внутрь как
   подсказки — подпись над полем и подсказка в поле говорили одно и то же дважды. */
.mx-item { display: flex; align-items: flex-start; gap: 10px; }
.mx-item > .mx-item-n {
  flex: none; padding-top: 14px; min-width: 1.2em; text-align: right;
  font-size: var(--fs-util); font-weight: 700; color: var(--muted-soft);
  font-variant-numeric: tabular-nums;
}
.mx-item > .mx-card { flex: 1 1 auto; min-width: 0; }
/* Ряд действий под полем и справа: метка и «убрать» — это то, что делают с уже
   написанным, значит стоят после него. */
.mx-acts-foot { justify-content: flex-end; margin-top: 8px; }
.mx-acts-foot:empty { display: none; }
/* Ряд под полем: опора слева, метка и «убрать» справа — соседи по смыслу. */
.mx-card-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 8px 0 0; }
.mx-card-row > .mx-acts { margin-left: auto; }

/* Кнопка «+ наблюдение» / «+ ещё связь» встаёт ровно под голубой карточкой:
   номер вынесен влево и сдвигает карточку на свою ширину плюс зазор, а кнопка
   раньше начиналась от края колонки и висела шире поля. */
/* Кнопка «+ …» лежит в такой же обёртке, что и карточки, с пустой клеткой
   номера: так она встаёт ровно под голубым полем при любой ширине. Двигать её
   margin'ом было нельзя — margin-left затирает auto, и группа теряла правое
   выравнивание. */
.mx-item > .mx-add { flex: 1 1 auto; min-width: 0; }

/* Сданный веер будущих: карточки гаснут, отмеченная остаётся голубой и с рамкой —
   видно, о каком именно варианте спрашивает Лемех. */
.mx-card.is-sealed { background: var(--soft); border-color: var(--hairline); }
.mx-card.is-sealed .mx-input { background: var(--soft); color: var(--muted); cursor: default; resize: none; }
.mx-card.is-sealed.is-first { background: var(--band); border-color: var(--jb-ink); }
.mx-card.is-sealed.is-first .mx-input { background: var(--paper); color: var(--ink); }

/* ── РАЗБОР ЗАЯВОК КАК ДОКУМЕНТ ──
   На печати участник смотрит не на список, а на то, что Агеев понесёт правлению.
   Поэтому лист: белое поле, рамка, поля по краям и скруглённые углы. Реплики
   Агеева остаются снаружи — он говорит про документ, а не внутри него. */
.mx-doc {
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  padding: 22px 24px 26px;
  margin: 0 0 4px;
  box-shadow: 0 1px 2px rgba(24, 24, 24, .04);
}
.mx-doc .mx-seal-total { margin-top: 0; }
.mx-doc > .bl-col-head:first-of-type { margin-top: 18px !important; }
.mx-doc .off-list:last-child { margin-bottom: 0; }

/* Номер ответа — у верхнего левого угла поля, а не строкой над ним. */
.mx-numrow { display: flex; gap: 8px; align-items: flex-start; }
.mx-numrow > .bl-n { flex: none; padding-top: 8px; font-variant-numeric: tabular-nums; }
.mx-numrow > .mx-input { flex: 1 1 auto; min-width: 0; }
/* Ряд действий без номера может остаться пустым — тогда он не занимает высоту. */
.mx-card-top:empty, .mx-card-top:has(> .mx-acts:empty) { display: none; }

/* «ВЫ» и отметка о фиксации держатся справа, как и сам пузырь. */
.win-fixed { text-align: right; }

/* ── ВЕРСТАК — ВО ВСЮ ШИРИНУ, ОДИНОЧНЫЙ ОТВЕТ — МЕССЕНДЖЕРОМ ──
   Решение владельца 28.08: «в тех шагах, где не просто окно для ответа на вопрос, а прям
   целый рабочий блок с разными окнами, — это будет во всю ширину области. И только когда
   нужно открытым текстом написать 1 ответ в окне без пояснений, тогда сохраняем формат
   мессенджера».
   ⚠ ЧТО ЗДЕСЬ СТОЯЛО. Пять верстаков (тезисы, варианты, будущие, цель, письмо) сжимались
   до 66,6% и прижимались вправо — «ответная область верстака = ответ в диалоге», правка
   19.08. На колонке ~627px это давало карточки по 418px при пустой левой трети, и владелец
   на снимке 28.08 показал ровно это: заголовки разделов и голубые карточки тезисов начинались
   от середины экрана. Разбор заявок и печать под то правило и тогда не попадали — у них
   верстак был полной ширины; теперь так у всех семи.
   Мера письма не нарушена: --w-form 880px, а полная ширина рабочей колонки при 1680 —
   627px, то есть шире меры карточка не станет ни на каком экране этой раскладки.
   ⚠ ЧТО ОСТАЛОСЬ МЕССЕНДЖЕРОМ, И ПОЧЕМУ ЭТО НЕ ИСКЛЮЧЕНИЕ. .s2-mine — это ответ на
   ПРОИЗНЕСЁННЫЙ вопрос: над ним «Вы», а выше пузырь собеседника. Это и есть «один ответ
   открытым текстом», формат которого владелец просил сохранить: второй такт вариантов и
   будущих спрашивают голосом Агеева и Лемеха. Поэтому .s2-mine из правила ниже убран и
   живёт по своему — 2/3 колонки, прижато вправо. .mx-ansbox (подписанное поле верстака)
   остаётся полной ширины: у него не реплика, а подпись. */
/* ⚠ ПРАВИЛО РАСПРОСТРАНЕНО НА ВСЕ ВЕРСТАКИ И ПОЛУЧИЛО МЕРУ (правка владельца 28.08).
   Список из пяти механик здесь остался от прежней раскладки: у разбора заявок и печати
   поле ответа сжималось до 66,6% и прижималось вправо. На широком экране это давало то,
   что владелец назвал «странно легло по диагонали»: сетка карточек кончается слева, а
   «Почему вы выбрали именно такой состав?» стоит внизу справа. По правилу владельца
   подписанное поле верстака — часть рабочего блока, а не реплика, значит полная ширина
   у всех семи. Мессенджером остаётся .s2-mine (ответ на произнесённый вопрос) и
   .mx-ansbox в ОКНАХ на несколько вопросов — там хост не .mx-host, и база 66,6% цела.
   max-width — мера письма, а не none: рабочая колонка на мониторе 2560 доходит до
   1274px, и поле без меры давало бы строку в полтораста знаков. */
.mx-host .mx-ansbox {
  width: 100%; min-width: 0; max-width: var(--w-form); margin-left: 0;
}
/* ⚠ ШКАЛА СРОКА — ПО ШИРИНЕ ПОЛЕЙ (правка владельца 28.08: «нужно, чтобы ползунок по ширине
   окон выравнивался для ответа»). Поля верстака держит мера письма (--w-form, правило выше),
   а ползунок и его подписи были прямыми детьми хоста и тянулись во всю колонку: на 1680 поля
   кончались на 880, шкала шла до 1594. Одна мера на весь верстак цели, чтобы правый край у
   всего, что участник заполняет, был один. */
.mx-host[data-mech="goal"] > * { max-width: var(--w-form); }

/* Кнопка «+ наблюдение» / «+ ещё связь» встаёт ровно под голубой карточкой:
   номер вынесен влево и сдвигает карточку на свою ширину плюс зазор, а кнопка
   раньше начиналась от края колонки и висела шире поля. */
/* Кнопка «+ …» лежит в такой же обёртке, что и карточки, с пустой клеткой
   номера: так она встаёт ровно под голубым полем при любой ширине. Двигать её
   margin'ом было нельзя — margin-left затирает auto, и группа теряла правое
   выравнивание. */
.mx-item > .mx-add { flex: 1 1 auto; min-width: 0; }

/* ── РАЗБОР ЗАЯВОК КАК ДОКУМЕНТ ──
   На печати участник смотрит не на список, а на то, что Агеев понесёт правлению.
   Поэтому лист: белое поле, рамка, поля по краям и скруглённые углы. Реплики
   Агеева остаются снаружи — он говорит про документ, а не внутри него. */
.mx-doc {
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  padding: 22px 24px 26px;
  margin: 0 0 4px;
  box-shadow: 0 1px 2px rgba(24, 24, 24, .04);
}
.mx-doc .mx-seal-total { margin-top: 0; }
.mx-doc > .bl-col-head:first-of-type { margin-top: 18px !important; }
.mx-doc .off-list:last-child { margin-bottom: 0; }

/* ── ДВЕ СТРАТЕГИИ ПРАВЛЕНИЯ В ЛИСТЕ (правка 6.3) ──
   Часть документа, а не реплики: блок стоит над разбором и отделён линией, как
   верхний колонтитул. Текст приходит из js/scenes.js. */
.mx-board { margin: 0 0 18px; padding: 0 0 16px; border-bottom: 1px solid var(--hairline); }
.mx-board > .bl-col-head { margin-top: 0; }
.mx-board-row { margin: 8px 0 0; font-size: var(--fs-util); color: var(--muted); line-height: 1.5; }
.mx-board-row b { color: var(--ink); }

/* Номер ответа — у верхнего левого угла поля, а не строкой над ним. */
.mx-numrow { display: flex; gap: 8px; align-items: flex-start; }
.mx-numrow > .bl-n { flex: none; padding-top: 8px; font-variant-numeric: tabular-nums; }
.mx-numrow > .mx-input { flex: 1 1 auto; min-width: 0; }
/* Ряд действий без номера может остаться пустым — тогда он не занимает высоту. */
.mx-card-top:empty, .mx-card-top:has(> .mx-acts:empty) { display: none; }

/* «ВЫ» и отметка о фиксации держатся справа, как и сам пузырь. */
.win-fixed { text-align: right; }

/* ⓘ у строки решения: список сжат до заголовков, а обоснование участник читал
   один раз на экране сортировки. Кружок открывает его на месте. */
.off-t { display: inline; }
.off-i {
  display: inline-flex; align-items: center; justify-content: center;
  width: 17px; height: 17px; margin-left: 7px; padding: 0;
  border: 1px solid var(--band-line); border-radius: 50%;
  background: var(--band); color: var(--jb-ink);
  font-family: var(--ff-body); font-size: var(--fs-op-sm); font-weight: 700; line-height: 1;
  cursor: pointer; vertical-align: 1px;
}
.off-i:hover { border-color: var(--jb-ink); }
.off-arg { display: none; }
li.is-open .off-arg {
  display: block; margin: 6px 0 0;
  font-size: var(--fs-dense); line-height: 1.55; color: var(--muted);
  border-left: 2px solid var(--band-line); padding-left: 10px;
}
.mx-opt { color: var(--muted-soft); font-weight: 400; }

.mx-card {
  border: 1px solid var(--hairline); border-radius: var(--radius);
  background: var(--paper); padding: 10px 12px; margin: 0 0 8px;
}
/* Отмеченный самый тревожный симптом и свой вариант в списке — «своё» помечено
   левой чертой цветом бренда: та же фигура, что у .dir в прототипе, но токеном. */
.mx-card.is-first, .bl-card.mx-own { border-color: var(--jb-ink); background: var(--band); }
/* Сданный веер во втором такте вариантов: карточки участника, поэтому голубые по
   общему правилу, но править их уже нельзя — рамка глуше, номер тише. Классы
   .mx-card-ro и .mx-ray-gist появились 14.08 вместе со вторым тактом и до 18.08
   не имели ни одного правила: текст ложился дефолтным кеглем. */
.mx-card-ro { border-color: var(--band-line); }
.mx-card-ro .bl-n { color: var(--muted-soft); }
.mx-ray-gist { font-size: var(--fs-dense); line-height: 1.55; color: var(--ink); }
.mx-card-top { display: flex; align-items: baseline; gap: 8px; margin: 0 0 6px; }
.mx-acts { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; }
/* ⚠ Ряд решений прижат к НИЗУ карточки (правка 07.08). Карточки в строке грида равны
   по высоте, а текста в них разное количество: после того как заголовки перестали
   обрезаться, кнопки «берём · не сейчас · не делаем» встали на разной высоте и прыгали
   от карточки к карточке. margin-top: auto ставит их на одну линию. */
.bl-card > .mx-acts { margin-top: auto; padding-top: 6px; }
.mx-flag {
  font-size: var(--fs-util); font-weight: 700; color: var(--jb-ink);
  text-transform: uppercase; letter-spacing: var(--label-track);
}
/* выбранное решение — не подсветка «правильного», а отметка поступка */
.s2-act.is-on { border-color: var(--jb-ink); color: var(--jb-ink); font-weight: 600; }

.mx-label { display: block; font-size: var(--fs-util); color: var(--muted-soft); margin: 8px 0 3px; }
.mx-input {
  width: 100%; border: 1px solid var(--hairline); border-radius: var(--radius);
  padding: 7px 9px; font-family: inherit; font-size: var(--fs-dense); line-height: 1.55;
  color: var(--ink); background: var(--paper); resize: vertical;
}
/* ⚠ Акцент помечает ДЕЙСТВИЕ (кнопку), а не поле (DESIGN.md стр. 101). Поля
   участника — голубые, как всё, что он производит; фокус голубой рамкой. */
.mx-input:focus { outline: none; border-color: var(--jb-ink); background: var(--paper); }
/* ⚠ ВЫСОТА ПОЛЕЙ ОДНА И РАСТЁТ ПОД ТЕКСТ (правка владельца 19.08). Высота
   задавалась атрибутом rows и была разной на разных шагах — от двух строк до
   девяти. overflow скрыт: полосу прокрутки внутри поля заменяет рост самого поля;
   resize оставлен вертикальный — участник вправе растянуть сам. */
textarea.mx-input, textarea.win-input { overflow-y: hidden; }
textarea.mx-input-thin { overflow: hidden; }

/* Раскрытая свёртка показывает весь монолог по порядку — оставленные пузыри
   прячутся, иначе конец монолога шёл бы дважды. */
details.talk-folded[open] + .talk-kept { display: none; }
/* Логистика перехода на межэтапном экране: крупнее строки настроя, но тише места и
   времени — это рассказ о том, что произошло между этапами. */
.interlude-bridge { margin: 10px 0 18px; }
.interlude-bridge-p { margin: 0 0 6px; font-size: var(--fs-read); line-height: 1.6; color: var(--ink); }

/* ── СВЁРНУТЫЙ МОНОЛОГ ПРОЙДЕННОГО ШАГА ── */
/* Ряд «Ответить» внутри своей карточки: прижат вправо, как и подвал колонки, —
   действие всегда у правого края, где бы оно ни стояло. */
.mine-act { display: flex; justify-content: flex-end; margin-top: 10px; }
/* Реплики, которые остаются на экране, пока участник отвечает (14.08). Своей рамки
   у них НЕТ намеренно: это те же пузыри разговора, просто не уехавшие в свёртку.
   Рамка сделала бы из них «блок с заданием», то есть анкету вместо разговора. */
.talk-kept { border: 0; background: none; padding: 0; }
.talk-kept + .talk-folded { margin-top: 10px; }
.talk-folded { border: 1px solid var(--hairline); border-radius: var(--radius); background: var(--soft); }
.talk-folded-sum {
  display: flex; align-items: baseline; gap: 10px; cursor: pointer; list-style: none;
  padding: 10px 14px; font-size: var(--fs-util); color: var(--muted);
}
.talk-folded-sum::-webkit-details-marker { display: none; }
.talk-folded-t {
  font-family: var(--ff-body); font-size: var(--label-size); font-weight: var(--label-weight);
  letter-spacing: var(--label-track); text-transform: uppercase; color: var(--muted-soft);
}
.talk-folded-n { margin-left: auto; color: var(--muted-soft); }
.talk-folded-sum:hover .talk-folded-n { color: var(--ink); }
.talk-folded[open] { background: var(--paper); }
.talk-folded-body { padding: 0 14px 8px; }

/* Карточка тезиса как цель перетаскивания пометки. Подсветка только пока курсор
   над ней: постоянная рамка обещала бы приём там, где ничего не тащат. */
.mx-card.is-drop { border-color: var(--jb-ink); background: var(--band); }
.mark-quote[draggable="true"] { cursor: grab; }
.mark-quote[draggable="true"]:active { cursor: grabbing; }

/* ── ПАКЕТ КАК АККОРДЕОН ──
   Свёрнутые разделы и есть оглавление кейса (решение владельца 06.08): отдельной
   колонки оглавления нет, четыре зоны на экране — перебор. Свёртка рисуется строкой
   с линейкой сверху: список заголовков читается как содержание, а не как набор
   кнопок. Ни одного нового цвета — --hairline, --soft, --muted, --ink. */
/* Полоса управления пакетом стоит НАД прокруткой, отдельным узлом панели.
   Внутри прокрутки она была sticky и оставляла зазор в верхнем отступе: в него
   пролезала строка текста и читалась поверх полосы (снимок 06.08). Отрицательные
   отступы этот зазор закрывали лишь отчасти, а платой была вылезающая наверх строка. */
.case-bar {
  flex: none; display: flex; align-items: baseline; gap: 12px;
  padding: 10px var(--frame-pad, 24px);
  background: var(--paper); border-bottom: 1px solid var(--hairline);
}
.case-bar-k {
  font-family: var(--ff-body); font-size: var(--label-size); font-weight: var(--label-weight);
  letter-spacing: var(--label-track); text-transform: uppercase; color: var(--muted-soft);
  margin-right: auto;
}
.case-bar-act {
  border: none; background: none; padding: 0; cursor: pointer;
  font: inherit; font-size: var(--fs-util); color: var(--muted); text-decoration: underline;
}
.case-bar-act:hover { color: var(--ink); }

.case-block { border-top: 1px solid var(--hairline); }
.case-block:first-of-type { border-top: none; }
.case-sum {
  display: flex; align-items: baseline; gap: 10px; cursor: pointer; list-style: none;
  padding: 12px 0; color: var(--ink);
}
.case-sum::-webkit-details-marker { display: none; }
.case-sum-t { font-family: var(--ff-display); font-weight: 700; line-height: 1.25; }
/* Значок состояния — плюс/минус текстом, а не стрелка-глиф: стрелка в этой
   гарнитуре съезжает по базовой линии, а знак стоит ровно. */
.case-sum-mark { margin-left: auto; flex: none; color: var(--muted-soft); font-size: var(--fs-util); }
/* Знак, а не слово: разделов семнадцать, и «развернуть» семнадцать раз — шум.
   Словами это сказано один раз, в полосе управления над пакетом. */
.case-sum-mark::before { content: '+'; }
.case-block[open] > .case-sum .case-sum-mark::before { content: '−'; }
.case-sum-mark { font-size: var(--fs-read); line-height: 1; }
.case-block[open] > .case-sum { border-bottom: 1px solid var(--soft); }
.case-sum:hover .case-sum-mark { color: var(--ink); }
.case-block > article { padding: 4px 0 18px; }

/* ── ЭКРАНЫ ПЕРЕД СТАРТОМ (intro.html, role.html) ──
   Раскладка общая на два экрана: одна колонка чтения, метки системным .kicker,
   пункты нумерованными кружками. Своих цветов и кеглей здесь нет — только те же
   токены; из v1 (intro2.html) стили переехали в общий файл, потому что теперь их
   два экрана, а не один, и копия разъехалась бы при первой же правке. */
/* Настройка и роль — один шаблон и одна шкала (решение владельца 07.08). Рамка та же,
   что у остальных страниц (var(--maxw)), а не 760px: заголовок здесь был уже, чем на
   входе и в кабинете. Мера строки при этом держится не рамкой, а колонками внутри. */
.intro { max-width: var(--maxw); margin: 0 auto; padding: 0 clamp(18px, 4vw, 40px); min-height: 100vh; display: flex; flex-direction: column; }
/* Группы принципов — в два столбика от 1100px: ширину рамки заполняет содержимое, а
   мера строки в каждом столбике остаётся своей. Заголовок и лид всегда во всю ширину. */
.intro-cols { display: block; }
/* ── РЯД ПОДЗАГОЛОВКОВ ──
   Тонкая линия над рядом — во всю ширину блока, а не по колонке: бордюр у каждой
   колонки дал бы две линии с разрывом посередине (правка владельца 07.08). */
.intro-row {
  display: grid; grid-template-columns: minmax(0, 1fr);
  gap: 0 clamp(24px, 4vw, 56px); align-items: start;
  border-top: 1px solid var(--hairline); padding-top: 8px; margin-top: 30px;
}
@media (min-width: 1100px) {
  .intro-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* ⚠ РЯД С ОДНИМ БЛОКОМ — ВО ВТОРУЮ КОЛОНКУ (правка владельца 26.08). Поле имени
     обязано стоять над кнопкой «Приступить», то есть справа, — а линейка над ним
     обязана идти во всю ширину блока (решение 07.08). Одно без другого не выходит:
     вложить блок в правую колонку соседнего ряда значит потерять линейку, а оставить
     своим рядом без сдвига — увести поле налево, через весь второй столбец от кнопки.
     Отдельный ряд плюс сдвиг решают оба требования сразу. */
  .intro-row-name > * { grid-column: 2; }
}
.intro-head { display: flex; align-items: baseline; justify-content: space-between; padding: 22px 0 18px; border-bottom: 1px solid var(--hairline); }
.intro-hero { padding: 40px 0 6px; }
/* Кегль заголовка ОДИН на обеих страницах. Было: 46px на настройке (инлайновый стиль
   в intro.html) и 76px на роли (общее правило h1) — один шаблон с двумя голосами. */
/* Отступ ПОСЛЕ заголовка больше, чем до него: заголовок принадлежит тому, что за ним.
   Замер 07.08: до h1 было 14px, после — 0 (правило #roleLead .lead { margin: 0 }
   затирало отступ, и лид стоял вплотную к 60px заголовку). Ниже — 0,4 кегля. */
/* ⚠ max-width: none обязателен: у лендингового h1 стоит max-width: 16ch (стр. 311),
   а «Как проходить ассессмент» — 24 знака, и заголовок рвался на две строки при
   свободных 900px справа. Кегль я правил 07.08, а рвал строку не кегль, а этот
   потолок. */
.intro-hero h1 { font-size: var(--fs-hero); font-weight: 800; text-transform: uppercase; letter-spacing: -.015em; line-height: 1.02; margin: 10px 0 0.4em; max-width: none; }
/* ⚠ ЭТА ФРАЗА КРУПНЕЕ ОСТАЛЬНОГО ТЕКСТА (правка владельца 25.08). Она стоит первой
   и объясняет, зачем всё дальше; на общем кегле чтения она читалась наравне с
   инструкциями ниже. Вместе с кеглем поднят и цвет: у .section-lead он приглушённый,
   а приглушённый крупный текст выглядит выключенным, а не важным.
   ⚠ МЕРУ НЕ ПЕРЕСЧИТЫВАЕМ. Я сузил её до 42ch, решив, что «при 20px строка станет
   длиннее читаемой», — и это неверно: ch считается от СОБСТВЕННОГО кегля элемента,
   значит 62ch остаются теми же 62 знаками, просто шире в пикселях. От сужения фраза
   развалилась на четыре короткие строки под огромным заголовком. 62ch как было. */
.intro-hero .lead {
  margin-top: 16px; max-width: 62ch;
  font-size: var(--fs-lead); line-height: 1.5; color: var(--ink);
}
.intro-hero .lead b { color: var(--ink); }
.pgroup { margin-top: 34px; }
/* ⚠ ЛИНЕЙКИ МЕЖДУ ПУНКТАМИ УБРАНЫ (правка владельца 25.08). Они стояли здесь с самого
   начала, но заметны стали, когда шестой пункт поехал из отдельного контейнера: внутри
   него он :first-of-type, линейки не получил — и разнобой стал видно. Владелец решил в
   пользу «линеек быть не должно»: номер в кружке и так делит пункты, а линейка на
   каждом превращала список в таблицу. Отступа 13px сверху и снизу хватает.
   Касается и второй страницы — .prin там же, это один компонент. */
.prin { display: flex; gap: 14px; padding: 13px 0; }
.prin .n {
  /* номер принципа — служебный кегль, не свой */
  flex: none; width: 26px; height: 26px; border-radius: 50%; border: 1.5px solid var(--ink);
  font-size: var(--fs-util); font-weight: 700; display: flex; align-items: center; justify-content: center;
}
/* Мера строки на экранах перед стартом: страница 760px, и при кегле 15px строка
   набегала на 76 знаков — на волосок выше нормы (45–75, потолок WCAG 80). Заголовкам
   ширина нужна, бегущему тексту — нет, поэтому мера стоит на самом тексте. */
.prin .t { font-size: var(--fs-read); line-height: 1.5; color: var(--ink); max-width: 68ch; }
.prin .t b { font-weight: 700; }
/* «про ИИ» — единственный акцент-блок: это важно проговорить прямо */
.prin.accent .n { border-color: var(--accent); color: var(--accent); }
/* Логистика — та же секция, но без нумерации: нумерованное = принципы,
   ненумерованное = справка. Различие намеренное, а не «дописали в конце». */
/* ⚠ ОСНОВНЫМ ЦВЕТОМ, А НЕ ПРИГЛУШЁННЫМ (правка владельца 26.08). Этим стилем набран
   блок «Что в итоге» — единственный абзац первой страницы, отвечающий «зачем я это
   делаю»; приглушённым он читался как сноска. Кегль не меняем: он и так --fs-read, то
   есть кегль чтения, — важность даёт цвет. Это ЕДИНСТВЕННЫЙ рецепт .intro-note: второй,
   что стоял выше в файле, сведён сюда. */
.intro-note { padding: 13px 0; border-top: 1px solid var(--hairline); font-size: var(--fs-read); line-height: 1.5; color: var(--ink); }
.intro-note > *, .intro-note { max-width: 68ch; }
.intro-note:first-of-type { border-top: none; }
/* «Чего платформа не умеет» — ОДИН текст, а не список: линейка между абзацами
   разделяла то, что читается подряд (замечание владельца 07.08). */
#roleHow .intro-note { border-top: none; padding: 0; margin: 0; }
.intro-note b { color: var(--ink); font-weight: 700; }
/* Первый вопрос в абзаце — жирным (правка владельца 07.08): он и есть то, что
   спрашивают, остальное — пояснение. */
.intro-name p b { color: var(--ink); font-weight: 700; }
.intro-disclaimer { margin-top: 28px; font-size: var(--fs-read); line-height: 1.5; color: var(--muted); }
/* ⚠ :not(.kicker) обязателен: без него это правило перебивало рецепт метки — у
   «.intro-name p» специфичность выше, — и «ПРЕЖДЕ ЧЕМ НАЧАТЬ» шёл 16px против 11px
   у соседних меток. Поймано владельцем 07.08. */
.intro-name p:not(.kicker) { font-size: var(--fs-read); font-weight: 400; line-height: 1.5; color: var(--muted); margin: 0 0 10px; max-width: 68ch; }
.intro-name input {
  width: 100%; max-width: 380px; border: 1px solid var(--hairline); border-radius: var(--radius);
  padding: 11px 12px; font: inherit; font-size: var(--fs-read); color: var(--ink); background: var(--paper);
}
.intro-name input:focus { outline: none; border-color: var(--jb-ink); }
/* ⚠ ПУСТОЕ ПОЛЕ ПОСЛЕ ПОПЫТКИ УЙТИ (правка владельца 25.08). Красным помечаем только
   после нажатия на «Приступить», а не сразу: подсвечивать поле, к которому человек
   ещё не подходил, значит ругать его до первой ошибки. Снимается на первом же вводе. */
.intro-name input.is-empty { border-color: var(--accent); }
.intro-name-warn {
  margin: 8px 0 0; font-size: var(--fs-util); color: var(--accent-ink);
}
.intro-name-warn[hidden] { display: none; }
/* ⚠ Поле имени и «Приступить» стоят ОДНОЙ СТРОКОЙ (правка владельца 26.08). Прежде
   кнопка была отдельным рядом ниже, во всю ширину страницы, а поле прижималось к правому
   краю столбца (margin-left: auto), чтобы встать с ней на одну вертикаль. Теперь они
   рядом, и поле выровнено по левому краю своего столбца — как весь текст над ним. */
.intro-name-row { display: flex; align-items: center; flex-wrap: wrap; gap: 12px 16px; margin-top: 12px; }
.intro-name-row input { flex: 1 1 220px; margin-top: 0; }
/* ⚠ КНОПКА — К ПРАВОМУ КРАЮ СТРАНИЦЫ (правка владельца 28.08). «Как устроен ассессмент»
   и «Приступить» стояли в разных местах и прыгали между двумя экранами: на первом кнопка
   лежит в своём ряду .intro-cta с justify-content: flex-end, то есть ровно у правого края
   содержимого (1565 при 1680), а здесь шла сразу за полем имени и кончалась на 1417 —
   148px левее. Поле остаётся рядом с кнопкой (решение 26.08: они одной строкой), но пустое
   место между ними отдаём margin-left: auto, и правый край у кнопки на обоих экранах один. */
.intro-name-row .btn { flex: none; margin-left: auto; }
/* Ряд действия — та же геометрия, что у ответа в ассессменте (.win-foot): записка
   слева, кнопка справа и по размеру своей подписи. Кнопка во всю ширину тянулась на
   широком окне до бесконечности и не совпадала ни с одним другим экраном. */
.intro-cta { margin: 40px 0; display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 8px 16px; }
.intro-cta .intro-next { margin: 0; max-width: 62ch; flex: 1 1 260px; }
.intro-cta .btn { flex: none; }
/* ⚠ ПОДВАЛ НЕ ЛИПНЕТ К СОДЕРЖИМОМУ НА НИЗКОМ ОКНЕ (правка владельца 28.08). Зазор над
   ним держал `margin-top: auto` — то есть свободное место страницы; когда содержимое
   заполняет высоту, свободного места нет, и линия подвала оказывается вплотную под полем
   имени и кнопкой «Приступить». Поэтому зазор задан последнему ряду содержимого явно:
   в колонке-флексе отступы не схлопываются, и эти 30px резервируются раньше, чем auto
   разберёт остаток. */
.intro-row:last-of-type { margin-bottom: 30px; }
/* Подвал — ряд: подпись слева (её место одно на обоих экранах), ссылка назад справа.
   На первом экране в ряду только подпись, и flex-строка её не двигает. */
.intro-foot {
  margin-top: auto; border-top: 1px solid var(--hairline); padding: 16px 0 30px;
  font-size: var(--fs-util); color: var(--muted-soft);
  display: flex; align-items: baseline; justify-content: space-between; gap: 16px; flex-wrap: wrap;
}
.intro-back { color: var(--muted); text-decoration: none; }
.intro-back:hover { color: var(--ink); text-decoration: underline; }
/* Роль на своём экране: абзацы истории читаются как проза, а не как лид-врезка. */
/* Введение в роль — ДВА СТОЛБИКА на широком окне (решение владельца 07.08: «текста
   много, пусть растягивается»). Во всю ширину растянуть нельзя: 1472px это 160 знаков
   в строке при норме 80. Два столбика заполняют ширину и держат меру в каждом. */
#roleLead { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0 clamp(24px, 4vw, 56px); }
@media (min-width: 1100px) { #roleLead { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
#roleLead .lead { max-width: none; margin: 0 0 12px; }

.mx-input-thin { margin-top: 6px; }
/* ── ОПОРА ТЕЗИСА НА ВЫПИСКУ ──
   Цитата рисуется тем же .mark-quote, что и во вкладке «Пометки»: это одна и та же
   вещь, и выглядеть она обязана одинаково — иначе выписка в тезисе читается как
   другой объект. Здесь только рамка вокруг неё, без новых цветов и кеглей. */
.mx-anchor { margin-top: 6px; padding: 8px 10px; border: 1px solid var(--hairline); border-radius: var(--radius); }
.mx-anchor-k { display: block; font-size: var(--fs-util); color: var(--muted-soft); margin-bottom: 6px; }
.mx-anchor .mark-quote { margin-bottom: 8px; }
.mx-anchor-pick {
  display: block; width: 100%; text-align: left; margin-bottom: 6px; cursor: pointer;
  border: 1px solid var(--hairline); border-radius: var(--radius); background: var(--paper);
  padding: 6px 8px; font: inherit; font-size: var(--fs-util); color: var(--muted); line-height: 1.5;
}
.mx-anchor-pick:hover { border-color: var(--accent); color: var(--ink); }
/* ⚠ ОТСТУП СНЯТ (правка владельца 28.08). «Приложить заметку» стояла на несколько
   пикселей ниже соседней «Самое тревожное наблюдение»: у неё одной был margin-top: 6px —
   наследство от времён, когда кнопка висела под полем сама по себе. Сейчас она лежит в
   .mx-card-row с align-items: center, и собственный отступ смещает её относительно
   соседей. Ряд задаёт вертикаль сам, кнопке своего отступа не нужно.
   Класс оставлен: по нему кнопка отличается от прочих .s2-act в разметке. */
.mx-anchor-open { margin-top: 0; }
/* Пунктир — место под то, что напишет участник, значит он голубой, как и всё
   его: и в покое, и под курсором. Вермилион здесь помечал бы действие платформы. */
.mx-add {
  border: 1px dashed var(--band-line); background: var(--paper); color: var(--muted);
  border-radius: var(--radius); font: inherit; font-size: var(--fs-dense);
  padding: 7px 12px; cursor: pointer; width: 100%; text-align: left;
}
.mx-add:hover:not(:disabled) { border-color: var(--jb-ink); color: var(--ink); }
.mx-add:disabled { opacity: .45; cursor: default; }
/* Реплика собеседника ВНУТРИ верстака (вопрос Лемеха под карточками будущего,
   вопрос Агеева в чате правления) начинается с отступа: вплотную к полю пузырь
   читался как подпись последнего поля, а не как сказанное вслух. */
.mx-add + .chat, .mx-card + .chat, .mx-seal-total + .chat, .s2-mine + .chat { margin-top: 18px; }
.mx-hint { font-size: var(--fs-util); color: var(--muted-soft); margin: 8px 0 3px; }

/* слот симптома: метка-заголовок, без стрелки и без глагола (лор §С1) */
.mx-slot {
  border: 1px dashed var(--band-line); border-radius: var(--radius);
  padding: 10px 12px; background: var(--band); margin: 12px 0 0;
}
.mx-quote { font-size: var(--fs-dense); line-height: 1.55; margin: 6px 0 0; }

/* связки */
.mx-link { border: 1px solid var(--band-line); background: var(--band); border-radius: var(--radius); padding: 10px 12px; margin: 0 0 8px; }
.mx-link-n { font-size: var(--fs-util); font-weight: 700; color: var(--jb-ink); }
.mx-link-refs { font-size: var(--fs-util); color: var(--muted); margin: 4px 0 8px; line-height: 1.5; }
.mx-pick { display: flex; align-items: flex-start; gap: 8px; font-size: var(--fs-dense); line-height: 1.45; padding: 3px 0; }
.mx-pick input { margin-top: 3px; }

/* вилка финансистов: пределы — текстом, выбор участника — двумя числами */
.mx-band { white-space: normal; }
.mx-pair { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 6px 0 0; font-size: var(--fs-util); color: var(--muted-soft); }
.mx-num {
  width: 6em; border: 1px solid var(--hairline); border-radius: var(--radius);
  padding: 4px 6px; font: inherit; font-size: var(--fs-util);
  text-align: right; font-variant-numeric: tabular-nums;
}
.mx-num:focus { outline: none; border-color: var(--jb-ink); background: var(--paper); }

/* Взятый свой вариант в столбике «Берём» остаётся с полями вилки: строка
   раскрывается на всю ширину и отдаёт третий ряд под пределы и два числа. Без
   этого участник попадал в тупик — гейт требовал число, а поля уезжали вместе с
   карточкой (поймано стендом механик). */
.bl-row.mx-row-wide { grid-template-columns: 20px 1fr auto; }
.mx-row-band { grid-column: 1 / 4; margin: 2px 0 4px; }
.mx-row-band .mx-label { margin-top: 6px; }

/* ТРИ СТОПКИ РЕШЕНИЙ вместо двух: «не сейчас» и «не делаем» разведены поступком,
   иначе псевдо-отказ (L2) и настоящий выбор (пол L3) неразличимы.
   ⚠ СТОПКИ ИДУТ ПОЛОСАМИ, А НЕ СТОЛБИКАМИ, И ЭТО ЗАМЕР, А НЕ ВКУС. Замерено 05.08
   на живом дне: рабочая колонка отдаёт хосту механики 474px при окне 1440, 554 при
   1600, 714 при 1920. Три столбика влезают только на 1920 и дают по 230px — на этой
   ширине заголовок заявки занимает три строки, а подпись «автор · столько человек ·
   столько денег» обрезкой съедается совсем. Именно она и делает стопку читаемой:
   без неё участник, чтобы понять, из чего сложились 785 человек, обязан помнить
   цены наизусть. Поэтому раскладка ОДНА на всех ширинах — три полосы во всю ширину
   колонки, каждая в рамке (.mx-pile). Два варианта раскладки здесь означали бы, что
   на 1920 механика теряет данные, которых на 1440 не теряет. */
.bl-cols.mx-cols3 { grid-template-columns: minmax(0, 1fr); }
/* ── СТОПКА КАК ПРЕДМЕТ ──
   Замер 05.08: рабочая колонка — 474px на 1440, 554 на 1600, 537 на 1280, 714 на
   1920. Три столбика в ряд дают по 150–230px, то есть рваный заголовок и съеденную
   подпись, поэтому стопки идут полосами (см. .bl-cols.mx-cols3 выше). Полосой это
   раньше читалось одним плоским списком с подзаголовками: «раскладывания» не
   было видно, хотя оно здесь и есть поступок. Рамка возвращает предмет: три стопки
   вместо трёх подзаголовков. Ни одного нового цвета — --paper, --hairline, --soft. */
.mx-pile {
  border: 1px solid var(--hairline); border-radius: var(--radius);
  background: var(--paper); padding: 8px 10px 2px;
}
.mx-pile + .mx-pile { margin-top: 8px; }
.mx-pile .bl-col-head { margin-top: 0; }
/* Последняя строка стопки без разделителя: он рисовал линию вдоль дна рамки. */
.mx-pile .bl-row:last-child { border-bottom: none; }
.mx-pile .bl-empty { margin: 4px 0 8px; }

/* Карточки нерешённого НЕ трогаем: два ряда в 587px дают 285px на карточку и так
   живут с 03.08, а за узкий экран отвечает медиазапрос ≤1100 выше. Второе правило
   на тот же класс дало бы два источника правды на одну раскладку. */

/* печать (С3б): итог крупно, список раздельно и в лицо */
.mx-seal-total {
  /* Ступенью ниже (20): 26 — это кегль заголовка этапа, внутри листа он спорил
     с самим листом. */
  font-size: var(--fs-op-xl); font-weight: 700; font-variant-numeric: tabular-nums;
  padding: 0 0 4px;
}
/* Строка списка на печати повторяет строку стопки: заголовок, под ним автор и
   цена. Заказ владельца 09.08 — участник должен видеть, из чего сложился итог,
   а не сверять заголовки с памятью. */
.off-list { list-style: none; margin: 0; padding: 0; }
.off-list li {
  padding: 8px 0; border-bottom: 1px solid var(--soft);
  font-size: var(--fs-dense); line-height: 1.4;
}
.off-list li:last-child { border-bottom: 0; }
/* ⚠ ЗАЯВКА, НА КОТОРОЙ НАСТОИТ ПРАВЛЕНИЕ (правка владельца 28.08). В листе из двадцати
   строк искать её глазами по названию из реплики Агеева — работа, к замеру не относящаяся.
   Тот же голубой, которым помечено всё, с чем участник работает руками (--band и его линия):
   нового цвета не заводим. Полоса слева, а не заливка во всю строку: строка остаётся строкой
   списка, а не превращается в карточку. Класс ставит механика только на шаге обмена. */
.off-list li.is-forced {
  background: var(--band); border-left: 3px solid var(--jb-ink);
  margin: 0 -10px; padding-left: 10px; padding-right: 10px; border-radius: 6px;
}
.off-cost {
  display: block; margin-top: 2px;
  font-size: var(--fs-util); color: var(--muted-soft); font-variant-numeric: tabular-nums;
  font-style: italic;
}

/* слайдер срока (С5). Дефолта нет: пока не сдвинут, значение «не выбрано» —
   обязательный срок стирал наблюдение «сам ли человек привязал цель ко времени» */
/* ⚠ РЯД СРОКА НЕ ДВИГАЕТСЯ (правка владельца 09.08). Дёргали его три вещи разом:
   у числа менялся кегль между «не выбрано» и «8», ширина была задана в em (то есть
   тоже менялась вместе с кеглем), а кнопка «сбросить» появлялась только после
   первого движения. Теперь это сетка с постоянными колонками: ползунок тянется,
   число стоит в своей колонке фиксированной ширины, кнопка на месте всегда. */

/* Тихие ссылки под главной кнопкой экрана установки: перечитать настройку и роль.
   Служебный кегль и приглушённый цвет — это не действие экрана, а выход из него. */
.setup-links { margin: 14px 0 0; text-align: center; font-size: var(--fs-util); color: var(--muted-soft); }
/* Те же ссылки внизу левой колонки ассессмента: выключка влево по колонке и отступ
   как у остального её содержимого, а не по центру карточки. */

.setup-links a { color: var(--muted); text-decoration: none; }
.setup-links a:hover { color: var(--ink); text-decoration: underline; }

/* ══════════════════════════════════════════════════════════════════════════
   КОНТРАСТ: РАБОТА ЧЁРНЫМ, ОПОРА ТИШЕ (решение владельца 07.08)
   Было наоборот, и это считано: в рабочей колонке преобладал --muted-soft
   (11 узлов против 8 чёрных), а в панели материалов — чёрный (272 против 98).
   То есть глаз вело туда, где участник ничего не делает. Логика теперь одна:
   где работают — полный контраст; что рядом для справки — на ступень тише.
   Опора остаётся читаемой: --muted это ≈5.4:1 на белом, выше порога WCAG 1.4.3.
   ══════════════════════════════════════════════════════════════════════════ */
/* --- опора: тише --- */
.support-body { color: var(--muted); }
#supCaseText, #supCaseText p, #supCaseText li, #supCaseText td { color: var(--muted); }
/* Заголовки внутри опоры тоже приглушены (правка владельца 07.08): иерархию здесь
   держит начертание, а не контраст, — «это вспомогательный блок, он не должен быть
   таким контрастным». Чёрным в опоре остаётся только выделение внутри текста (b) и
   выписка участника: она его, а не материала. */
#supCaseText h2, #supCaseText h3, .case-sum-t, .who-row b, .recap-q { color: var(--muted); }
#supCaseText b, #supCaseText strong, .mark-quote { color: var(--ink); }
/* --- работа: полный контраст --- */
.talk .win-label, .casewide .win-label, .talk .mx-label, .talk .mx-title, .talk .mx-count.mx-tally, .talk .bl-card-title, .talk .bl-zone-h, .talk .sc-head, .talk .chat-name { color: var(--ink); }
.talk .win-input, .talk .mx-input, .talk textarea { color: var(--ink); }

/* ══════════════════════════════════════════════════════════════════════════
   ГОЛУБОЙ = «ВЫ» (решение 04.08, приведено к одному стандарту 07.08)
   Голубым помечено ВСЁ, что участник произвёл: своя реплика, поле ответа,
   карточки, которые он пишет, и его выписки в тезисах. До этого правило
   работало только у двух отметок — самого тревожного симптома и самого
   вероятного варианта, — и голубой читался как «выбранное», а не как «моё».
   Отметка внутри своей зоны различается не заливкой, а рамкой (--jb-ink).
   ══════════════════════════════════════════════════════════════════════════ */
.s2-mine { background: var(--band); border: 1px solid var(--band-line); border-radius: var(--radius); padding: 10px; }
.s2-mine .win-input, .s2-mine textarea { background: var(--paper); }
.mx-card { background: var(--band); border-color: var(--band-line); }
.mx-card .mx-input, .mx-card textarea, .mx-card input { background: var(--paper); }
.mx-card.is-first, .bl-card.mx-own { border-color: var(--jb-ink); background: var(--band); }

/* ── СХЕМА ЭКРАНА НА СТРАНИЦЕ РОЛИ ──
   Обезличенная: полосы вместо текста, ни одного слова из маршрута. Служит одному —
   показать, где что лежит, до того как участник туда попадёт. */
.scr { margin: 18px 0 0; }
.scr-frame {
  border: 1px solid var(--hairline); border-radius: var(--radius);
  background: var(--paper); overflow: hidden;
}
.scr-top {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px; border-bottom: 1px solid var(--hairline); background: var(--soft);
}
.scr-logo { width: 46px; height: 8px; border-radius: 2px; background: var(--ink); opacity: .75; }
/* Схема живёт в столбике страницы (≈700px), а не во всю ширину: пропорции колонок
   те же, что на экране, но полосы короче и ряд ниже. */
.scr-body { display: grid; grid-template-columns: 1.2fr 1fr; min-height: 170px; }
/* полоса этапов под шапкой схемы — как на экране (03.10) */
.scr-k-top { margin-left: auto; }
.scr-rail { display: flex; align-items: center; gap: 4px; padding: 6px 10px; border-bottom: 1px solid var(--hairline); background: var(--paper); }
.scr-rail i { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--soft); }
.scr-rail i.on { background: var(--jb-ink); }
.scr-rail i.now { width: 46px; border-radius: 999px; background: linear-gradient(90deg, var(--band-line) 55%, var(--band) 55%); }
.scr-rail b { flex: 1 1 auto; height: 1px; background: var(--hairline); }
.scr-col { display: flex; flex-direction: column; gap: 7px; padding: 10px; min-width: 0; }
.scr-mid { border-right: 1px solid var(--hairline); }
.scr-k {
  font-size: var(--label-size); font-weight: var(--label-weight); letter-spacing: var(--label-track);
  text-transform: uppercase; color: var(--muted-soft); margin-bottom: 2px;
}
.scr-bar { height: 7px; border-radius: 3px; background: var(--hairline); }
.scr-bar.w40 { width: 40% } .scr-bar.w50 { width: 50% } .scr-bar.w55 { width: 55% }
.scr-bar.w60 { width: 60% } .scr-bar.w65 { width: 65% } .scr-bar.w70 { width: 70% }
.scr-bar.w75 { width: 75% } .scr-bar.w80 { width: 80% } .scr-bar.w85 { width: 85% }
.scr-bar.w90 { width: 90% }
/* реплика — как на экране: серый пузырь у левого края */
.scr-bubble {
  display: flex; flex-direction: column; gap: 6px; width: 76%;
  padding: 10px; border-radius: var(--radius); background: var(--soft);
}
/* поле ответа — голубое, как всё, что делает участник */
.scr-field {
  height: 38px; border-radius: var(--radius);
  background: var(--band); border: 1px solid var(--band-line);
}
/* Схема показывает экран ассессмента, а там действие голубое — цвет берём оттуда,
   а не со страницы роли, где вермилион ещё живёт. */
.scr-btn { align-self: flex-end; width: 96px; height: 20px; border-radius: var(--radius); background: var(--jb-ink); }
.scr-tabs { display: flex; flex-wrap: wrap; gap: 4px 12px; margin-bottom: 4px; font-size: var(--fs-util); }
.scr-tabs b { font-weight: 600; color: var(--ink); border-bottom: 2px solid var(--accent); padding-bottom: 2px; }
.scr-tabs i { font-style: normal; color: var(--muted-soft); }
.scr figcaption { margin-top: 8px; font-size: var(--fs-util); color: var(--muted-soft); }
@media (max-width: 700px) { .scr-body { grid-template-columns: 1fr; } .scr-mid { border-right: none; } }

/* ── РЕПЛИКИ ПОЯВЛЯЮТСЯ ПО ОДНОЙ (решение владельца 07.08) ──
   Реплика ждёт своей очереди скрытой и въезжает снизу; рабочая область до конца
   монолога тоже скрыта (.is-await), и её действие в подвал колонки не переносится.
   Ни одного нового цвета и размера — только прозрачность и сдвиг. */
/* ⚠ НЕПОКАЗАННАЯ РЕПЛИКА ТЕПЕРЬ ДЕРЖИТ СВОЮ ВЫСОТУ (правка владельца 28.08).
   «При росте окна с диалогами отвлекает появление ползунка прокрутки, а потом его
   постепенное растягивание. Может он сразу будет нужного размера и именно баблы будут
   появляться, чтобы лишних дёрганий на странице не было».
   Здесь стоял display: none с прямо противоположной пометкой — «иначе непоказанные
   реплики держат высоту, участник видит пустоту, а действие уползает вниз». Вторая
   половина того довода с тех пор отпала сама: действие живёт ВНЕ прокручиваемого тела
   (.work-act в разметке), а рабочая область до конца монолога скрыта целиком (.is-await),
   так что уползать ему больше некуда. Осталась первая половина — пустота под последней
   показанной репликой, — и владелец её выбрал сознательно: она ниже зоны чтения, а
   ползунок за монолог перестаёт менять размер ни разу.
   display оставляем block, как в состоянии .is-in ниже: место, которое реплика занимает
   скрытой, обязано равняться месту, которое она займёт показанной, — иначе высота всё
   равно поедет. visibility, а не opacity: скрытый текст не читается скринридером и не
   выделяется мышью.
   ⚠ ПОЛЯ ВЕРСТАКА (.mx-ansbox, .mx-hold ниже) НАМЕРЕННО ОСТАЛИСЬ НА display: none. Они
   стоят ПОСЛЕ своих реплик, и зарезервированная высота дала бы пустой провал в середине
   монолога на каждое поле — там растяжение ползунка меньше провала. */
.chat.is-staged { display: block; visibility: hidden; }
.chat.is-staged.is-in { visibility: visible; animation: bubbleIn .3s ease both; }
/* ⚠ ПОЛЕ ОТВЕТА ЖДЁТ СВОЕЙ ОЧЕРЕДИ (правка владельца 21.08). У окна ответа это
   уже было (.is-await снимается по окончании монолога), а внутри верстака поля
   стояли на экране с самого начала: собеседник ещё говорит, а под ним уже открыто
   четыре поля. Рецепт тот же, что у пузыря, и очередь та же — revealRun идёт по
   разметке сверху вниз, поэтому поле встаёт ровно после своей реплики. */
.mx-ansbox.is-staged { display: none; }
.mx-ansbox.is-staged.is-in { display: block; animation: bubbleIn .3s ease both; }
/* То же для ответной области, которая не карточка с подписью, а своя реплика
   («Вы» + голубое поле): обёртка обязана быть геометрически пустой, иначе поле
   съедет — доля и прижим вправо живут на .s2-mine внутри неё. */
.mx-hold.is-staged { display: none; }
.mx-hold.is-staged.is-in { display: block; animation: bubbleIn .3s ease both; }
@keyframes bubbleIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.s2-block.is-await, .is-await { display: none; }
@media (prefers-reduced-motion: reduce) {
  .chat.is-staged.is-in { animation: none; }
}

/* Записка верстака над серой линией: та же роль, что у .win-note, но своё место —
   в рабочей области, а не в ряду действия (решение владельца 07.08). */
.mx-foot-note { margin: 14px 0 0; font-size: var(--fs-util); line-height: 1.5; color: var(--muted-soft); max-width: 880px; }

/* Сумма взятого — в подписи стопки «Берём», а не крупной полосой над списком
   (правка владельца 07.08). Служебный кегль: это справка, а не приговор. */
/* Сумма стопки уходит ВПРАВО, к краю рамки (решение владельца 09.08). Счёт
   карточек и число людей стояли встык, и разделитель на этом кегле их не
   разводил: «Берём · 2 460 чел.» читалось как одно число. Разводит расстояние.
   Класс, а не :has() — правило обязано держать и там, где :has не поддержан:
   без flex сумма встала бы обратно встык к счёту, то есть ровно в ту ошибку. */
.bl-col-head.has-sum { display: flex; align-items: baseline; gap: 6px; }
.bl-pile-sum { margin-left: auto; font-size: var(--fs-util); color: var(--muted-soft); font-weight: 400; letter-spacing: 0; text-transform: none; }

/* ── ЛИЦО СОБЕСЕДНИКА ──
   Кружок слева от имени. Пока картинки нет — инициалы на подложке; размер и цвет
   служебные, чтобы кружок не спорил с репликой. */
.chat-face {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: 50%; margin-right: 8px;
  background: var(--soft) center/cover no-repeat;
  border: 1px solid var(--hairline);
  font-size: var(--label-size); font-weight: 700; letter-spacing: 0;
  color: var(--muted); vertical-align: middle;
}
.chat-face.is-casual { border-color: var(--band-line); background-color: var(--band); }
/* inline-flex нужен ИМЕНИ СОБЕСЕДНИКА: рядом с ним стоит кружок с лицом, и они должны
   стоять на одной линии. У своей реплики кружка нет, а inline-flex ломал выравнивание:
   text-align: right у такого блока двигает содержимое ВНУТРИ него, а сам он остаётся у
   левого края — поэтому «Вы» над зафиксированным ответом уезжало влево, хотя над
   открытым полем стояло справа (там своя разметка, chat-name-mine, блочная).
   ⚠ Владелец указывал на это четыре раза; причина была одна и эта. */
.chat-msg:not(.me) .chat-name { display: inline-flex; align-items: center; }
.chat-msg.me .chat-name { display: block; }

/* Галочка у прочитанного приложения: голубая, потому что это отметка участника,
   а не платформы. Ставится, когда приложение открыто и его низ побывал на экране.
   ⚠ СЛЕВА ОТ НАЗВАНИЯ, а не в конце строки (правка владельца 09.08): во всей
   платформе галочка стоит перед тем, что отмечает, — так же в столбике этапов. */
.case-block.is-read > .case-sum .case-sum-t::before {
  content: '✓'; color: var(--jb-ink); font-weight: 700; margin-right: 8px;
}

/* Ключ ссылки потока: только для чтения, моноширинный — его диктуют и сверяют. */
.cab-key { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px;
           letter-spacing: .04em; color: var(--ink); }

/* Подпись роли в шапке кабинета: спокойная, это не предупреждение. */
.cab-role { font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
            color: var(--muted); border: 1px solid var(--hairline); border-radius: 999px;
            padding: 3px 9px; }

/* ===== Кабинет ведущего (vedushchiy.html, решение владельца 03.10) =====
   Своя простая страница: создать поток → ссылка и QR → прохождение. Статусы —
   голубым («идёт» — бледная заливка, «закончено» — залитый), как «вы» в дне. */
.ved { background: var(--paper); }
.ved-hd {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  max-width: 1040px; margin: 0 auto; padding: 22px 24px 18px;
  border-bottom: 1px solid var(--hairline);
}
.ved-who { color: var(--muted); font-size: 14px; }
.ved-who a { color: var(--muted); }
.ved-who a:hover { color: var(--ink); }
.ved-wrap { max-width: 1040px; margin: 0 auto; padding: 36px 24px 72px; }
.ved-k {
  margin: 0 0 6px; font-size: 12px; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--muted-soft);
}
.ved-k-gap { margin-top: 44px; }
.ved-h1 { max-width: none; margin: 0 0 20px; font-size: 30px; font-weight: 700; line-height: 1.15; letter-spacing: -.01em; }
.ved-card { border: 1px solid var(--hairline); border-radius: var(--radius); padding: 22px 24px; background: var(--paper); }
.ved-row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; }
.ved-f { display: flex; flex-direction: column; gap: 6px; flex: 1 1 220px; font-size: 14px; }
.ved-f > span { color: var(--muted); font-size: 13px; }
.ved-f input, .ved-f select {
  font: inherit; font-size: 15px; padding: 10px 12px; border: 1px solid #cfd1d4;
  border-radius: var(--radius); background: var(--paper); color: var(--ink);
}
.ved-f input:focus, .ved-f select:focus { outline: 2px solid var(--jb); outline-offset: 0; border-color: var(--jb-ink); }
.ved-f em { font-style: normal; color: var(--muted-soft); font-size: 13px; }
.ved-list { display: flex; flex-direction: column; border-top: 1px solid var(--hairline); }
.ved-list a {
  display: flex; justify-content: space-between; gap: 16px; padding: 14px 4px;
  border-bottom: 1px solid var(--hairline); color: var(--ink); text-decoration: none;
}
.ved-list a:hover { background: var(--soft); }
.ved-list a span { color: var(--muted); font-size: 14px; white-space: nowrap; }
.ved-share { display: flex; gap: 28px; align-items: flex-start; margin-bottom: 24px; }
.ved-share > div { flex: 1; min-width: 0; }
.ved-qr {
  flex: none; width: 200px; height: 200px; padding: 10px; border: 1px solid var(--hairline);
  border-radius: var(--radius); background: #fff; cursor: zoom-in;
}
.ved-qr svg { display: block; width: 100%; height: 100%; }
.ved-link {
  margin: 4px 0 14px; padding: 12px 14px; background: var(--soft); border-radius: var(--radius);
  font-size: 16px; font-weight: 500; word-break: break-all; user-select: all;
}
.ved-dim { color: var(--muted); font-size: 14px; margin: 14px 0 0; }
.ved-meta { display: flex; flex-wrap: wrap; gap: 8px 22px; align-items: center; margin: -8px 0 22px; font-size: 14px; color: var(--muted); }
.ved-meta a { color: var(--jb-ink); }
.ved-live { display: inline-flex; align-items: center; gap: 7px; }
.ved-live::before {
  content: ''; width: 8px; height: 8px; border-radius: 50%; background: #2fa36b;
  animation: ved-pulse 2s ease-in-out infinite;
}
@keyframes ved-pulse { 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) { .ved-live::before { animation: none; } }
.ved-tabs { display: flex; gap: 26px; border-bottom: 1px solid var(--hairline); margin-bottom: 18px; }
.ved-tabs button {
  font: inherit; font-size: 15px; font-weight: 500; background: none; border: 0; cursor: pointer;
  padding: 10px 0 12px; color: var(--muted); border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.ved-tabs button.is-on { color: var(--ink); border-bottom-color: var(--ink); }
.ved-table { width: 100%; border-collapse: collapse; font-size: 15px; }
.ved-table th, .ved-table td { border: 0; text-align: left; white-space: normal; min-width: 0; background: none; }
.ved-table th {
  text-align: left; font-size: 12px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted-soft); padding: 8px 12px 10px 0; border-bottom: 1px solid var(--hairline);
}
.ved-table td { padding: 13px 12px 13px 0; border-bottom: 1px solid var(--hairline); vertical-align: middle; }
.ved-table td:nth-child(3), .ved-table td:nth-child(4) { white-space: nowrap; color: var(--muted); font-variant-numeric: tabular-nums; }
.ved-name {
  font: inherit; font-weight: 600; color: var(--ink); background: none; border: 0; padding: 0; cursor: pointer;
  text-decoration: underline dotted #b8babd; text-underline-offset: 4px;
}
.ved-name:hover { text-decoration-color: var(--ink); }
.ved-num {
  margin-left: 10px; padding: 2px 8px; border-radius: 6px; background: var(--soft);
  font-size: 14px; font-weight: 600; font-variant-numeric: tabular-nums;
}
.ved-st { display: inline-block; padding: 3px 10px; border-radius: 999px; font-size: 13px; color: var(--muted); background: var(--soft); white-space: nowrap; }
.ved-st.is-run { background: var(--band); color: var(--jb-ink); }
.ved-st.is-done { background: var(--jb-ink); color: #fff; }
.ved-empty { padding: 40px 0; color: var(--muted); text-align: center; }
.ved-set { display: flex; flex-direction: column; gap: 18px; max-width: 560px; }
.ved-set .ved-f { flex: none; }
.ved-check { display: flex; align-items: center; gap: 10px; font-size: 15px; }
.ved-qrfull {
  position: fixed; inset: 0; z-index: 100; background: #fff; align-items: center; justify-content: center; cursor: zoom-out;
}
.ved-qrfull-in { text-align: center; }
.ved-qrfull-in > div { width: min(72vh, 86vw); height: min(72vh, 86vw); margin: 0 auto 18px; }
.ved-qrfull-in svg { width: 100%; height: 100%; }
.ved-qrfull-in p { margin: 6px 0; font-size: 20px; font-weight: 500; word-break: break-all; }
.ved-qrfull-in p.ved-dim { font-size: 14px; }
@media (max-width: 720px) {
  .ved-share { flex-direction: column; }
  .ved-table th:nth-child(4), .ved-table td:nth-child(4) { display: none; }
}

/* ===== Кабинет администратора (administrator.html, решение владельца 03.10) =====
   Тот же язык, что у кабинета ведущего (.ved-*), шире: в таблице потока ещё оценка. */
.adm-hd, .adm-wrap { max-width: 1200px; }
.adm-hd { gap: 20px; }
.adm-nav { display: flex; gap: 24px; margin-right: auto; margin-left: 20px; }
.adm-nav a { color: var(--muted); text-decoration: none; font-weight: 500; padding: 4px 0; border-bottom: 2px solid transparent; }
.adm-nav a.is-on { color: var(--ink); border-bottom-color: var(--ink); }
.adm-hd .cab-status { max-width: 320px; text-align: right; }
.adm-find {
  font: inherit; font-size: 14px; padding: 8px 12px; border: 1px solid #cfd1d4; border-radius: var(--radius);
  width: 260px; background: var(--paper); color: var(--ink);
}
.adm-find:focus { outline: 2px solid var(--jb); outline-offset: 0; border-color: var(--jb-ink); }
.adm-new { margin-bottom: 36px; }
.adm-f-s { flex: 0 1 190px; }
.adm-f-xs { flex: 0 0 110px; }
.adm-new-ai { margin-bottom: 12px; white-space: nowrap; }
.adm-cols { display: grid; grid-template-columns: 1.7fr 1.1fr .9fr .8fr 1fr .6fr; gap: 12px; width: 100%; align-items: center; }
.adm-cols > span { white-space: nowrap; }
.adm-cols-hd {
  padding: 0 4px 8px; font-size: 12px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted-soft); border-bottom: 1px solid var(--hairline);
}
.adm-list { border-top: 0; }
.adm-list a { align-items: center; }
.adm-list a span { font-size: 15px; }
.adm-ai {
  margin-left: 8px; padding: 1px 6px; border: 1px solid #cfd1d4; border-radius: 4px;
  font-size: 11px; font-weight: 700; color: var(--muted); vertical-align: 2px;
}
.adm-wait {
  display: inline-block; padding: 2px 10px; border-radius: 999px; white-space: nowrap;
  background: var(--accent-tint); color: var(--accent-ink); font-size: 13px; font-weight: 600;
}
.adm-wait.is-run { background: var(--band); color: var(--jb-ink); }
.adm-bar { display: flex; justify-content: space-between; align-items: center; gap: 16px; margin-bottom: 6px; }
.adm-bar .ved-dim { margin: 0; }
.adm-table tbody tr[data-bib] { cursor: pointer; }
.adm-table tbody tr[data-bib]:hover { background: var(--soft); }
.adm-table tr.is-off td { opacity: .55; }
.adm-table td:nth-child(3), .adm-table td:nth-child(4) { color: inherit; }
.adm-table .ved-num { margin-left: 6px; }
.adm-table .cab-skill { margin-right: 8px; }
.adm-key { font-family: ui-monospace, Menlo, monospace; font-size: 14px; background: var(--soft); padding: 3px 8px; border-radius: 6px; }
.adm-copy, .adm-table a { color: var(--jb-ink); font-size: 14px; }
.adm-table td.adm-acts { text-align: right; white-space: nowrap; }
.adm-acts .btn + .btn { margin-left: 6px; }
.adm-inline { font: inherit; font-weight: 600; border: 1px solid transparent; border-radius: 6px; padding: 4px 6px; margin-left: -7px; background: none; color: var(--ink); width: 220px; }
.adm-inline:hover { border-color: var(--hairline); }
.adm-inline:focus { border-color: var(--jb-ink); outline: none; }
.adm-more { margin-top: 18px; max-width: 560px; }
.adm-more summary { cursor: pointer; font-weight: 600; }
.adm-issued { font-family: ui-monospace, Menlo, monospace; font-size: 14px; line-height: 1.7; }
.adm-danger { margin-top: 28px; }
.adm-num .ved-row { align-items: flex-end; }
.adm-num .ved-check { margin-bottom: 12px; }
@media (max-width: 900px) {
  .adm-find { width: 180px; }
  .adm-cols { grid-template-columns: 1.6fr 1fr 1fr; }
  .adm-cols > :nth-child(n+4) { display: none; }
}
.adm-bar-acts { display: flex; gap: 8px; flex: none; }
.btn.adm-soon, .btn.adm-soon:hover { color: var(--muted-soft); border-color: var(--hairline); background: var(--soft); cursor: not-allowed; opacity: 1; }
/* Кабинет ведущего: оценка и заглушки отчёта (решение владельца 03.10). */
.ved-bar { display: flex; justify-content: flex-end; gap: 8px; margin-bottom: 6px; }
.ved-dim0 { color: var(--muted); }
.ved-total { font-weight: 700; font-variant-numeric: tabular-nums; }
.ved-table td.ved-acts { text-align: right; width: 1%; white-space: nowrap; }
