/* Оформление сайта. Все значения — из tokens.css, здесь только раскладка.
   Кабинет подключает те же токены и получает тот же вид.

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

*, *::before, *::after { box-sizing: border-box; }

/* `both-edges` держит поля страницы одинаковыми слева и справа. Без него
   полоса прокрутки отъедает место только справа, контейнер центрируется
   в оставшейся ширине, и левое поле выглядит уже правого */
html { -webkit-text-size-adjust: 100%; color-scheme: light;
       scrollbar-gutter: stable both-edges;
       /* Переход по якорю не должен прятать заголовок под липкой шапкой:
          высота шапки 5rem плюс воздух */
       scroll-padding-top: 6rem; }

body {
  margin: 0;
  background: var(--color-surface);
  color: var(--color-ink);
  font-family: var(--font-text);
  font-size: var(--text-md);
  line-height: var(--leading-normal);
  /* Альтернативные формы знаков из макета: одноэтажная «a» в цифрах
     и более спокойная «g» */
  font-feature-settings: 'ss01' 1;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-tight);
  line-height: var(--leading-snug);
  margin: 0;
}

p { margin: 0 0 var(--space-4); max-width: var(--measure); }
p:last-child { margin-bottom: 0; }

a { color: inherit; text-decoration: none; }
a:focus-visible, button:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.skip-link {
  position: absolute; left: -9999px; top: var(--space-3);
  background: var(--color-surface); padding: var(--space-3) var(--space-4);
  border: var(--border); border-radius: var(--radius-md);
  /* Выше липкой шапки: ссылка «к содержимому» появляется в том же углу,
     и спрятать её под шапкой значит сломать единственный способ
     пропустить меню с клавиатуры */
  z-index: 60;
}
.skip-link:focus { left: var(--space-4); }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* --- Общие примитивы --------------------------------------------------- */

/* Полоса контента одна на весь сайт: 1180 пикселей и поля от токена */
.container {
  width: 100%; max-width: var(--page-max); margin: 0 auto;
  padding-left: var(--page-gutter); padding-right: var(--page-gutter);
}

/* Крупный заголовок. Отличительная черта макета — почти нулевой просвет
   между строками и заметно отрицательный трекинг. */
.display {
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-display);
  line-height: var(--leading-display);
  margin: 0;
  max-width: none;
}

/* Надпись капителью моноширинным — вторая отличительная черта */
.eyebrow {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-ink-muted);
  margin: 0;
}
.eyebrow--accent { color: var(--color-accent); }

/* Числа и коды: моноширинный с табличными цифрами, чтобы разряды
   выстраивались в столбик */
.data {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-tight);
}

.lead { font-size: var(--text-lg); color: var(--color-ink-muted);
        line-height: var(--leading-normal); max-width: 46ch; }
/* Автор и дата под заголовком статьи. Мелко и приглушённо: это не часть
   текста, а его паспорт — читают его один раз и обычно после текста. */
.byline {
  display: flex; flex-wrap: wrap; align-items: baseline;
  gap: var(--space-2) var(--space-3);
  margin: var(--space-4) 0 0;
  font-family: var(--font-mono); font-size: var(--text-xs);
  color: var(--color-ink-muted);
}
.byline a { color: var(--color-ink); text-decoration: none;
            border-bottom: 1px solid var(--color-line-strong); }
.byline a:hover { border-bottom-color: var(--color-accent); }

.note { font-size: var(--text-sm); color: var(--color-ink-muted); max-width: 68ch;
        margin-top: var(--space-6); }
/* В кабинете таких пояснений больше сотни, и набраны они были тем же
   кеглем и цветом, что данные. Подсказка, неотличимая от факта, —
   главная причина, по которой экран читается с трудом */
.app-body .note { font-size: 0.8125rem; line-height: var(--leading-normal);
                  color: var(--color-ink-muted); max-width: 64ch; }
.icon { display: inline-flex; width: 20px; height: 20px; color: currentColor; flex: none; }
.icon svg { width: 100%; height: 100%; }
.link { color: var(--color-accent); font-family: var(--font-display);
        font-size: var(--text-sm); font-weight: var(--weight-medium); }
.link:hover { color: var(--color-accent-strong); text-decoration: underline; }

.section { padding: var(--space-9) 0; }
.section__inner { width: 100%; max-width: var(--page-max); margin: 0 auto;
                  padding: 0 var(--page-gutter); }
.section h2 { font-size: var(--text-2xl); margin-bottom: var(--space-4); max-width: 26ch; }
.section__head { margin-bottom: var(--space-7); }
.band { background: var(--color-surface-sunken); }

/* --- Знак и логотип ---------------------------------------------------- */
/* В макете знака нет — только слово, набранное тем же шрифтом.
   Это и есть решение: марка, которую не надо рисовать. */
.mark { width: 1.15em; height: 1.15em; flex: none; }
.lockup {
  display: inline-flex; align-items: center;
  font-family: var(--font-display); font-weight: var(--weight-medium);
  font-size: var(--text-md); letter-spacing: var(--tracking-tight);
}
.lockup .mark { display: none; }
.lockup--small { font-size: var(--text-md); }

/* --- Кнопки ------------------------------------------------------------ */
/* Плоский цветной блок без рамок и теней: подложка и несёт нажим.
   Скруглённая пилюля — форма из макета. */
.button {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--space-2);
  font-family: var(--font-display); font-size: 0.9rem;
  font-weight: var(--weight-medium); line-height: 1;
  padding: 0.75rem 1.5rem; border-radius: var(--radius-full);
  border: none;
  transition: background var(--duration) var(--ease), color var(--duration) var(--ease);
  cursor: pointer;
}
.button--primary { background: var(--color-accent); color: var(--color-accent-ink); }
.button--primary:hover { background: var(--color-accent-strong); }
.button--dark { background: var(--color-ink); color: var(--color-surface); }
.button--dark:hover { background: color-mix(in oklab, var(--color-ink) 85%, var(--color-surface)); }
/* Третий вид — без подложки вовсе: ссылка со стрелкой */
.button--secondary { background: none; color: var(--color-ink); padding-left: 0;
                     padding-right: 0; }
.button--secondary:hover { color: var(--color-ink-muted); }
.button--ghost { background: none; color: var(--color-ink-inverse);
                 border: 1px solid var(--color-line-inverse); }
.button--ghost:hover { background: var(--color-line-inverse); }
.button--large { font-size: var(--text-md); padding: 0.9rem 1.75rem; }
.button--small { font-size: var(--text-xs); padding: 0.5rem 1rem; }

/* Стрелка уезжает вправо на наведении — единственное движение в макете */
.button__arrow { width: 1rem; height: 1rem; flex: none;
                 transition: transform var(--duration) var(--ease); }
.button:hover .button__arrow { transform: translateX(2px); }

/* --- Шапка ------------------------------------------------------------- */
/* Без рамки снизу: в макете шапка сливается с фоном страницы */
/* Шапка едет с читателем. Фон непрозрачный обязательно: под ней идёт
   текст, и просвечивающая шапка превращает первую строку в кашу.
   Линия снизу появляется только когда страница сдвинута, — у верха
   страницы шапка по макету сливается с фоном и ничем не отделена */
.site-header { position: sticky; top: 0; z-index: 50;
               background: var(--color-surface); }
.site-header[data-scrolled] { box-shadow: 0 1px 0 var(--color-line); }
@media (prefers-reduced-motion: no-preference) {
  .site-header { transition: box-shadow var(--duration) var(--ease); }
}
.site-header__inner {
  max-width: var(--page-max); margin: 0 auto;
  padding: 0 var(--page-gutter);
  height: 5rem;
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-5);
}
.site-nav {
  display: flex; align-items: center; gap: 2.5rem;
  font-family: var(--font-display); font-size: 0.9rem;
}
.site-nav a:not(.button) { color: var(--color-ink-muted);
                           transition: color var(--duration) var(--ease); }
.site-nav a:not(.button):hover { color: var(--color-ink); }
.site-nav__side { display: flex; align-items: center; gap: 1.5rem; }
.site-nav__login { color: var(--color-ink-muted); }
.site-nav__login:hover { color: var(--color-ink); }

.nav-toggle {
  display: none; align-items: center; justify-content: center;
  /* 44px — минимальная цель для пальца, меньше делать нельзя */
  width: 44px; height: 44px; margin-right: calc(0px - var(--space-2));
  background: none; border: none; border-radius: var(--radius-md);
  color: var(--color-ink); cursor: pointer;
}
.nav-toggle .nav-toggle__close { display: none; }
.site-header[data-nav="open"] .nav-toggle__open { display: none; }
.site-header[data-nav="open"] .nav-toggle__close { display: inline-flex; }

/* --- Подвал ------------------------------------------------------------ */
/* Тоже без рамки: отделяет пустота, а не линия */
.site-footer { background: var(--color-surface); padding: var(--space-9) 0 3.5rem; }
.site-footer__inner { max-width: var(--page-max); margin: 0 auto;
                      padding: 0 var(--page-gutter); }
.site-footer__grid {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 3.5rem var(--space-5);
}
.site-footer__about { grid-column: span 2; }
.site-footer__about .lockup { display: inline-flex; }
.footer-note { color: var(--color-ink-muted); font-size: var(--text-sm);
               line-height: var(--leading-normal); max-width: 26ch;
               margin: 1.25rem 0 0; }
.site-footer__group ul { list-style: none; margin: 1.25rem 0 0; padding: 0;
                         display: flex; flex-direction: column; gap: var(--space-3); }
.site-footer__group a { font-size: var(--text-sm); color: var(--color-ink-80);
                        transition: color var(--duration) var(--ease); }
.site-footer__group a:hover { color: var(--color-ink); }
/* Значки каталогов. Ряд переносится сам: их будет несколько, и подвал
   не должен ломаться на четвёртом.

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

   Приглушены в покое и наливаются цветом под курсором: это
   подтверждение, а не призыв, и спорить с содержимым подвала они
   не должны. */
.badges { display: flex; flex-wrap: wrap; align-items: center;
          gap: var(--space-4); list-style: none;
          margin: 4rem 0 0; padding: 0; }
.badges a { display: block; opacity: 0.75;
            transition: opacity var(--duration) var(--ease); }
.badges a:hover, .badges a:focus-visible { opacity: 1; }
.badges img { display: block; height: 2.25rem; width: auto; }

/* Правовая строка идёт сразу за значками, и шесть рем отступа между ними
   были бы провалом: сокращаем, когда значки есть */
.badges + .site-footer__legal { margin-top: var(--space-6); }

.site-footer__legal {
  margin-top: 6rem; display: flex; flex-direction: column-reverse;
  align-items: flex-start; gap: var(--space-5);
}
.site-footer__legal p { margin: 0; font-size: var(--text-xs);
                        color: var(--color-ink-muted); }
.site-footer__legal a { color: var(--color-ink-muted); }
.site-footer__legal a:hover { color: var(--color-ink); }

@media (min-width: 48rem) {
  .site-header__inner { height: 6rem; }
  .site-footer__grid { grid-template-columns: repeat(6, 1fr); }
  /* Колонок четыре: продукт, услуги, компания, правовое. Блоку с маркой
     остаётся две доли из шести — с тремя четвёртая группа переносилась
     на вторую строку */
  .site-footer__about { grid-column: span 2; }
  .site-footer__legal { flex-direction: row; align-items: center;
                        justify-content: space-between; }
}

/* Порог «меню под кнопку» — 64rem, а не 48. Пунктов стало шесть, и
   в одну строку они помещаются от 1024 пикселей; между 768 и 1024 меню
   переносилось на две-три строки и наезжало на логотип. Планшету кнопка
   привычнее, чем ломаная шапка. */
@media (max-width: 64rem) {
  .site-nav { gap: var(--space-4); font-size: var(--text-xs); }
  .site-nav__side { gap: var(--space-3); }

  .js .nav-toggle { display: inline-flex; }
  .js .site-nav { display: none; }
  /* Раскрытое меню ложится поверх страницы, как в макете */
  .js .site-header[data-nav="open"] .site-nav {
    display: flex; flex-direction: column; align-items: flex-start;
    position: absolute; inset-inline: 0; top: 5rem;
    background: var(--color-surface);
    padding: var(--space-6) var(--page-gutter) 2.5rem;
    gap: var(--space-5); font-size: 1.5rem;
  }
  .js .site-header[data-nav="open"] .site-nav a:not(.button) {
    font-size: 1.5rem; color: var(--color-ink);
  }
  .js .site-header[data-nav="open"] .site-nav__side {
    flex-direction: column; align-items: flex-start; gap: var(--space-4);
    margin-top: var(--space-4);
  }
}

@media (max-width: 48rem) {
  .section { padding: 4rem 0; }
}

/* =====================================================================
   Главная. Композиция перенесена из макета: разреженная сетка,
   иллюстрации из плоских фигур, шаг между разделами 7rem / 10rem.
   ===================================================================== */

/* --- Три шага ---------------------------------------------------------- */
.how { margin-top: var(--space-8); }
.hero-chat + .how { margin-top: var(--space-7); }
.how__head { max-width: 34ch; }
.how__head h2 { margin-top: var(--space-5); font-size: var(--text-3xl); }
.how__flow { margin-top: var(--space-8); display: none; color: var(--color-ink-60); }
.how__flow svg { width: 100%; max-width: 640px; height: 110px; display: block; }
.how__steps { margin-top: var(--space-8); display: grid;
              gap: 3.5rem var(--space-6); list-style: none; padding: 0; }
.how__steps li { margin: 0; }
.how__n { margin: 0; font-size: var(--text-sm); color: var(--color-ink-muted); }
.how__steps h3 { margin-top: var(--space-4); font-size: var(--text-xl);
                 font-weight: var(--weight-medium);
                 letter-spacing: var(--tracking-tight); }
.how__steps p { margin-top: 0.75rem; max-width: 32ch; font-size: var(--text-base);
                line-height: var(--leading-normal); color: var(--color-ink-muted); }

/* --- Улика: отчёт из того, что было сказано ---------------------------- */
.evidence { margin-top: var(--space-8); }
.evidence__inner { display: grid; gap: var(--space-8); align-items: center; }
.evidence h2 { margin-top: var(--space-5); font-size: var(--text-3xl); }
.evidence__sub { margin-top: 1.75rem; max-width: 42ch; font-size: var(--text-md);
                 line-height: var(--leading-normal); color: var(--color-ink-muted); }
.evidence__list { margin: var(--space-6) 0 0; padding: 0; list-style: none;
                  display: flex; flex-direction: column; gap: var(--space-3); }
.evidence__list li { display: flex; align-items: center; gap: 0.75rem;
                     font-size: var(--text-base); color: var(--color-ink-85); }
.evidence__list .icon { width: 1rem; height: 1rem; color: var(--color-accent); }
.evidence__more { margin-top: 2.25rem; }
.evidence__figure { color: var(--color-ink-80); }
.evidence__figure .note { margin-top: var(--space-5); max-width: 38ch; }
.pricing-teaser .note { margin-top: var(--space-6); max-width: 52ch; }
.evidence__figure svg { width: 100%; height: auto; display: block; }

/* --- Утверждение ------------------------------------------------------- */
.thesis { margin-top: var(--space-8); }
.thesis p { max-width: 26ch; font-size: var(--text-3xl);
            line-height: var(--leading-tight); }

/* --- Цены анонсом ------------------------------------------------------ */
.pricing-teaser { margin-top: var(--space-8); }
.pricing-teaser__inner { display: flex; flex-direction: column;
                         align-items: flex-start; justify-content: space-between;
                         gap: var(--space-6); }
.pricing-teaser h2 { margin-top: var(--space-5); max-width: 24ch;
                     font-size: var(--text-2xl); }

/* --- Тёмная полоса призыва --------------------------------------------- */
.cta-band { margin-top: var(--space-8); }
.cta-band__block { background: var(--color-ink); color: var(--color-surface);
                   padding: 6rem 0; }
.cta-band__inner { display: flex; flex-direction: column; align-items: flex-start;
                   gap: 2.5rem; }
.cta-band h2 { max-width: 20ch; font-size: var(--text-3xl); }

@media (min-width: 48rem) {
  .how, .evidence, .thesis, .pricing-teaser, .cta-band {
    margin-top: var(--space-9);
  }
  /* После первого экрана шаг меньше: блок выступает за нижний край окна
     и часть этой высоты занимает собой */
  .hero-chat + .how { margin-top: var(--space-8); }
  /* После залитого блока — тоже меньше: его собственный нижний паддинг
     уже отсчитал часть паузы, и полный шаг сверху читается пустотой */
  .doing + .how, .doing + .shots { margin-top: var(--space-8); }
  .how__flow { display: block; }
  .how__steps { margin-top: 3.5rem; grid-template-columns: repeat(3, 1fr); }

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

  .thesis p { font-size: var(--text-display); font-size: 3.4rem; }

  .pricing-teaser__inner { flex-direction: row; align-items: center; }
  .pricing-teaser h2 { font-size: 2.5rem; }

  .cta-band__block { padding: 8rem 0; }
  .cta-band__inner { flex-direction: row; align-items: center;
                     justify-content: space-between; }
  .cta-band .button { flex: none; }
}

/* --- Шаги ------------------------------------------------------------- */
.steps { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-6); }
.step { padding-top: var(--space-4); border-top: 2px solid var(--color-ink); }
.step__icon { display: inline-flex; width: 24px; height: 24px; color: var(--color-accent); }
.step__icon svg { width: 100%; height: 100%; }
.step__n { display: block; font-family: var(--font-display); font-size: var(--text-xs);
           letter-spacing: var(--tracking-wide); text-transform: uppercase;
           color: var(--color-ink-faint); margin-top: var(--space-3); }
.step h3 { font-size: var(--text-lg); margin: var(--space-2) 0; }
.step p { color: var(--color-ink-muted); max-width: 42ch; font-size: var(--text-sm); }

/* --- Разброс: каждая точка — компания, названная хотя бы одним ------- */
/* Счёт совпадений: число, полоса и подпись в строку. Пришло на смену
   полю точек — подписи у него не помещались в остаток колонки
   и рассыпались по одному слову в строку. */
.tally { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-4); }
.tally li { display: grid; grid-template-columns: 2.5rem 1fr; gap: var(--space-2) var(--space-4);
            align-items: center; }
.tally__value { font-family: var(--font-display); font-size: var(--text-xl);
                font-weight: var(--weight-medium); font-variant-numeric: tabular-nums;
                text-align: right; }
.tally__bar { height: 0.5rem; width: var(--w); min-width: 0.5rem;
              background: var(--color-accent); opacity: 0.5; border-radius: 2px; }
.tally li:first-child .tally__bar { opacity: 1; }
.tally__caption { grid-column: 2; font-size: var(--text-sm);
                  color: var(--color-ink-muted); }

.figure__note { margin-top: var(--space-4); font-size: var(--text-sm); }

/* --- Тарифы ----------------------------------------------------------- */
.plans { display: grid; gap: var(--space-4); }
/* Карточки выровнены по базовой линии: строка под бейдж зарезервирована
   во всех четырёх, иначе выделенная карточка сдвигает содержимое вниз. */
.plan { background: var(--color-surface); border: var(--border);
        border-radius: var(--radius-lg); padding: var(--space-5);
        display: flex; flex-direction: column; gap: var(--space-3); position: relative; }
.plan::before { content: attr(data-flag); display: block;
                font-family: var(--font-display); font-size: var(--text-xs);
                letter-spacing: var(--tracking-wide); text-transform: uppercase;
                color: var(--color-accent); min-height: 1.2em; }
/* Выделенный пакет — плотностью, а не цветом и не тенью: теней на сайте
   нет нигде, а ярлыка «берут чаще» у нас нет оснований ставить.
   Внутренний отступ уменьшен ровно на прибавку, чтобы текст не сдвинулся. */
.plan--featured { border: 2px solid var(--color-ink);
                  padding: calc(var(--space-5) - 1px); }
.plan h3 { font-size: var(--text-lg); }
.plan__price { font-family: var(--font-display); font-size: var(--text-lg);
               font-weight: var(--weight-medium); font-variant-numeric: tabular-nums;
               white-space: nowrap; line-height: 1.1; }
.plan__price span { display: block; font-size: var(--text-xs);
                    letter-spacing: var(--tracking-wide); text-transform: uppercase;
                    color: var(--color-ink-faint); font-weight: var(--weight-regular);
                    margin-top: var(--space-1); }
.plan__summary { font-size: var(--text-sm); color: var(--color-ink-muted); }
.plan__list { list-style: none; margin: 0 0 var(--space-4); padding: var(--space-4) 0 0;
              border-top: var(--border); display: grid; gap: var(--space-3);
              font-size: var(--text-sm); }
.plan__list li { display: grid; grid-template-columns: 1.1rem 1fr; gap: var(--space-3);
                 align-items: start; color: var(--color-ink-muted); }
/* Отметка в списке тарифа. Короткая линия вместо значка: галочка
   выглядит взятой из чужой библиотеки, а волосок — язык самого сайта. */
.plan__mark { width: 0.7rem; height: 0; margin-top: 0.72em;
              border-top: var(--border-width) solid var(--color-accent); }
.plans__note { margin-top: var(--space-6); font-size: var(--text-md);
               color: var(--color-ink-muted); }
.plan .button { margin-top: auto; justify-content: center; }

/* --- Формы ------------------------------------------------------------ */
.split { display: grid; gap: var(--space-7); }
.form { display: grid; gap: var(--space-4); }
.field { display: grid; gap: var(--space-2); font-family: var(--font-display);
         font-size: var(--text-sm); color: var(--color-ink-muted); }
.field input { font-family: var(--font-text); font-size: var(--text-base);
               color: var(--color-ink); padding: 0.65rem 0.85rem;
               border: var(--border-strong); border-radius: var(--radius-md);
               background: var(--color-surface); width: 100%; }
.field input:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 1px; }
.form .button { justify-self: start; }

/* --- Шире ------------------------------------------------------------- */
@media (min-width: 44rem) {
  .board__cols { grid-template-columns: repeat(2, 1fr); column-gap: var(--space-6); }
  .steps { grid-template-columns: repeat(3, 1fr); }
  .plans { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 64rem) {
  .dots { grid-template-columns: auto minmax(0, 1fr); gap: var(--space-8); }
  .board__cols { grid-template-columns: repeat(4, 1fr); }
  .tracks { grid-template-columns: 1fr auto 1fr; gap: var(--space-6); }
  .track__arrow { align-self: center; }
  .plans { grid-template-columns: repeat(4, 1fr); }
  .split { grid-template-columns: minmax(0, 1fr) 24rem; gap: var(--space-8);
           align-items: start; }
  .panel { display: none; }
  .panel__screen { min-height: 17rem; }
}
@media (max-width: 43rem) {
  .hero-a__actions .button, .hero-b__actions .button { flex: 1 1 100%;
                                                       justify-content: center; }
  /* Доска листается пальцем: четыре ответа рядом — это и есть мысль блока,
     ставить их друг под друга значит её потерять */
  .board__cols { display: flex; overflow-x: auto; scroll-snap-type: x mandatory;
                 gap: var(--space-4); margin-right: calc(0px - var(--page-gutter));
                 padding-right: var(--page-gutter); }
  .col { flex: 0 0 min(17rem, 76vw); scroll-snap-align: start; }
  .board__hint { display: block; }
  .site-nav { gap: var(--space-3); }
  .site-nav a:not(.button) { font-size: var(--text-xs); }
  /* Тринадцать точек с обычным зазором не влезают в 390px */
  .dots__grid { gap: var(--space-2); }
  .tabs__bar { gap: var(--space-2); }
  .tabs__tab { font-size: var(--text-xs); padding: var(--space-2) var(--space-3); }
}

/* =====================================================================
   Внутренние страницы.
   ===================================================================== */

.page-head { padding-bottom: var(--space-6); }
.page-head h1 { font-size: var(--text-2xl); line-height: var(--leading-snug);
                letter-spacing: var(--tracking-tight); margin-bottom: var(--space-4);
                max-width: 22ch; }
.band--thin .section__inner { padding-top: var(--space-5); padding-bottom: var(--space-5); }
.section--tight { padding: var(--space-7) 0; }

/* Оглавление длинной страницы */
.toc { display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-5);
       font-family: var(--font-display); font-size: var(--text-sm); }
.toc a { color: var(--color-ink-muted); }
.toc a:hover { color: var(--color-ink); text-decoration: underline; }

/* Длинный текст */
.prose { padding-top: var(--space-7); padding-bottom: var(--space-7); }
.prose p { max-width: 66ch; margin-bottom: var(--space-4); }
.prose h2 { margin-bottom: var(--space-4); }
.prose--legal p { font-size: var(--text-base); }
.prose--legal h2 { font-size: var(--text-lg); margin-top: var(--space-7); }
.prose--legal h2:first-child { margin-top: 0; }
.prose--legal b { font-weight: var(--weight-medium); }

/* Вопрос — ответ */
.faq { margin: 0; display: grid; gap: 0; }
.faq__item { padding: var(--space-5) 0; border-bottom: var(--border); }
.faq__item:first-child { border-top: var(--border); }
.faq dt { font-family: var(--font-display); font-size: var(--text-base);
          font-weight: var(--weight-medium); margin-bottom: var(--space-2); }
.faq dd { margin: 0; color: var(--color-ink-muted); max-width: 64ch;
          font-size: var(--text-sm); }

/* Выбор движков и переключатель работ */
.chooser { display: grid; gap: var(--space-7); }
.chooser__label { font-family: var(--font-display); font-size: var(--text-xs);
                  letter-spacing: var(--tracking-wide); text-transform: uppercase;
                  color: var(--color-ink-faint); margin-bottom: var(--space-4); }
.chooser__options { display: grid; gap: var(--space-3); }
.choice, .switch { display: grid; grid-template-columns: auto 1fr; gap: var(--space-3);
                   align-items: start; cursor: pointer; padding: var(--space-3);
                   border: var(--border); border-radius: var(--radius-md);
                   transition: border-color var(--duration) var(--ease); }
.choice input, .switch input { position: absolute; opacity: 0; pointer-events: none; }
.choice__box { width: 1.25rem; height: 1.25rem; border: var(--border-strong);
               border-radius: var(--radius-sm); display: inline-flex;
               align-items: center; justify-content: center; color: transparent;
               margin-top: 0.1rem; flex: none; }
.choice__box svg { width: 0.9rem; height: 0.9rem; }
.choice input:checked ~ .choice__box { background: var(--color-accent);
                                       border-color: var(--color-accent); color: #fff; }
.choice:has(input:checked), .switch:has(input:checked) { border-color: var(--color-accent); }
.choice b, .switch b { font-family: var(--font-display); font-weight: var(--weight-medium); }
.choice__note { display: block; font-size: var(--text-sm); color: var(--color-ink-muted);
                margin-top: var(--space-1); max-width: 52ch; }
.switch__track { width: 2.5rem; height: 1.4rem; border-radius: var(--radius-full);
                 background: var(--color-line-strong); position: relative; flex: none;
                 transition: background var(--duration) var(--ease); margin-top: 0.05rem; }
.switch__knob { position: absolute; top: 0.2rem; left: 0.2rem; width: 1rem; height: 1rem;
                border-radius: var(--radius-full); background: #fff;
                transition: transform var(--duration) var(--ease); }
.switch input:checked ~ .switch__track { background: var(--color-accent); }
.switch input:checked ~ .switch__track .switch__knob { transform: translateX(1.1rem); }

/* Скидки за предоплату */
.prepay { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }
.prepay li { display: flex; gap: var(--space-3); align-items: baseline;
             padding-bottom: var(--space-3); border-bottom: var(--border);
             font-size: var(--text-sm); color: var(--color-ink-muted); }
.prepay b { font-family: var(--font-display); font-size: var(--text-base);
            color: var(--color-ink); font-variant-numeric: tabular-nums; }
.prepay__note { border-bottom: 0; color: var(--color-ink-faint); }

/* Шапка отчёта */
.report-head { display: grid; gap: var(--space-5); }
.report-head__label { font-family: var(--font-display); font-size: var(--text-xs);
                      letter-spacing: var(--tracking-wide); text-transform: uppercase;
                      color: var(--color-ink-faint); margin-bottom: var(--space-1); }
.report-head__value { font-size: var(--text-base); margin: 0; }

/* min-width: 0 обязателен: без него элемент сетки не сжимается ниже
   min-content своего содержимого, широкая таблица распирает колонку, и
   вбок едет вся страница вместо самой таблицы */
.split > *, .method > * { min-width: 0; }
.table-wrap { overflow-x: auto; min-width: 0; margin-top: var(--space-5); }
.table-wrap table { width: 100%; min-width: 34rem; table-layout: auto; }
.table-wrap th:first-child, .table-wrap td:first-child { width: 34%; }
.table-wrap th, .table-wrap td { padding-left: var(--space-5); }
.table-wrap th:first-child, .table-wrap td:first-child { padding-left: 0; }
.table-wrap tr.is-you td { background: var(--color-accent-wash); }
.cell-bar { display: inline-flex; align-items: center; gap: var(--space-3);
            justify-content: flex-end; width: 100%; }
.cell-bar::before { content: ""; height: 0.4rem; width: var(--w);
                    background: var(--color-accent); border-radius: var(--radius-full);
                    max-width: 6rem; }

/* Источники */
.sources { list-style: none; margin: var(--space-5) 0 0; padding: 0; display: grid; }
.sources li { display: grid; grid-template-columns: 1fr auto auto; gap: var(--space-4);
              align-items: baseline; padding: var(--space-3) 0;
              border-bottom: var(--border); font-size: var(--text-sm); }
.sources__kind { font-family: var(--font-display); font-size: var(--text-xs);
                 letter-spacing: var(--tracking-wide); text-transform: uppercase;
                 color: var(--color-ink-faint); }
.sources__count { font-family: var(--font-display); font-variant-numeric: tabular-nums; }

/* Цитаты в отчёте: названия выделяются акцентной подложкой,
   иначе браузер рисует их жёлтым маркером по умолчанию */
.answer p { font-size: var(--text-base); line-height: var(--leading-normal);
            max-width: 64ch; margin-bottom: var(--space-3); }
.answer mark { background: none; color: var(--color-ink);
               font-weight: var(--weight-medium);
               box-shadow: inset 0 -0.42em 0 var(--color-accent-wash); }
.answer footer { font-family: var(--font-display); font-size: var(--text-xs);
                 letter-spacing: var(--tracking-wide); text-transform: uppercase;
                 color: var(--color-ink-faint); }
.answer--static { display: block; border: var(--border); border-radius: var(--radius-lg);
                  background: var(--color-surface); padding: var(--space-5);
                  margin-bottom: var(--space-4); }
.answer--static .answer__question { font-size: var(--text-sm);
                    color: var(--color-ink-muted);
                    padding-bottom: var(--space-3); margin-bottom: var(--space-3);
                    border-bottom: var(--border); }
.answer--static .answer__question span { font-family: var(--font-display); font-size: var(--text-xs);
                         letter-spacing: var(--tracking-wide); text-transform: uppercase;
                         color: var(--color-ink-faint); margin-right: var(--space-3); }
.mark--you { box-shadow: inset 0 -0.42em 0 var(--color-signal-wash);
             color: var(--color-signal); }

/* Что менять */
.actions { list-style: none; margin: var(--space-5) 0 0; padding: 0; counter-reset: a;
           display: grid; gap: var(--space-5); }
.action { padding-top: var(--space-4); border-top: 2px solid var(--color-ink); }
.action h3 { font-size: var(--text-lg); margin-bottom: var(--space-2); }
.action__finding { color: var(--color-ink-muted); font-size: var(--text-sm);
                   max-width: 62ch; }
.action__do { display: grid; grid-template-columns: 20px 1fr; gap: var(--space-3);
              font-size: var(--text-sm); max-width: 62ch; }
.action__do .icon { color: var(--color-accent); margin-top: 0.2em; }

/* Списки с галочками, формы-карточки, контакты */
.ticks { list-style: none; margin: var(--space-5) 0 0; padding: 0; display: grid;
         gap: var(--space-3); font-size: var(--text-sm); color: var(--color-ink-muted); }
.ticks li { display: grid; grid-template-columns: 1.1rem 1fr; gap: var(--space-3); }
.form--card { background: var(--color-surface); border: var(--border);
              border-radius: var(--radius-lg); padding: var(--space-6); }
.field textarea { font-family: var(--font-text); font-size: var(--text-base);
                  color: var(--color-ink); padding: 0.65rem 0.85rem;
                  border: var(--border-strong); border-radius: var(--radius-md);
                  background: var(--color-surface); width: 100%; resize: vertical; }
.field textarea:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 1px; }
.field em { font-style: normal; color: var(--color-ink-faint); text-transform: none;
            letter-spacing: 0; }
.form__legal { font-size: var(--text-xs); color: var(--color-ink-faint); margin: 0; }
.contact-mail { font-family: var(--font-display); font-size: var(--text-lg);
                margin: var(--space-5) 0 var(--space-3); }
.contact-mail a { color: var(--color-accent); }
.cta-buttons { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: start; }
.facts-list { margin: 0; display: grid; gap: 0; }
.facts-list > div { display: grid; gap: var(--space-2); padding: var(--space-4) 0;
                    border-bottom: var(--border); }
.facts-list dt { font-family: var(--font-display); font-size: var(--text-sm);
                 color: var(--color-ink-faint); }
.facts-list dd { margin: 0; font-size: var(--text-base); max-width: 62ch; }

@media (min-width: 48rem) {
  .report-head { grid-template-columns: repeat(4, 1fr); }
  .chooser { grid-template-columns: 1.2fr 1fr; gap: var(--space-8); }
  .facts-list > div { grid-template-columns: 14rem 1fr; gap: var(--space-5); }
}
@media (min-width: 64rem) {
  .page-head h1 { font-size: var(--text-display); max-width: 20ch; }
  .actions { grid-template-columns: repeat(2, 1fr); gap: var(--space-6) var(--space-7); }
}

/* =====================================================================
   Разделы длинной страницы: текст слева, схема справа, во всю ширину.
   Оглавления и пометок на полях нет — читателю непонятно, к чему они.
   ===================================================================== */

.page-head__grid { display: grid; gap: var(--space-6); margin-top: var(--space-6); }
.page-head__facts { margin: 0; display: grid; gap: 0; align-content: start; }
.page-head__facts > div { display: grid; grid-template-columns: 3.5rem 1fr;
                          gap: var(--space-4); align-items: baseline;
                          padding: var(--space-4) 0; border-top: var(--border); }
.page-head__facts > div:last-child { border-bottom: var(--border); }
.page-head__facts dt { font-family: var(--font-display); font-size: var(--text-xl);
                       font-weight: var(--weight-medium);
                       font-variant-numeric: tabular-nums; }
.page-head__facts dd { margin: 0; font-size: var(--text-sm);
                       color: var(--color-ink-muted); }

.method { display: grid; gap: var(--space-6); align-items: stretch; }
.method__n {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  color: var(--color-ink-faint);
  margin-bottom: var(--space-3);
}
.method__text h2 { font-size: var(--text-xl); margin-bottom: var(--space-4);
                   max-width: 22ch; }
.method__text p { max-width: 60ch; margin-bottom: var(--space-4); }
/* Карточка тянется на высоту текста, содержимое стоит по центру: короткая
   иллюстрация иначе оставляет под собой пустой угол страницы */
.method__figure { display: grid; align-content: center; }
.band-inner { background: var(--color-surface-sunken);
              border-top: var(--border); border-bottom: var(--border); }
.band-inner .figure { background: var(--color-surface); }

/* --- Визуальные объекты в тексте -------------------------------------- */
.figure { margin: var(--space-6) 0; padding: var(--space-5);
          border: var(--border); border-radius: var(--radius-lg);
          background: var(--color-surface-sunken); }
.figure__label { font-family: var(--font-display); font-size: var(--text-xs);
                 letter-spacing: var(--tracking-wide); text-transform: uppercase;
                 color: var(--color-ink-faint); margin-bottom: var(--space-4); }

.kinds { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }
.kinds li { display: grid; grid-template-columns: 6rem 1fr; gap: var(--space-4);
            align-items: baseline; font-size: var(--text-sm);
            padding-bottom: var(--space-3); border-bottom: var(--border); }
.kinds li:last-child { border-bottom: 0; padding-bottom: 0; }
.kinds b { font-family: var(--font-display); font-weight: var(--weight-medium); }
.kinds span { color: var(--color-ink-muted); }

.drift { display: grid; gap: var(--space-4); }
.drift__row { display: grid; grid-template-columns: 5rem 1fr 3rem; gap: var(--space-4);
              align-items: center; font-size: var(--text-sm); }
.drift__row span { color: var(--color-ink-muted); font-family: var(--font-display);
                   font-size: var(--text-xs); letter-spacing: var(--tracking-wide);
                   text-transform: uppercase; }
.drift__row b { font-family: var(--font-display); font-variant-numeric: tabular-nums;
                text-align: right; }
.drift__track { position: relative; height: 0.5rem; background: var(--color-surface);
                border: var(--border); border-radius: var(--radius-full); }
.drift__track i { position: absolute; top: 50%; width: 0.85rem; height: 0.85rem;
                  margin-top: -0.425rem; margin-left: -0.425rem;
                  background: var(--color-accent); border-radius: 50%; }
.drift__band { margin-left: 5rem; padding-left: var(--space-4);
               border-left: 2px solid var(--color-line-strong); }
.drift__band span { font-size: var(--text-xs); color: var(--color-ink-faint);
                    font-family: var(--font-display); }

.stack { display: grid; gap: var(--space-3); }
.stack__row { display: grid; grid-template-columns: 1fr auto; gap: var(--space-3);
              align-items: center; font-size: var(--text-sm); position: relative;
              padding: var(--space-3); border-radius: var(--radius-md);
              background: var(--color-surface); border: var(--border); }
.stack__bar { position: absolute; left: 0; top: 0; bottom: 0; width: var(--w);
              background: var(--color-accent-wash); border-radius: var(--radius-md); }
.stack__row span:not(.stack__bar) { position: relative; }
.stack__row b { position: relative; font-family: var(--font-display);
                font-variant-numeric: tabular-nums; }
.stack__row--you .stack__bar { background: var(--color-you-wash); }
.stack__row--you b { color: var(--color-you); }

.work { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-4); }
.work li { display: grid; grid-template-columns: 20px 1fr; gap: var(--space-3) var(--space-4);
           font-size: var(--text-sm); }
.work .icon { color: var(--color-accent); grid-row: span 2; margin-top: 0.15em; }
.work b { font-family: var(--font-display); font-weight: var(--weight-medium); }
.work span:not(.icon) { color: var(--color-ink-muted); }

.callout { margin: var(--space-6) 0; padding: var(--space-5);
           border: 1px solid var(--color-signal); border-left-width: 3px;
           border-radius: var(--radius-lg); background: var(--color-signal-wash); }
.callout__label { font-family: var(--font-display); font-size: var(--text-xs);
                  letter-spacing: var(--tracking-wide); text-transform: uppercase;
                  color: var(--color-signal); margin-bottom: var(--space-4); }
.callout ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-4); }
.callout li { display: grid; gap: var(--space-1); font-size: var(--text-sm); }
.callout b { font-family: var(--font-display); font-weight: var(--weight-medium); }
.callout span { color: var(--color-ink-muted); max-width: 60ch; }

@media (min-width: 64rem) {
}
@media (min-width: 60rem) {
  /* Текстовой колонке чуть больше: читают её, а не карточку */
  .method { grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); gap: var(--space-8); }
  .method--flip .method__text { order: 2; }
  .method--flip .method__figure { order: 1; }

  /* Шапка длинной страницы: вводка и три числа рядом */
  .page-head--split .page-head__grid {
    display: grid;
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
    gap: var(--space-8);
    align-items: start;
  }
}
.faq--wide { column-gap: var(--space-8); }
@media (min-width: 60rem) {
  .faq--wide { grid-template-columns: repeat(2, 1fr); }
  .faq--wide .faq__item:nth-child(2) { border-top: var(--border); }
}

/* --- Отчёт как документ ------------------------------------------------ */
.browser--wide { margin-bottom: var(--space-4); }
.browser__screen--report { padding: 0; min-height: 0; gap: 0; }
.doc-head { display: flex; flex-wrap: wrap; justify-content: space-between;
            align-items: baseline; gap: var(--space-4);
            padding: var(--space-5) var(--space-6); border-bottom: var(--border); }
.doc-head__label { font-family: var(--font-display); font-size: var(--text-xs);
                   letter-spacing: var(--tracking-wide); text-transform: uppercase;
                   color: var(--color-ink-faint); }
.doc-head__title { font-family: var(--font-display); font-size: var(--text-lg);
                   font-weight: var(--weight-medium); margin: 0; }
.doc-head__meta { font-size: var(--text-sm); color: var(--color-ink-muted); margin: 0;
                  font-variant-numeric: tabular-nums; }
.doc-scores { display: grid; }
.doc-score { padding: var(--space-4) var(--space-6); border-bottom: var(--border);
             display: grid; grid-template-columns: 7rem 4rem 1fr; gap: var(--space-4);
             align-items: center; }
.doc-score:last-child { border-bottom: 0; }
.doc-score__engine { font-family: var(--font-display); font-size: var(--text-sm);
                     margin: 0; }
.doc-score__value { font-family: var(--font-display); font-size: var(--text-lg);
                    font-variant-numeric: tabular-nums; margin: 0; }
.doc-score__track { height: 0.5rem; background: var(--color-surface-sunken);
                    border-radius: var(--radius-full); overflow: hidden; }
.doc-score__track div { height: 100%; background: var(--color-accent);
                        border-radius: var(--radius-full); }

/* Таблицы отчёта: числа по правому краю, доля — полоса на всю ячейку,
   слабые строки подсвечены сигнальным */
.table-wrap tbody tr:hover td { background: var(--color-surface-sunken); }
/* Заливка провала — только в образце отчёта на сайте: там строка одна из трёх
   и читается как иллюстрация. В кабинете вместо плашки волосок у края строки */
.table-wrap table:not(.data-table) tr.is-gap td { background: var(--color-signal-wash); }
.table-wrap table:not(.data-table) tr.is-gap td:first-child {
  box-shadow: inset 3px 0 0 var(--color-signal); }
.cell-bar { display: grid; grid-template-columns: 1fr auto; gap: var(--space-3);
            align-items: center; min-width: 8rem; }
.cell-bar::before { content: ""; height: 0.4rem; width: 100%; max-width: none;
                    background: linear-gradient(to right,
                      var(--color-accent) var(--w), var(--color-surface-sunken) var(--w));
                    border-radius: var(--radius-full); }
.table-wrap table:not(.data-table) tr.is-gap .cell-bar::before {
  background: linear-gradient(to right,
    var(--color-signal) var(--w), var(--color-signal-wash) var(--w)); }
.cell-bar b { font-family: var(--font-display); font-weight: var(--weight-medium);
              font-variant-numeric: tabular-nums; }
/* Тихий вариант выноски: не сигнал, а просто оговорка */
.callout--quiet { border-color: var(--color-line-strong); background: var(--color-surface-sunken); }
.callout--quiet .callout__label { color: var(--color-ink-faint); }

/* --- Формы: ошибки, ловушка, благодарность ---------------------------- */
/* Поле-ловушка спрятано так, чтобы его не увидел человек и не озвучил
   экранный диктор, но заполнил робот, который читает разметку. */
.trap { position: absolute; left: -9999px; width: 1px; height: 1px;
        overflow: hidden; }
.form__error { color: var(--color-signal); font-size: var(--text-sm);
               font-family: var(--font-text); }
.form__error--top { padding: var(--space-3) var(--space-4);
                    background: var(--color-signal-wash);
                    border: 1px solid var(--color-signal);
                    border-radius: var(--radius-md); margin: 0; }
.field input[aria-invalid="true"], .field textarea[aria-invalid="true"] {
  border-color: var(--color-signal); }
.form--done { display: grid; gap: var(--space-3); }
.form-done__mark { width: 2.25rem; height: 2.25rem; border-radius: var(--radius-full);
                   background: var(--color-accent-wash); color: var(--color-accent);
                   display: inline-flex; align-items: center; justify-content: center;
                   margin: 0; }
.form-done__mark svg { width: 1.25rem; height: 1.25rem; }
.form--done h3 { font-family: var(--font-display); font-size: var(--text-lg); }
.form--done p { color: var(--color-ink-muted); font-size: var(--text-sm); max-width: 46ch; }
/* Пока запрос идёт, кнопка гаснет — htmx сам ставит этот атрибут */
.button[disabled] { opacity: 0.55; pointer-events: none; }

/* --- Пакет проекта на обзоре ------------------------------------------ */
/* Клиент видит, на чём работает, и просит другое здесь же. Кнопки
   выбора — заявка, а не переключатель: об этом сказано строкой ниже. */

.plan-now { margin-top: var(--space-9); padding-top: var(--space-6);
            border-top: var(--border); }
.plan-now__name { font-family: var(--font-display); font-size: var(--text-xl);
                  font-weight: var(--weight-medium); margin-top: var(--space-3); }
.plan-now__name--none { color: var(--color-ink-faint); }
.plan-now__label { margin-top: var(--space-5); font-size: var(--text-sm);
                   color: var(--color-ink-muted); }
.plan-now__pick { display: flex; flex-wrap: wrap; gap: var(--space-3);
                  margin: var(--space-3) 0 var(--space-4); }
/* Кнопки-заявки: контурные, чтобы не спорить с действиями раздела */
.plan-now__pick .button {
  background: none; color: var(--color-ink);
  border: var(--border-strong); padding: 0.5rem 1rem;
  font-size: var(--text-sm);
}
.plan-now__pick .button:hover { border-color: var(--color-ink); color: var(--color-ink); }

/* --- Основатель на /about ---------------------------------------------- */
/* Тонкие линии вместо плиток, как на главной. Факты стоят своей колонкой:
   это перечень умений, и абзацем он читался бы хуже. */

.founder { border-top: var(--border); }
.founder__inner { display: grid; gap: var(--space-7); }

.founder__words p { max-width: 62ch; margin-top: var(--space-4); }
.founder__photo {
  display: block;
  width: 10rem; height: 10rem;
  margin: var(--space-5) 0;
  object-fit: cover;
  border-radius: var(--radius-md);
  border: var(--border);
}
.founder__link { margin-top: var(--space-5); }

.founder__facts { margin: 0; display: grid; gap: 0; align-content: start; }
.founder__facts > div { padding: var(--space-4) 0; border-bottom: var(--border); }
.founder__facts > div:first-child { border-top: var(--border); }
/* Значение крупно, подпись мелко под ним */
.founder__facts dt {
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: var(--text-lg);
  line-height: var(--leading-snug);
}
.founder__facts dd {
  margin: var(--space-2) 0 0;
  font-size: var(--text-sm);
  color: var(--color-ink-muted);
}

@media (min-width: 48rem) {
  .founder__inner { grid-template-columns: 1.5fr 1fr; gap: var(--space-8); }
}


/* =====================================================================
   Кабинет: страницы входа.
   Узкая колонка по центру — на этих экранах читать нечего, кроме формы.
   ===================================================================== */

.auth { padding-top: var(--space-8); padding-bottom: var(--space-9); }
.auth__inner { max-width: 26rem; margin: 0 auto; padding: 0 var(--page-gutter); }
.auth h1 { font-size: var(--text-xl); margin-bottom: var(--space-4); }
.auth .lead { font-size: var(--text-sm); margin-bottom: var(--space-5); }
.auth .form { margin-top: var(--space-4); }

.button--full { width: 100%; }

/* Разделитель «или» между входом через Google и формой */
.auth__or {
  display: flex; align-items: center; gap: var(--space-4);
  margin: var(--space-5) 0 0;
  font-family: var(--font-display); font-size: var(--text-xs);
  color: var(--color-ink-faint);
}
.auth__or::before, .auth__or::after {
  content: ""; flex: 1; height: var(--border-width); background: var(--color-line);
}

.auth__foot { margin-top: var(--space-5); font-size: var(--text-sm);
              color: var(--color-ink-muted); }
.field__hint { font-family: var(--font-display); font-size: var(--text-xs);
               color: var(--color-ink-faint); }

/* =====================================================================
   Кабинет: оболочка по макету приборной панели.

   Две колонки: слева панель с разделами, справа содержимое. Панель
   липкая и не прокручивается вместе с таблицами — раздел всегда видно.
   Углы в кабинете прямые: это инструмент, а не витрина, и скруглённая
   плитка вокруг числа мешает читать столбец.
   ===================================================================== */

.app-body { background: var(--color-surface); }

/* Полоса сотрудника. Своё дело — своё место: инструменты, которых у
   клиента нет вовсе, идут отдельной строкой наверху и приглушённым
   фоном, чтобы не спорить с отчётами за внимание. */
.app-staff { background: var(--color-surface-sunken);
             border-bottom: var(--border); }
.app-staff__inner { display: flex; flex-wrap: wrap; align-items: center;
                    gap: var(--space-3) var(--space-5);
                    padding: var(--space-2) var(--space-5);
                    max-width: 100rem; margin: 0 auto; }
.app-staff__label { font-family: var(--font-display); font-size: 0.66rem;
                    letter-spacing: 0.16em; text-transform: uppercase;
                    color: var(--color-ink-faint); }
.app-staff__nav { display: flex; flex-wrap: wrap; align-items: center;
                  gap: var(--space-2) var(--space-5); }
.app-staff__nav a { font-family: var(--font-display); font-size: var(--text-sm);
                    color: var(--color-ink-muted); display: inline-flex;
                    align-items: center; gap: var(--space-2);
                    padding: var(--space-1) 0; }
.app-staff__nav a:hover { color: var(--color-ink); }
.app-staff__nav a[aria-current="page"] { color: var(--color-ink);
                                         font-weight: var(--weight-medium);
                                         box-shadow: inset 0 -2px 0 var(--color-accent); }
.app-staff__side { margin-left: auto; }
/* На телефоне полоса не переносится, а прокручивается вбок: перенос
   съедал четверть первого экрана ещё до заголовка страницы */
@media (max-width: 56.25rem) {
  .app-staff__inner { flex-wrap: nowrap; overflow-x: auto; gap: var(--space-4);
                      padding: var(--space-1) var(--space-4);
                      scrollbar-width: none; }
  .app-staff__inner::-webkit-scrollbar { display: none; }
  .app-staff__nav { flex-wrap: nowrap; gap: var(--space-4); }
  .app-staff__nav a, .app-staff__label { white-space: nowrap; }
  .app-staff__side { margin-left: 0; }
}
/* Кнопки и поля кабинета. Пилюля, как на сайте, читается здесь значком,
   а полный ноль скругления плюс волосяная рамка — «неоформленный HTML»,
   каким кабинет и выглядел. Берём середину: 6 пикселей, плотные поля,
   заметное наведение и видимый фокус. */
.app-body .button, .app-body input, .app-body textarea, .app-body select {
  border-radius: 6px; }
.app-body .button {
  font-size: var(--text-sm); font-weight: var(--weight-medium);
  padding: 0.55rem 1rem; line-height: 1.2;
  transition: background-color var(--duration) var(--ease),
              border-color var(--duration) var(--ease),
              color var(--duration) var(--ease);
}
.app-body .button--primary { background: var(--color-accent);
                             color: var(--color-accent-ink); border: 0; }
.app-body .button--primary:hover { background: oklch(0.34 0.055 152); }
/* Вторая кнопка — мягкая заливка, а не рамка-волосок: рамка на светлом
   фоне теряется, и действие выглядит текстом */
.app-body .button--secondary { background: var(--color-surface-sunken);
                               border: 1px solid var(--color-line);
                               color: var(--color-ink); }
.app-body .button--secondary:hover { background: var(--ok-wash);
                                     border-color: var(--ok-line);
                                     color: var(--color-accent); }
.app-body .button--quiet { padding-left: 0; padding-right: 0; }
.app-body .button:focus-visible { outline: 2px solid var(--color-focus);
                                  outline-offset: 2px; }
.app-body input, .app-body textarea, .app-body select {
  border: 1px solid var(--color-line); padding: 0.55rem 0.75rem;
  background: var(--color-surface);
}
.app-body input:focus-visible, .app-body textarea:focus-visible,
.app-body select:focus-visible { outline: 2px solid var(--color-focus);
                                 outline-offset: 1px; border-color: var(--color-accent); }

/* Вывод экрана. Крупнее таблицы под ним намеренно: таблица нужна тем,
   кто захочет проверить, а вывод — всем остальным. Светлая заливка
   и акцентная черта слева делают его первым, на что падает взгляд. */
.verdict-card { margin: var(--space-6) 0 var(--space-7);
                padding: var(--space-5) var(--space-6);
                border: 1px solid var(--color-line); border-left: 3px solid var(--color-ink-muted);
                border-radius: 6px; background: var(--color-surface-sunken);
                box-shadow: var(--shadow-card); }
/* Цвет плашки — по сути сказанного. Зелёный фон над словами «вас нет
   у двух ассистентов из трёх» замечают быстрее, чем сам текст */
.verdict-card--ok { background: var(--ok-wash); border-color: var(--ok-line);
                    border-left-color: var(--ok); }
.verdict-card--warn { background: var(--warn-wash); border-color: var(--warn-line);
                      border-left-color: oklch(0.62 0.13 75); }
.verdict-card--bad { background: var(--bad-wash); border-color: var(--bad-line);
                     border-left-color: var(--bad); }
.verdict-card__label { margin: 0 0 var(--space-2); font-family: var(--font-display);
                       font-size: 0.66rem; letter-spacing: 0.16em;
                       text-transform: uppercase; color: var(--color-ink-muted); }
.verdict-card__text { margin: 0; font-size: var(--text-lg);
                      line-height: var(--leading-snug); max-width: 60ch; }
.verdict-card__marks { list-style: none; display: flex; flex-wrap: wrap;
                       gap: var(--space-3) var(--space-6);
                       margin: var(--space-4) 0 0; padding: 0;
                       font-size: var(--text-sm); align-items: center; }
.verdict-card__marks li { display: inline-flex; align-items: center; gap: var(--space-2); }

/* --- Таблицы на телефоне -----------------------------------------------
   Главная жалоба: первая колонка занимает половину экрана, и до второй
   не добраться. Чинится тремя вещами сразу.

   1. Первая колонка перестаёт быть широкой: 34% ширины она держала,
      чтобы длинный вопрос не рвался, — но на 390 пикселях это 130 точек
      под текст и ничего под числа.
   2. Она становится липкой: при прокрутке вбок название остаётся
      на месте, и видно, к чему относится число. Это и есть ответ
      на «неудобно сопоставлять»: раньше, докрутив до Claude, человек
      терял, чья это строка.
   3. У края появляется тень — видно, что справа есть ещё.

   Горизонтальная прокрутка внутри блока, а не всей страницы: страница
   на телефоне не ездит вбок никогда. */
@media (max-width: 56.25rem) {
  .app-body .table-wrap table { min-width: 0; }
  /* Шрифт в таблицах на телефоне мельче основного: таблица — это сетка
     чисел, её читают не как текст, а как карту, и лишние два пикселя
     кегля стоят целой колонки */
  .app-body .table-wrap th, .app-body .table-wrap td { font-size: 0.8125rem; }
  .app-body .table-wrap td { padding-top: 0.6rem; padding-bottom: 0.6rem; }

  .app-body .table-wrap th:first-child,
  .app-body .table-wrap td:first-child {
    /* `width: 1px` — не ширина, а приказ раскладке: «ужми колонку
       до минимально возможной». Без него браузер отдаёт колонке
       с самым длинным текстом всю свободную ширину, и на экране
       источников название домена занимало 212 точек из 375 — больше
       половины, при том что таблица помещалась целиком.

       `max-width` здесь бесполезен: в таблице с автоматической
       раскладкой браузер его не соблюдает. Поэтому и трюк с единицей.

       `overflow-wrap: anywhere` разрешает разорвать длинное слово:
       «triodent.od.ua» — одно слово, и без разрыва колонка не ужимается
       ниже его длины. Нижняя граница держится `min-width`, иначе
       название разъехалось бы по букве в строке. */
    width: 1px; min-width: 7rem; max-width: 9rem;
    overflow-wrap: anywhere;
    position: sticky; left: 0; z-index: 2;
    background: var(--color-surface);
    /* Волосок справа отделяет липкую колонку от уезжающих под неё */
    box-shadow: 1px 0 0 var(--color-line);
  }
  /* Метка «tracked» под названием растягивала строку на три этажа.
     На телефоне она мельче и прижата к названию */
  .app-body .table-wrap td:first-child .tag {
    font-size: 0.56rem; padding: 0.1rem 0.3rem; margin-top: 0.15rem;
  }
  /* Строка «это вы» и провал держат свою заливку и под липкой колонкой */
  .app-body .table-wrap tr.is-you td:first-child { background: var(--color-you-wash); }
  .app-body .data-table tr.is-gap td:first-child {
    box-shadow: 1px 0 0 var(--color-line), inset 2px 0 0 var(--color-signal); }
  /* Остальные столбцы ужимаются до содержимого: числу хватает своей
     ширины, и в экран помещается не один столбец, а три.
     Переносить нельзя числа — заголовку перенос как раз нужен: «Share of
     answers» в одну строку шире всей колонки и выталкивал значения
     за экран */
  .app-body .table-wrap th:not(:first-child),
  .app-body .table-wrap td:not(:first-child) { padding-left: var(--space-4); }
  .app-body .table-wrap td:not(:first-child) { white-space: nowrap; }
  /* Разрядку в шапке на телефоне убираем: «SHARE OF ANSWERS» с ней
     ложится в три строки, без неё — в две */
  .app-body .table-wrap th:not(:first-child) { white-space: normal;
                                               max-width: 8rem;
                                               letter-spacing: 0.04em; }
  .app-body .data-table th { font-size: 0.62rem; }
  /* Прокрутка останавливается на начале столбца, а не посреди числа */
  .app-body .table-wrap { scroll-snap-type: x proximity; }
  .app-body .table-wrap th, .app-body .table-wrap td { scroll-snap-align: start; }
}

/* Альбомная ориентация на телефоне: ширины хватает, и таблица
   разворачивается целиком — ни липкой колонки, ни прокрутки.
   Об этом сказано словами в подсказке под таблицей: сама по себе
   такая возможность не обнаруживается */
@media (max-width: 56.25rem) and (orientation: landscape) {
  .app-body .table-wrap th:first-child,
  .app-body .table-wrap td:first-child { position: static; box-shadow: none;
                                         max-width: none; }
}

/* Строка под таблицей: пометка о прокрутке и кнопка разворота.

   Видна только там, где в ней есть смысл: на узком экране и только
   когда таблица действительно не поместилась (класс `has-overflow`
   ставит скрипт на обёртке). Подсказка, не ведущая никуда, хуже
   отсутствующей. */
.table-tools { display: none; }
@media (max-width: 56.25rem) {
  .table-wrap.has-overflow + .table-tools,
  .table-wrap.is-scrollable + .table-tools {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--space-3); margin: var(--space-2) 0 0;
  }
  .table-tools__swipe { font-size: 0.6875rem; color: var(--color-ink-faint);
                        line-height: 1; }
  .table-tools__swipe::before { content: "↔ "; }
  .table-tools__full {
    display: inline-flex; align-items: center; gap: 0.3rem;
    /* Цель нажатия 44 точки, но видимой высоты у кнопки нет: отступ
       съедал бы место под данные. Поэтому запас уходит в поля,
       а не в заливку */
    min-height: 44px; padding: 0 0 0 var(--space-3);
    border: 0; background: none; cursor: pointer;
    font-family: var(--font-display); font-size: 0.6875rem;
    letter-spacing: 0.04em; text-transform: uppercase;
    color: var(--color-accent);
  }
  .table-tools__full .icon { width: 0.85rem; height: 0.85rem; }
}

/* --- Прокрутка вбок ----------------------------------------------------
   Ряд, который не помещается в ширину экрана, по умолчанию молчит:
   человек видит обрезанный край и считает, что это всё. Отсюда половина
   жалоб на кабинет с телефона — «колонка с долей не показывается»,
   хотя она просто правее.

   Решение одно на все такие ряды: тень у правого края, пока есть что
   прокручивать, и она пропадает, когда докрутили до конца. Тень рисуется
   фоном самого элемента (приём с четырьмя слоями background-attachment),
   без единой строки скрипта — значит работает и при выключенном
   JavaScript, и не стоит ни одного кадра на прокрутке. */
.swipe {
  /* Цвет заглушки по краям. По умолчанию — основной фон, но ряд на
     подложке переопределяет его у себя: иначе заглушка рисует по тёмному
     фону светлые пятна поверх текста */
  --swipe-bg: var(--color-surface);
  overflow-x: auto;
  /* Полосу прокрутки прячем: она тут не навигация, а шум */
  scrollbar-width: none; -ms-overflow-style: none;
  /* Инерция на iOS и остановка на краю соседнего столбца */
  -webkit-overflow-scrolling: touch;
  background:
    /* заглушка слева и справа — закрывает тень, когда докрутили до края */
    linear-gradient(to right, var(--swipe-bg) 30%, transparent) left center,
    linear-gradient(to left, var(--swipe-bg) 30%, transparent) right center,
    /* сами тени */
    radial-gradient(farthest-side at 0 50%,
      oklch(0.19 0.0068 78 / 0.16), transparent) left center,
    radial-gradient(farthest-side at 100% 50%,
      oklch(0.19 0.0068 78 / 0.16), transparent) right center;
  background-repeat: no-repeat;
  /* Тень узкая намеренно: она подсказка, а не оформление. Была в рем
     шириной — на узкой таблице читалась как затемнённый столбец */
  background-size: 1.75rem 100%, 1.75rem 100%, 0.6rem 100%, 0.6rem 100%;
  background-attachment: local, local, scroll, scroll;
}
.swipe::-webkit-scrollbar { display: none; }

/* Подпись «листается вбок». Нужна там, где тени мало: ряд фильтров
   узкий, и тень на нём читается как край блока, а не как обещание
   продолжения. Показывается только на узком экране и только когда
   прокручивать действительно есть что — класс ставит скрипт. */
.swipe-hint { display: none; }
@media (max-width: 56.25rem) {
  .has-overflow > .swipe-hint, .swipe-hint.is-needed {
    display: inline-flex; align-items: center; gap: 0.3rem;
    margin-left: var(--space-2); flex: none;
    font-family: var(--font-display); font-size: var(--text-xs);
    color: var(--color-ink-faint); white-space: nowrap;
  }
  .swipe-hint::after { content: "›››"; letter-spacing: -0.1em;
                       animation: nudge 2.4s ease-in-out infinite; }
}
@keyframes nudge {
  0%, 60%, 100% { transform: translateX(0); opacity: 0.55; }
  30% { transform: translateX(3px); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .swipe-hint::after { animation: none; }
}

/* --- Светофор ----------------------------------------------------------
   Плашка состояния: цвет и слово вместе. Цвет понимают за десятую долю
   секунды, слово — за секунду, и слепой к цвету человек не теряет ничего,
   потому что слово есть всегда. */
.state { display: inline-flex; align-items: center; gap: 0.4rem;
         padding: 0.2rem 0.55rem; border-radius: var(--radius-full);
         font-family: var(--font-display); font-size: var(--text-xs);
         font-weight: var(--weight-medium); white-space: nowrap;
         border: 1px solid transparent; }
.state::before { content: ""; width: 0.45rem; height: 0.45rem;
                 border-radius: var(--radius-full); background: currentColor; }
.state--ok { background: var(--ok-wash); border-color: var(--ok-line); color: var(--ok); }
.state--warn { background: var(--warn-wash); border-color: var(--warn-line);
               color: oklch(0.45 0.1 75); }
.state--bad { background: var(--bad-wash); border-color: var(--bad-line); color: var(--bad); }
.state--flat { background: var(--color-surface-sunken); border-color: var(--color-line);
               color: var(--color-ink-muted); }

/* Число, окрашенное по состоянию: 100% и 0% больше не выглядят одинаково.
   Правило с двумя классами намеренно: у части чисел цвет задан своим
   классом (`.strength__share`, `.cell-bar b`), и одного класса не хватило
   бы, чтобы его перебить */
.app-body .value--ok, .value--ok { color: var(--ok); }
.app-body .value--warn, .value--warn { color: oklch(0.45 0.1 75); }
.app-body .value--bad, .value--bad { color: var(--bad); }

/* Изменение с прошлого замера: рост зелёным, падение красным, ноль серым.
   Стрелка остаётся — цвет без знака читается хуже, чем знак без цвета */
.delta { display: inline-flex; align-items: center; gap: 0.3rem;
         font-family: var(--font-mono); font-size: var(--text-sm);
         font-weight: var(--weight-medium); }
.delta--up { color: var(--ok); }
.delta--down { color: var(--bad); }
.delta--flat { color: var(--color-ink-muted); }

/* На сайте «вторая» кнопка — это ссылка со стрелкой без подложки, и там
   это верно: рядом всегда стоит цветная главная. В кабинете она часто
   единственная в блоке, и без рамки читается как обычный текст — именно
   поэтому «Send it» под полем ввода не выглядел кнопкой. */
.app-body .button--secondary {
  padding-left: var(--space-5); padding-right: var(--space-5);
  border: var(--border-strong); color: var(--color-ink);
}
.app-body .button--secondary:hover { border-color: var(--color-accent);
                                     color: var(--color-accent); }

/* Карточка действия. Всё, что принимает ввод или что-то запускает,
   стоит в рамке: на общем фоне форма читалась продолжением текста,
   и человек не понимал, что здесь можно что-то сделать. */
/* Хвост длинной таблицы. Строка-раскрывашка, а не кнопка: это не
   действие, а продолжение того же списка */
.more-rows { margin-top: var(--space-4); }
.more-rows > summary { cursor: pointer; font-family: var(--font-display);
                       font-size: var(--text-sm); color: var(--color-accent);
                       padding: var(--space-3) 0; }
.more-rows > summary:hover { color: var(--color-accent-strong); }
.more-rows[open] > summary { color: var(--color-ink-muted); }

.app-card { margin-top: var(--space-6); padding: var(--space-6);
            border: var(--border); background: var(--color-surface-raised); }
.app-card > :first-child { margin-top: 0; }
.app-card .app-h2 { margin-top: 0; padding-top: 0; border-top: 0; }
.app-card .note { margin-top: var(--space-3); }
.app-side { border-bottom: var(--border); background: var(--color-surface); }
.app-side__inner { display: flex; flex-direction: column; gap: var(--space-5);
                   padding: var(--space-4) var(--page-gutter); }
.app-side__top { display: flex; flex-direction: column; gap: var(--space-4); }

.app-side__project { display: flex; flex-wrap: wrap; align-items: baseline;
                     gap: var(--space-3); }
.app-side__name { font-family: var(--font-display); font-size: var(--text-md);
                  font-weight: var(--weight-medium); }
.app-side__account { font-family: var(--font-mono); font-size: var(--text-xs);
                     color: var(--color-ink-faint); }

/* Разделы: на узком экране лентой, на широком столбцом */
.app-side__nav { display: flex; flex-wrap: wrap;
                 gap: var(--space-2) var(--space-4); }
/* Раздел отчётов. Крупнее подпунктов и темнее — иначе список из
   четырёх разделов и пятнадцати подразделов читается одной серой
   простынёй, в которой не видно, где ты находишься */
.app-side__nav a {
  position: relative;
  font-family: var(--font-display); font-size: var(--text-base);
  font-weight: var(--weight-medium);
  color: var(--color-ink-80); white-space: nowrap; padding: var(--space-2) 0;
}
.app-side__nav a:hover { color: var(--color-ink); }
.app-side__nav a[aria-current="page"] { color: var(--color-ink);
                                        font-weight: var(--weight-medium); }
/* Отметка текущего раздела — волосок акцентом, а не заливка */
.app-side__nav a[aria-current="page"]::before {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0;
  height: 2px; background: var(--color-accent);
}
/* Название раздела и стрелка к нему — одна строка меню. По названию
   открывается обзор раздела, по стрелке — список внутри него, не уходя
   со страницы. Без JavaScript стрелки нет вовсе: нажимать было бы не на
   что, и тогда меню выглядит как раньше — ссылка прямым пунктом списка,
   подразделы только у текущего раздела. */
.app-side__group { display: contents; }
.app-side__toggle { display: none; }

.js .app-side__group { display: flex; align-items: center; gap: var(--space-2); }
.js .app-side__group > a { flex: 1; min-width: 0; }
.js .app-side__toggle {
  display: inline-flex; align-items: center; justify-content: center;
  flex: none; width: 1.75rem; height: 1.75rem;
  margin: 0; padding: 0; border: 0; background: none;
  color: var(--color-ink-faint); cursor: pointer;
}
.js .app-side__toggle:hover { color: var(--color-ink); }
.js .app-side__toggle .icon { display: inline-flex; width: 1rem; height: 1rem; }
.js .app-side__toggle .icon svg { width: 100%; height: 100%;
                                  transition: transform 160ms ease; }
.js .app-side__toggle[aria-expanded="true"] { color: var(--color-ink); }
.js .app-side__toggle[aria-expanded="true"] .icon svg { transform: rotate(180deg); }
.js .app-side__toggle:focus-visible { outline: 2px solid var(--color-focus);
                                      outline-offset: 2px;
                                      border-radius: var(--radius-sm); }

/* Подразделы текущего раздела: на ступень правее и мельче, чтобы
   разделы читались списком из четырёх, а не из пятнадцати строк */
.app-side__sub { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); }
/* Со стрелкой список становится столбиком с волоском слева: раскрытых
   разделов может быть несколько, и в строчку они слиплись бы */
.js .app-side__sub { flex-direction: column; flex-wrap: nowrap; gap: 0;
                     margin: var(--space-1) 0 var(--space-3) var(--space-1);
                     padding-left: var(--space-3);
                     border-left: 1px solid var(--color-line); }
/* Свёрнутый список: своё правило обязательно — display у класса сильнее
   браузерного [hidden] и перекрыл бы его */
.app-side__sub[hidden] { display: none; }
.app-side__sub a { position: relative; font-family: var(--font-display);
                   font-size: var(--text-sm); line-height: 1.35;
                   font-weight: var(--weight-regular);
                   color: var(--color-ink-muted); padding: var(--space-1) 0; }
.app-side__sub a:hover { color: var(--color-ink); }
/* Текущий экран: тёмный текст и акцентная метка слева. Раньше отличие
   было только в насыщенности, и на мелком тексте его не было видно */
.app-side__sub a[aria-current="page"] { color: var(--color-ink);
                                        font-weight: var(--weight-medium); }


.app-side__foot { display: flex; flex-wrap: wrap; align-items: center;
                  gap: var(--space-3); }
.app-user { font-family: var(--font-display); font-size: var(--text-sm);
            color: var(--color-ink-muted); }
.app-user:hover { color: var(--color-ink); }

.project-name {
  font-family: var(--font-display); font-size: var(--text-sm);
  font-weight: var(--weight-medium); color: var(--color-ink);
}

/* Выбор проекта. Своя кнопка и свой список: системный выпадающий список
   рисует операционная система, и он выбивается из всего кабинета.
   Вместо рамки — тонкая линия, вместо системной стрелки — своя,
   тем же волоском в 1.5px, что и значки сайта. */
.picker { position: relative; }
.picker__button {
  display: flex; align-items: center; gap: var(--space-3);
  width: 100%; min-height: 2.25rem; padding: 0.25rem 0;
  border: 0; border-bottom: var(--border-strong); border-radius: 0;
  background: none; cursor: pointer; text-align: left;
  font-family: var(--font-display); font-size: var(--text-sm);
  font-weight: var(--weight-medium); color: var(--color-ink);
}
.picker__button:hover { border-bottom-color: var(--color-accent); }
.picker__button:focus-visible { outline: 2px solid var(--color-focus);
                                outline-offset: 2px; }
/* Стрелка нарисована двумя гранями квадрата — тот же приём, что у значков:
   один волосок, никакой заливки */
.picker__arrow {
  margin-left: auto; width: 0.42em; height: 0.42em;
  border-right: 1.5px solid var(--color-ink-muted);
  border-bottom: 1.5px solid var(--color-ink-muted);
  transform: translateY(-0.15em) rotate(45deg);
}
.picker__button[aria-expanded="true"] .picker__arrow {
  transform: translateY(0.1em) rotate(225deg);
}

.picker__list { list-style: none; margin: var(--space-2) 0 0; padding: 0; }
.picker__list a {
  display: block; padding: var(--space-2) var(--space-3);
  font-family: var(--font-display); font-size: var(--text-sm);
  color: var(--color-ink-muted);
}
.picker__list a:hover { color: var(--color-ink);
                        background: var(--color-surface-sunken); }
.picker__list a[aria-current="true"] { color: var(--color-ink);
                                       font-weight: var(--weight-medium); }

/* Со скриптом список живёт за кнопкой и раскрывается поверх страницы.
   Без скрипта он просто стоит на месте: перейти можно и так. */
.js .picker__list {
  /* Ширина по самому длинному названию, но не уже кнопки: имена проектов
     не должны переноситься по слогам */
  display: none; position: absolute; left: 0; top: calc(100% + 2px);
  min-width: 100%; width: max-content; max-width: 18rem;
  z-index: 50; padding: var(--space-2) 0;
  border: var(--border-strong); background: var(--color-surface-raised);
  box-shadow: 0 6px 24px oklch(0.19 0.0068 78 / 0.08);
}
.js .picker[data-open="yes"] .picker__list { display: block; }

/* Кнопка без рамки — для действий, которые не должны спорить с содержанием */
.button--quiet { background: none; border: none; color: var(--color-ink-muted);
                 padding: 0.4rem 0.5rem; }
.button--quiet:hover { color: var(--color-ink); }

/* Мелкая надпись-уточнение: одна на весь кабинет */
.app-label {
  font-family: var(--font-display);
  font-size: 0.66rem; line-height: 1.2;
  letter-spacing: 0.16em; text-transform: uppercase;
  font-weight: var(--weight-medium);
  color: var(--color-ink-muted);
}

.app-section { padding: var(--space-7) 0 var(--space-9); }
/* Лестница кабинета в три ступени. До этого заголовок страницы и
   заголовок раздела внутри неё отличались на два пикселя и были одного
   цвета — «начался новый раздел» не читалось вовсе.

   1. Название экрана — 26 px, самый крупный текст на странице.
   2. Раздел внутри экрана — 18 px с волоском сверху: видно, что
      предыдущее кончилось.
   3. Подраздел — 15 px полужирным, без линии. */
.app-section h1 { font-size: 1.625rem; line-height: var(--leading-snug);
                  letter-spacing: var(--tracking-tight);
                  margin-bottom: var(--space-5); }
/* Шапка раздела одна во всём кабинете: заголовок, под ним вводная строка,
   и волосок под ними. Если вводной строки нет, волосок ложится под заголовок. */
.app-section__inner > h1 { margin: 0 0 var(--space-6); padding-bottom: var(--space-5);
                           border-bottom: var(--border); }
.app-section__inner > h1:has(~ .section-head) {
  margin-bottom: var(--space-3); padding-bottom: 0; border-bottom: 0; }
/* Полоса во всю ширину, текст в ней — не длиннее 62 знаков */
/* Вводная строка экрана — то, с чего человек начинает читать. Акцентный
   волосок слева даёт глазу точку входа: раньше страница открывалась
   заголовком и сразу таблицей, и взгляд падал в неё без подготовки */
.section-head { padding-bottom: var(--space-5); margin-bottom: var(--space-6);
                border-bottom: var(--border); }
.app-body .section-head { padding-left: var(--space-4);
                          border-left: 2px solid var(--color-accent); }
.section-head__meta { max-width: 68ch; margin: 0;
                      font-size: var(--text-md); line-height: var(--leading-normal);
                      color: var(--color-ink-80); }
.app-section__inner { max-width: var(--page-max); margin: 0 auto;
                      padding: 0 var(--page-gutter); }

/* ---------------------------------------------------------------------
   Кабинет на телефоне: узкая шапка и меню слоем поверх страницы.

   Ниже 900px боковая колонка лентой занимает две строки над содержимым
   и съедает первый экран — тот самый, ради которого человек перешёл
   по ссылке из письма. Поэтому она прячется за кнопку, а в строке
   остаётся то, что отвечает на вопрос «где я»: знак, проект, меню.

   Всё ниже включается только при работающем JavaScript (класс .js
   ставится в <head> до первой отрисовки). Без него меню не открылось бы
   вовсе, и лента над содержимым — честный запасной вариант.
   --------------------------------------------------------------------- */

.app-top { display: none; }
.app-burger { display: none; }
/* Число у пункта меню — только на узком экране: на широком оно стоит
   на кнопке экрана Reports, и в меню было бы вторым тем же числом */
.badge--narrow { display: none; }

@media (max-width: 56.25rem) {
  /* Шапка стоит над слоем меню: иначе кнопка, которой меню закрывают,
     оказывается под затемнением и нажимается только промахом мимо панели */
  .js .app-top { position: sticky; top: 0; z-index: 70;
                 display: flex; align-items: center; gap: var(--space-3);
                 padding: var(--space-2) var(--page-gutter);
                 background: var(--color-surface); border-bottom: var(--border); }
  .js .app-top .lockup { flex: none; }
  .app-top__name { flex: 1; min-width: 0; margin: 0;
                   font-family: var(--font-display); font-size: var(--text-sm);
                   font-weight: var(--weight-medium); color: var(--color-ink);
                   white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

  /* Кнопка своя: тот же знак, что в шапке сайта, и палец по ней попадает */
  .js .app-burger { position: relative; display: inline-flex;
                    align-items: center; justify-content: center;
                    width: 2.75rem; height: 2.75rem; flex: none;
                    margin-right: calc(var(--space-2) * -1);
                    border: 0; background: none; color: var(--color-ink);
                    cursor: pointer; }
  .app-burger:focus-visible { outline: 2px solid var(--color-focus);
                              outline-offset: -2px; }
  .app-burger .icon svg { width: 1.5rem; height: 1.5rem; }
  .app-burger__close { display: none; }
  .app-burger[aria-expanded="true"] .app-burger__open { display: none; }
  .app-burger[aria-expanded="true"] .app-burger__close { display: inline-flex; }
  /* Точка вместо числа: на кнопке размером с палец число не читается,
     а «что-то ждёт» — читается */
  .app-burger[data-waiting="yes"]::after {
    content: ""; position: absolute; top: 0.55rem; right: 0.5rem;
    width: 0.45rem; height: 0.45rem; border-radius: var(--radius-full);
    /* Тем же акцентом, что и счётчик в меню: сигнальный красный оставлен
       провалам и нулям, а очередь — это не провал */
    background: var(--color-accent);
  }

  /* Затемнение — сам .app-side, панель лежит внутри: промах мимо панели
     и есть нажатие по затемнению */
  .js .app-side { position: fixed; inset: 0; z-index: 60; border-bottom: 0;
                  background: color-mix(in oklab, var(--color-ink) 38%, transparent);
                  opacity: 0; visibility: hidden;
                  transition: opacity 220ms ease, visibility 0s linear 220ms; }
  .js .app-side[data-menu="open"] { opacity: 1; visibility: visible;
                  transition: opacity 220ms ease, visibility 0s; }
  .js .app-side__inner { position: absolute; inset-block: 0; left: 0;
                  width: min(21rem, 88vw); overflow-y: auto;
                  gap: var(--space-6); background: var(--color-surface);
                  border-right: var(--border);
                  /* Сверху — место под узкую шапку: она лежит поверх панели */
                  padding: 4rem var(--space-5) var(--space-6);
                  transform: translateX(-100%);
                  transition: transform 230ms ease; }
  .js .app-side[data-menu="open"] .app-side__inner { transform: none; }
  .js .app-side__inner:focus-visible { outline: none; }
  /* Знак и название проекта уже стоят в шапке над меню — вторые тут лишние */
  .js .app-side__inner > .app-side__top > .lockup { display: none; }

  /* В меню разделы стоят столбцом — тем же списком, что на широком экране,
     а не лентой: в ленте подразделы уезжают за край */
  .js .app-side__nav { flex-direction: column; flex-wrap: nowrap;
                       gap: var(--space-1); border-top: var(--border);
                       padding-top: var(--space-4); }
  .js .app-side__nav a { display: flex; align-items: center; min-height: 2.75rem;
                         padding: var(--space-2) 0 var(--space-2) var(--space-4); }
  .js .app-side__nav a[aria-current="page"]::before {
    left: 0; right: auto; top: 0.35rem; bottom: 0.35rem;
    width: 2px; height: auto;
  }
  /* На телефоне стрелка — цель под палец: 44 px, как у прочих кнопок
     кабинета, и с кружком под ней. Голая стрелка такого размера на краю
     строки читается как украшение, а не как то, на что нажимают */
  .js .app-side__toggle { width: 2.75rem; min-height: 2.75rem;
                          color: var(--color-ink-muted); }
  .js .app-side__toggle .icon {
    align-items: center; justify-content: center;
    width: 2rem; height: 2rem; border-radius: var(--radius-full);
    background: var(--color-surface-sunken);
  }
  .js .app-side__toggle .icon svg { width: 1rem; height: 1rem; }
  /* Раскрытое состояние — волосок акцентом по кружку: той же отметкой,
     какой в этом меню помечен текущий раздел */
  .js .app-side__toggle[aria-expanded="true"] .icon {
    box-shadow: inset 0 0 0 1px var(--color-accent);
  }
  .js .app-side__toggle:focus-visible { outline-offset: -4px;
                                        border-radius: var(--radius-full); }

  .js .app-side__sub { margin: var(--space-1) 0 var(--space-2) var(--space-4); }
  .js .app-side__sub a { display: flex; align-items: center; min-height: 2.5rem;
                         padding: var(--space-1) 0; font-size: var(--text-sm); }
  .js .app-side__foot { flex-direction: column; align-items: flex-start;
                        gap: var(--space-3); }
  .js .badge--narrow { display: inline-block; }

  /* Страница под открытым меню не едет: закрыв его, человек должен
     оказаться там же, где был */
  .menu-open, .menu-open body { overflow: hidden; }
}

@media (prefers-reduced-motion: reduce) {
  .js .app-side, .js .app-side__inner,
  .js .app-side__toggle .icon svg { transition-duration: 0s; }
}

@media (min-width: 64rem) {
  .app-body { display: grid; grid-template-columns: 17rem minmax(0, 1fr);
              /* Кабинет — рабочий экран, а не страница для чтения: таблицы
                 занимают ширину, которая есть. На узкой раскладке остаётся
                 прежний предел, на широкой пустая треть справа исчезает */
              max-width: 100rem; margin: 0 auto; min-height: 100vh;
              /* Поля у всего кабинета: без них боковая колонка липнет
                 к краю окна */
              padding-right: var(--space-6); }
  /* Полосы поверх обеих колонок: режим просмотра и инструменты сотрудника.
     Без этого полоса становится первой ячейкой сетки и выталкивает
     боковую колонку во вторую — меню уезжает к правому краю */
  .impersonating, .app-staff { grid-column: 1 / -1; }
  .app-side { border-bottom: 0; border-right: var(--border); }
  .app-side__inner { position: sticky; top: 0; height: 100vh;
                     justify-content: space-between;
                     padding: var(--space-6) var(--space-5) var(--space-6)
                              var(--space-6); }
  .app-side__nav { flex-direction: column; gap: var(--space-1); overflow: visible;
                   padding-top: 0; border-top: 0; }
  /* Подпись колонки: после переезда служебного наверх здесь остались
     только отчёты, и список стоит назвать — иначе непонятно, чего он */
  .app-side__label { margin: var(--space-5) 0 var(--space-2);
                     padding-top: var(--space-4); border-top: var(--border); }
  .app-side__nav a { padding: var(--space-2) 0 var(--space-2) var(--space-4); }
  /* Отметка раздела переезжает на левый край строки */
  .app-side__nav a[aria-current="page"]::before {
    left: 0; right: auto; top: 0.25rem; bottom: 0.25rem;
    width: 3px; height: auto;
  }
  .app-side__sub { flex-direction: column; gap: 0;
                   margin: var(--space-1) 0 var(--space-4) var(--space-4);
                   padding-left: var(--space-4);
                   border-left: 1px solid var(--color-line); }
  .app-side__sub a { padding: 0.35rem 0; }
  /* Текущий экран внутри раздела: акцентная метка на том же волоске,
     которым очерчен список. Видно, в какой строке ты стоишь, не читая */
  .app-side__sub a[aria-current="page"]::before {
    content: ""; position: absolute; left: calc(-1 * var(--space-4) - 1px);
    top: 0.3rem; bottom: 0.3rem; width: 3px; background: var(--color-accent);
  }
  /* Текущий экран ещё и подложкой: метка на волоске видна, только если
     её искать, а подложку глаз находит сам */
  .app-side__sub a[aria-current="page"] {
    background: var(--ok-wash); border-radius: 4px;
    margin-left: calc(-1 * var(--space-2)); padding-left: var(--space-2);
    padding-right: var(--space-2); color: var(--color-accent);
  }
  .app-side__foot { flex-direction: column; align-items: flex-start;
                    gap: var(--space-2); }
  .app-section__inner { max-width: none; padding: 0 var(--space-7); }
  .app-section { padding: 0 0 var(--space-9); }
}

/* =====================================================================
   Кабинет: обзор.
   Доли ассистентов идут строками, а не плитками: числа выстроены
   по одной вертикали, и столбец можно сравнить глазом. Ни одной
   усреднённой цифры здесь нет и быть не может.
   ===================================================================== */

/* Шапка раздела: заголовок, строка о замере и волосок под ними */
.app-head { padding-bottom: var(--space-5); border-bottom: var(--border);
            margin-bottom: var(--space-6); }
.app-head__row { display: flex; flex-wrap: wrap; gap: var(--space-4);
                 align-items: baseline; justify-content: space-between; }
.app-head h1 { margin: 0; }
.app-head__action { flex: none; }
.app-head__meta { margin-top: var(--space-3); max-width: 68ch;
                  font-size: var(--text-md); line-height: var(--leading-normal);
                  color: var(--color-ink-80); }

.app-h2 { font-size: var(--text-lg); line-height: var(--leading-snug);
          color: var(--color-ink);
          margin: var(--space-8) 0 var(--space-4);
          padding-top: var(--space-5); border-top: var(--border); }
/* Первый заголовок после шапки экрана линии не получает: под шапкой
   она уже есть, и две подряд читаются как ошибка вёрстки */
.app-head + .app-h2, .section-head + .app-h2,
.app-section__inner > h1 + .app-h2 { padding-top: 0; border-top: 0;
                                     margin-top: var(--space-6); }
.app-h3 { font-size: var(--text-base); font-weight: var(--weight-medium);
          margin: var(--space-6) 0 var(--space-3); }
.dim { color: var(--color-ink-faint); }
.note--tight { margin-top: var(--space-4); }

/* Пустое состояние: не поломка и не бодрая заглушка, а сказанный факт.
   Отбито волоском сверху — там же, где идут остальные границы кабинета. */
/* Пустое состояние — это ответ экрана, а не прореха в нём. Раньше оно
   было абзацем под чертой и читалось так, будто страница не догрузилась;
   теперь это карточка на приподнятом фоне: видно, что так и задумано */
.empty { max-width: 60ch; margin: var(--space-6) 0 0;
         padding: var(--space-6); border: var(--border);
         background: var(--color-surface-raised); }
.empty__title { font-size: var(--text-md); line-height: var(--leading-normal);
                color: var(--color-ink); margin: 0; }
.empty__text { font-size: var(--text-sm); color: var(--color-ink-muted);
               margin: var(--space-3) 0 0; }
.empty .button { margin-top: var(--space-4); }

/* --- Разрезы: вывод словами, полосы, качели ---------------------------- */

/* Вывод — это и есть ответ экрана. Он крупнее таблицы под ним намеренно:
   таблица нужна тем, кто захочет проверить, а вывод — всем. */
.verdict { max-width: 60ch; margin: var(--space-6) 0 0;
           font-size: var(--text-lg); line-height: var(--leading-normal); }

/* Имя не .band: так называется полоса на сайте, и правила бы столкнулись */
.tier { margin-top: var(--space-7); }
/* Заголовок ступени и счётчик вопросов в ней — одной строкой: число
   рядом со словом отвечает на «сколько именно» раньше, чем человек
   начнёт считать строки */
.tier__head { display: flex; flex-wrap: wrap; align-items: center;
              gap: var(--space-3); }
.tier .app-h2 { margin-bottom: var(--space-2); }
.tier__count { margin-left: var(--space-3); font-size: var(--text-sm);
               color: var(--color-ink-muted); }

/* Строка подготовки отчёта: правим формулировку и решаем, пойдёт ли
   находка на первую страницу. Выбранная помечена слева, как «вы»
   в таблице конкурентов — один язык на весь кабинет. */
.prep-row { padding: var(--space-4) 0; border-bottom: var(--border); }
.prep-row--chosen { box-shadow: inset 3px 0 0 var(--color-you);
                    padding-left: var(--space-4); }
.prep-row textarea { width: 100%; }
.prep-row__pick { font-size: var(--text-sm); color: var(--color-ink-muted); }
.prep-build { margin-top: var(--space-6); padding-top: var(--space-5);
              border-top: var(--border); }

/* Свойство и то, часто ли оно звучит: слово слева, слова о частоте
   справа. Цитата под словом, как в разрезе про описания. */
.trait { display: grid; grid-template-columns: minmax(0, 1fr) auto;
         gap: var(--space-4); align-items: baseline;
         padding: var(--space-4) 0; border-bottom: var(--border);
         font-size: var(--text-sm); }
.trait__word { color: var(--color-ink); }
.trait__word .cell-note { display: block; margin: var(--space-1) 0 0; }
.trait__often { font-size: var(--text-xs); }

/* Дорога страницы: дата слева, событие справа, волосок между ними.
   Имя не .steps: так называется сетка шагов на сайте, и правила бы
   столкнулись — как уже было с .band. */
.trail { list-style: none; margin: var(--space-4) 0 0; padding: 0; }
.trail__step { display: grid; grid-template-columns: 5.5rem minmax(0, 1fr);
               gap: var(--space-4); align-items: baseline;
               padding: var(--space-3) 0 var(--space-3) var(--space-4);
               border-left: 2px solid var(--color-line);
               font-size: var(--text-sm); }
/* Звено, ради которого разрез и существует, — страница в ответе */
.trail__step--cited, .trail__step--named { border-left-color: var(--color-ink); }
.trail__when { color: var(--color-ink-muted); font-size: var(--text-xs); }
.trail__what { color: var(--color-ink); }
.trail__what .cell-note { display: block; margin: var(--space-1) 0 0; }

/* Команда для консоли: её копируют целиком, и переносить её нельзя —
   зато можно прокрутить, не растягивая экран */
.code-line { margin: var(--space-4) 0 0; padding: var(--space-4);
             background: var(--color-surface-sunken);
             border-radius: var(--radius-sm); overflow-x: auto;
             font-size: var(--text-sm); }

.strength, .swings, .quotes, .reads { list-style: none;
                                     margin: var(--space-4) 0 0; padding: 0; }
/* Список страниц: адрес и под ним кто его читал — имён бывает четыре,
   и в узкой колонке они рассыпаются по одному слову в строку */
.read { display: grid; grid-template-columns: minmax(0, 1fr) auto;
        gap: var(--space-4); align-items: baseline;
        padding: var(--space-4) 0; border-bottom: var(--border);
        font-size: var(--text-sm); }
.read__page { color: var(--color-ink); }
.read__page .cell-note { display: block; margin: var(--space-1) 0 0; }
.read__count { color: var(--color-ink-muted); font-size: var(--text-xs); }
/* Цитата из ответа: волосок слева, как у сырых ответов — один язык на весь кабинет */
.quote { border-left: 2px solid var(--color-line); padding: 0 0 0 var(--space-5);
         margin-bottom: var(--space-5); max-width: 68ch; }
.quote__text { margin: 0; font-size: var(--text-base);
               line-height: var(--leading-normal); }
.quote__meta { margin: var(--space-2) 0 0; display: flex; gap: var(--space-3);
               align-items: baseline; font-size: var(--text-xs); }
.strength__row, .swing { display: grid; gap: var(--space-1);
                         /* Плотнее: на экран должно помещаться десять
                            вопросов, а не шесть */
                         padding: var(--space-3) 0; border-bottom: var(--border);
                         font-size: var(--text-sm); }
.strength__text, .swing__text { color: var(--color-ink); max-width: 60ch; }
/* Число — якорь строки: крупнее подписей, моноширинным, с табличными
   цифрами, чтобы столбец выравнивался по разряду */
.strength__share, .swing__was { font-family: var(--font-mono);
                                font-size: var(--text-md);
                                font-variant-numeric: tabular-nums;
                                color: var(--color-ink); }

@media (min-width: 48rem) {
  /* Тип вопроса умещается в строку: перенос «Setup and / features» делал
     строку вдвое выше ради двух слов */
  .strength__row { grid-template-columns: minmax(0, 1fr) 11rem auto 5rem;
                   align-items: center; column-gap: var(--space-5); }
  .strength__row .dim { white-space: nowrap; }
  .strength__share { text-align: right; }
  .swing { grid-template-columns: minmax(0, 1fr) 7rem auto;
           align-items: center; column-gap: var(--space-5); }
  .swing__was { text-align: right; }
}

/* --- Подразделы: название, вывод словами, ссылка ------------------------ */

.cuts { list-style: none; margin: 0; padding: 0; }
.cut { padding: var(--space-5) 0; border-bottom: var(--border); }
.cut:first-child { padding-top: var(--space-3); }
.cut__name { display: inline-block; font-family: var(--font-display);
             font-size: var(--text-md); font-weight: var(--weight-medium);
             color: var(--color-ink); }
.cut__name:hover { color: var(--color-accent); }
.cut__summary { margin: var(--space-2) 0 0; max-width: 68ch;
                font-size: var(--text-sm); color: var(--color-ink-muted); }
/* Тот же список, но под обзором проекта: отбит сверху, как и пакет */
.more { margin-top: var(--space-9); padding-top: var(--space-6);
        border-top: var(--border); }
.more .cuts { margin-top: var(--space-2); }

/* --- Доли ассистентов строками ----------------------------------------- */

.readings { list-style: none; margin: 0; padding: 0; }
.readings__key { display: none; }
.reading { display: grid; gap: var(--space-3);
           padding: var(--space-5) 0; border-bottom: var(--border); }

.reading__engine { font-family: var(--font-display); font-size: var(--text-md);
                   font-weight: var(--weight-medium); }
.reading__share { font-family: var(--font-mono); font-size: 2.25rem; line-height: 1;
                  font-variant-numeric: tabular-nums;
                  letter-spacing: var(--tracking-tight); }
.reading__share span { font-size: 1.125rem; color: var(--color-ink-faint);
                       margin-left: 0.1em; }
/* Ноль — это не «мало», это отсутствие. Сигнальный цвет только здесь. */
.reading--absent .reading__share { color: var(--color-signal); }
.reading__share--none { color: var(--color-ink-faint); }
.reading__note { margin-top: var(--space-2); font-size: var(--text-sm);
                 color: var(--color-ink-muted); }
.reading__leader { margin-top: var(--space-3); font-size: var(--text-xs);
                   color: var(--color-ink-faint); }
.reading__change { font-size: var(--text-sm); }
/* Ни цвета, ни плашки: стрелка и число говорят сами */
.reading__delta { font-weight: var(--weight-medium); }

/* Шкала доли: волосок от нуля до ста с четвертями. Имя не .measure —
   так называется блок на главной, и правила бы столкнулись. */
/* Шкала доли. Была волоском в три пикселя — на расстоянии вытянутой руки
   её просто не видно. Стала полосой с дорожкой и скруглением, и цвет
   у неё тот же, что у числа рядом: глаз ловит длину и цвет раньше,
   чем читает проценты. */
.gauge { position: relative; height: 0.5rem; margin-top: var(--space-4);
         max-width: 28rem; background: var(--color-surface-sunken);
         border-radius: var(--radius-full); overflow: hidden; }
/* Четверти остаются, но тише: это разметка, а не данные */
.gauge::after {
  content: ""; position: absolute; inset: 0;
  background-image: repeating-linear-gradient(
    to right, var(--color-line) 0 1px, transparent 1px 25%);
}
.gauge__fill { position: absolute; left: 0; top: 0; bottom: 0;
               width: var(--w); background: var(--color-accent);
               border-radius: var(--radius-full);
               /* Заливка поверх засечек, иначе они режут её на куски */
               z-index: 1; }
.gauge--ok .gauge__fill { background: var(--ok); }
.gauge--warn .gauge__fill { background: oklch(0.62 0.13 75); }
.gauge--bad .gauge__fill { background: var(--bad); }

/* Плашка состояния под числом */
.reading__state { margin: var(--space-2) 0 0; }

@media (min-width: 48rem) {
  .readings__key, .reading {
    display: grid;
    grid-template-columns: minmax(9rem, 1fr) minmax(0, 2.2fr) minmax(8rem, 1fr);
    gap: var(--space-6);
    align-items: start;
  }
  .readings__key { padding-bottom: var(--space-3); border-bottom: var(--border); }
  .reading { padding: var(--space-6) 0; align-items: start; }
}

/* --- График ------------------------------------------------------------ */
/* На узком экране график не сжимаем: подписи ушли бы в шесть пикселей.
   Вместо этого он прокручивается пальцем — так же, как таблицы. */
.chart { margin: 0; overflow-x: auto; min-width: 0; }
.chart svg { width: 100%; min-width: 40rem; height: auto; overflow: visible; }
.chart__grid { stroke: var(--color-line); stroke-width: 1; }
.chart__axis { fill: var(--color-ink-faint); font-family: var(--font-display);
               font-size: 12px; }
.chart__line { fill: none; stroke: var(--tint); stroke-width: 2;
               stroke-linecap: round; stroke-linejoin: round; }
.chart__dot { fill: var(--tint); }
.chart__leader { stroke: var(--tint); stroke-width: 1; }
/* Подпись у конца линии вместо легенды: не нужно сопоставлять цвета глазами */
.chart__label { fill: var(--tint); font-family: var(--font-display);
                font-size: 12px; font-weight: var(--weight-medium); }

/* --- Переключатель движка ---------------------------------------------- */
.engine-tabs { display: flex; flex-wrap: wrap; gap: var(--space-2);
               margin-bottom: var(--space-5); }
/* Выбранный движок отмечен волоском под названием, а не залитой пилюлей:
   пилюля читается как значение, а это переключатель разреза */
.engine-tabs { border-bottom: var(--border); gap: var(--space-5); }
.engine-tabs a {
  font-family: var(--font-display); font-size: var(--text-sm);
  padding: var(--space-2) 0 var(--space-3);
  color: var(--color-ink-muted);
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.engine-tabs a:hover { color: var(--color-ink); }
.engine-tabs a[aria-selected="true"] {
  color: var(--color-ink); font-weight: var(--weight-medium);
  border-bottom-color: var(--color-accent);
}

/* --- Полосы сравнения в кабинете ---------------------------------------
   Названия свои, не .bar: он уже занят одноимённым блоком на сайте,
   и часть чужих правил (капс в названиях) протекала сюда. */
.ranking { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }
.ranking__row { display: grid; grid-template-columns: minmax(6rem, 12rem) 1fr 3rem;
                gap: var(--space-4); align-items: center;
                font-family: var(--font-display); font-size: var(--text-sm); }
.ranking__name { color: var(--color-ink-muted); overflow: hidden;
                 text-overflow: ellipsis; white-space: nowrap; }
/* Та же шкала, что и на обзоре: волосок от нуля до ста, заливка — до значения */
.ranking__track { position: relative; height: 0.5rem; }
.ranking__track::before { content: ""; position: absolute; left: 0; right: 0;
                          bottom: 0; height: 1px; background: var(--color-line); }
.ranking__fill { position: absolute; left: 0; bottom: 0; height: 3px;
                 width: var(--w);
                 background: color-mix(in oklch, var(--color-ink-muted) 45%, transparent); }
.ranking__value { text-align: right; font-family: var(--font-mono);
                  font-variant-numeric: tabular-nums; font-size: var(--text-xs);
                  color: var(--color-ink-muted); }
/* «Это вы» — единственное место второго акцента */
.ranking__row--you .ranking__name,
.ranking__row--you .ranking__value { color: var(--color-you);
                                     font-weight: var(--weight-medium); }
.ranking__row--you .ranking__fill { background: var(--color-you); }
.ranking__row--you .ranking__fill { background: var(--color-you); }

/* --- Таблица данных ----------------------------------------------------- */
.data-table { width: 100%; border-collapse: collapse; min-width: 30rem;
              font-size: var(--text-sm); }
.data-table th { font-family: var(--font-display); font-size: var(--text-xs);
                 letter-spacing: var(--tracking-wide); text-transform: uppercase;
                 font-weight: var(--weight-medium);
                 color: var(--color-ink-muted); text-align: left;
                 padding: 0 var(--space-4) var(--space-3) 0;
                 border-bottom: 1px solid var(--color-line-strong); }
/* Строка плотнее: на экран должно помещаться вдвое больше вопросов,
   и глаз не должен идти через воздух от вопроса к его числу */
.data-table td { padding: var(--space-3) var(--space-4) var(--space-3) 0;
                 border-bottom: var(--border); vertical-align: top;
                 line-height: 1.4; }
/* Число — якорь строки: моноширинное, с табличными цифрами и заметно
   крупнее подписей рядом */
.data-table .num { font-family: var(--font-mono); font-size: var(--text-md);
                   font-variant-numeric: tabular-nums; text-align: right;
                   color: var(--color-ink);
                   padding-right: var(--space-5); }
.data-table th.num { text-align: right; }
/* Название компании в шапке столбца капителью не набирают: имя с разрядкой
   читается по буквам, а не целиком */
.data-table th.plain { text-transform: none; letter-spacing: normal;
                       font-size: var(--text-sm); color: var(--color-ink); }
/* Образец черты для подписи под таблицей: тот же волосок, что у строки */
.legend-mark {
  display: inline-block; width: 2px; height: 0.85em;
  margin-right: var(--space-2); vertical-align: -0.1em;
  background: var(--color-signal);
}

/* Строка под курсором подсвечивается: в таблице на двадцать строк глаз
   теряет, какую именно он читает */
.app-body .data-table tbody tr { transition: background-color var(--duration-fast) var(--ease); }
.app-body .data-table tbody tr:hover { background: var(--color-surface-sunken); }
/* Провал отмечен волоском у края строки, без заливки: заливка читается
   как статус-плашка, а строки и без того отсортированы по величине провала */
.data-table tr.is-gap td:first-child {
  box-shadow: inset 2px 0 0 var(--color-signal); padding-left: var(--space-3); }
.data-table tr.is-gap td:last-child { color: var(--color-ink);
                                      font-weight: var(--weight-medium); }

@media (max-width: 48rem) {
  .card__share { font-size: 2.25rem; }
  .ranking__row { grid-template-columns: minmax(4.5rem, 8rem) 1fr 2.75rem;
                  gap: var(--space-3); }
  .app-h2 { margin-top: var(--space-7); }

  /* Четыре ассистента на телефоне: столбцом, но плотно. Изменение
     переезжает в строку с названием — иначе карточка занимает пол-экрана,
     и до второго ассистента человек доходит прокруткой. Число не мельчает:
     ради него экран и открыли. */
  .reading { grid-template-columns: minmax(0, 1fr) auto;
             align-items: baseline; gap: var(--space-2) var(--space-3); }
  .reading__engine { grid-column: 1; }
  .reading__change { grid-column: 2; grid-row: 1; text-align: right; }
  .reading__value { grid-column: 1 / -1; }
  .reading__note { margin-top: var(--space-1); }
  .gauge { margin-top: var(--space-3); }
  .reading__leader { margin-top: var(--space-2); }
}

/* =====================================================================
   Кабинет: вопросы.
   ===================================================================== */

/* Фильтры — ссылками, а не выпадающими списками: состояние живёт в адресе,
   его можно переслать и вернуться к нему кнопкой «назад». */
.filters { display: flex; flex-wrap: wrap; gap: var(--space-6);
           margin-bottom: var(--space-5); }
.filters__set { display: flex; flex-wrap: wrap; align-items: baseline;
                gap: var(--space-3); font-family: var(--font-display);
                font-size: var(--text-sm); }

/* На узком экране ряд фильтров переносился на вторую и третью строку
   и съедал пол-экрана ещё до первой строки данных. Теперь он идёт
   одной строкой и листается вбок, а рядом стоит подпись «more»:
   без неё прокрутку не находят. */
@media (max-width: 56.25rem) {
  .app-body .filters { flex-direction: column; gap: var(--space-3);
                       align-items: stretch; }
  /* `width: 100%` обязателен: `align-items: stretch` не удерживает
     элемент, чьё содержимое шире колонки, и ряд растягивал всю страницу
     на 850 точек вместо того, чтобы прокручиваться внутри себя */
  .app-body .filters__row { display: flex; align-items: center; gap: var(--space-2);
                            width: 100%; min-width: 0; }
  /* `min-width: 0` обязателен и здесь, и на предках: без него содержимое
     ряда растягивает колонку сетки, и вбок едет вся страница, а не ряд.
     Так страница лидов становилась на 850 точек шире экрана */
  .app-body .app-section, .app-body .app-section__inner,
  .app-body .filters { min-width: 0; }
  .app-body .filters__set { flex-wrap: nowrap; min-width: 0;
                            padding-bottom: var(--space-1); }
  .app-body .filters__set > * { flex: none; }
  /* Внутри ссылки — слово и счётчик. Без зазора они слипались в «All12» */
  .app-body .filters__set a { display: inline-flex; align-items: baseline;
                              gap: 0.3rem; white-space: nowrap; }
  .app-body .engine-tabs { flex-wrap: nowrap; }
  .app-body .engine-tabs > * { flex: none; }
  .app-body .pills { flex-wrap: nowrap; }
  .app-body .pills > * { flex: none; }
  /* Полоса сотрудника листается так же. Заглушка — цветом её подложки,
     и «смотреть глазами клиента» не рвётся на три строки */
  .app-staff__nav { flex-wrap: nowrap; --swipe-bg: var(--color-surface-sunken); }
  .app-staff__side { flex: none; }
  .app-staff__side .button { white-space: nowrap; padding-left: 0; }
  /* Подпись «Staff» на телефоне убираем: место под неё дороже, чем
     польза, — и так ясно, что это не клиентское меню. Слово «client»
     из кнопки тоже: «View as» в полосе сотрудника читается однозначно */
  .app-staff__label { display: none; }
  .app-staff__long { display: none; }
}
.filters__label { font-size: var(--text-xs); letter-spacing: var(--tracking-wide);
                  text-transform: uppercase; color: var(--color-ink-faint); }
.filters__set a { color: var(--color-ink-muted); padding-bottom: 2px;
                  border-bottom: 2px solid transparent; }
.filters__set a:hover { color: var(--color-ink); }
.filters__set a[aria-current="true"] { color: var(--color-ink);
                                       border-bottom-color: var(--color-accent); }

/* Засечки по повторам. Пять меток подряд читаются быстрее любой цифры:
   видно не только сколько, но и насколько ответ устойчив. */
/* Отступ сверху обнуляем намеренно: выше по файлу тем же именем назван
   список на сайте, и его margin протекал сюда — строка становилась
   на двадцать четыре точки выше без единой причины */
.ticks { display: inline-flex; gap: 3px; margin: 0; }
/* Засечка — наш фирменный знак, и она должна читаться с одного взгляда:
   закрашенная акцентом, пустая с настоящим контуром, а не светлой
   заливкой, которая на экране сливается с фоном */
.tick { width: 9px; height: 20px;
        background: transparent;
        box-shadow: inset 0 0 0 1px var(--color-ink-faint); }
.tick--hit { background: var(--color-accent); box-shadow: none; }

/* Вопрос помещается в строку: колонка теперь во всю ширину экрана,
   и переносить его на второй ряд больше незачем */
.questions__text { max-width: 44rem; }
.data-table.questions { min-width: 44rem; }

@media (max-width: 48rem) {
  .filters { gap: var(--space-4); }
}

/* Выбор замера. Список, а не вкладки: замеров со временем становится много,
   и вкладками они переполнят строку уже на третьем месяце. */
.run-picker { margin-bottom: var(--space-5); display: grid; gap: var(--space-2); }
.run-picker label { display: flex; flex-wrap: wrap; align-items: center;
                    gap: var(--space-3); }
.run-picker select {
  font-family: var(--font-display); font-size: var(--text-sm);
  color: var(--color-ink); background: var(--color-surface);
  border: var(--border); padding: 0.35rem 0.6rem; cursor: pointer;
  /* min-width: 0 обязателен: без него список раздувается под самый длинный
     пункт и уносит вбок всю страницу на узком экране. Во всю ширину его тоже
     не тянем: это фильтр, а не поле ввода. */
  min-width: 0; max-width: 100%; flex: 0 1 32rem;
}
.run-picker select:focus-visible { outline: 2px solid var(--color-focus);
                                   outline-offset: 2px; }
/* Предупреждение о старом замере: сигнальным фоном, чтобы его не проскочили */
.run-picker__note {
  font-family: var(--font-display); font-size: var(--text-sm);
  background: var(--color-signal-wash);
  padding: var(--space-3) var(--space-4); justify-self: start;
}

/* =====================================================================
   Кабинет: конкуренты, источники, ответы, работы.
   ===================================================================== */

.data-table.competitors { min-width: 40rem; }
.data-table tr.is-you td { background: var(--color-you-wash); }
.data-table tr.is-you td:first-child { box-shadow: inset 3px 0 0 var(--color-you); }
/* Средняя позиция рядом с долей: мельче, чтобы не спорить с главным числом */
.cell-note { font-size: var(--text-xs); color: var(--color-ink-faint);
             margin-left: var(--space-2); }

/* Не плашка, а надпись. Обведённая плашка читается как значение и спорит
   с числами; состояние достаточно назвать словом. */
.tag { display: inline-block; font-family: var(--font-display);
       font-size: 0.66rem; line-height: 1.2; letter-spacing: 0.16em;
       text-transform: uppercase; font-weight: var(--weight-medium);
       color: var(--color-ink-muted); margin-left: var(--space-3); }
/* «Это вы» — единственная отметка цветом, и та волоском, а не заливкой */
.tag--you { color: var(--color-you); }
.tag--you::before { content: ""; display: inline-block; width: 3px; height: 0.7em;
                    background: var(--color-you); margin-right: 0.45em; }
/* Статусы работ и отчётов — те же плашки светофора, что у чисел:
   «сделано», «в работе» и «брошено» должны отличаться с одного взгляда,
   а не читаться по буквам. Заливка мягкая: это пометка, а не кнопка */
.app-body .tag--done, .app-body .tag--in_progress,
.app-body .tag--planned, .app-body .tag--dropped, .app-body .tag--absent {
  display: inline-flex; align-items: center; gap: 0.35rem;
  padding: 0.15rem 0.5rem; margin-left: var(--space-3);
  border-radius: var(--radius-full); border: 1px solid transparent;
  letter-spacing: 0.08em;
}
.app-body .tag--done { background: var(--ok-wash); border-color: var(--ok-line);
                       color: var(--ok); }
.app-body .tag--in_progress { background: var(--warn-wash);
                              border-color: var(--warn-line);
                              color: oklch(0.45 0.1 75); }
.app-body .tag--planned { background: var(--color-surface-sunken);
                          border-color: var(--color-line);
                          color: var(--color-ink-muted); }
.app-body .tag--dropped, .app-body .tag--absent {
  background: var(--color-surface-sunken); border-color: var(--color-line);
  color: var(--color-ink-faint); }

/* --- Сырые ответы ------------------------------------------------------ */
.answers { list-style: none; margin: 0; padding: 0; }
.answer { padding: var(--space-6) 0; border-bottom: var(--border); }
.answer__head { display: flex; flex-wrap: wrap; gap: var(--space-3);
                justify-content: space-between; align-items: baseline;
                margin-bottom: var(--space-5); padding-bottom: var(--space-4);
                border-bottom: var(--border); }
.answer__question { font-family: var(--font-display);
                    font-weight: var(--weight-medium); }
.answer__meta { font-family: var(--font-mono); font-size: var(--text-xs);
                font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Ответ — главное на экране, поэтому в полную силу. Что это цитата,
   говорит волосок слева, а не серый цвет. */
.answer__body { white-space: pre-wrap; color: var(--color-ink); max-width: 70ch;
                line-height: var(--leading-loose);
                border-left: 2px solid var(--color-line);
                padding-left: var(--space-5); }
.answer__full { margin-top: var(--space-3); white-space: pre-wrap; }
/* Треугольник раскрытия убираем двумя способами: разные браузеры рисуют
   его то маркером списка, то своим псевдоэлементом */
.answer summary { cursor: pointer; list-style: none; }
.answer summary::marker { content: ""; }
.answer summary::-webkit-details-marker { display: none; }
.answer__more { font-family: var(--font-display); font-size: var(--text-sm);
                color: var(--color-accent); white-space: nowrap; }
details[open] .answer__more { display: none; }
/* Раскрытый ответ прячет свою же выжимку: она повторяет первые строки.
   Правило обязано остаться внутри .answer — без области действия оно
   гасило заголовок у любого details на сайте, включая вопросы главной. */
.answer details[open] > summary { color: transparent; height: 0; overflow: hidden;
                                  display: block; }

/* Подсветка названий в сыром тексте: вас — волоском в цвет, прочих — серым */
mark.mark--you { background: none; color: var(--color-ink);
                 font-weight: var(--weight-medium);
                 border-bottom: 2px solid var(--color-you); }
mark.mark--rival { background: none; color: var(--color-ink);
                   border-bottom: 1px solid var(--color-line-strong); }

/* --- Работы ------------------------------------------------------------ */
.work-list { list-style: none; margin: 0; padding: 0; }
/* Дата слева отдельным столбцом: список работ читается как хроника,
   а не как стопка карточек */
.work-item { padding: var(--space-5) 0; border-bottom: var(--border);
             display: grid; gap: var(--space-2); }
.work-item--dropped { opacity: 0.66; }
.work-item__head { display: flex; flex-wrap: wrap; gap: var(--space-3);
                   align-items: baseline; justify-content: space-between; }
.work-item__head h2 { font-size: var(--text-md); margin: 0; }
.work-item__date { font-family: var(--font-mono); font-size: var(--text-xs);
                   font-variant-numeric: tabular-nums;
                   color: var(--color-ink-muted); margin: 0; }
.work-item p { max-width: 68ch; font-size: var(--text-sm);
               color: var(--color-ink-muted); }
.work-item p:has(.link) { color: var(--color-ink); }

/* На телефоне столбца с датой нет, и состояние встаёт под заголовком
   слева, а не улетает к правому краю */
@media (max-width: 48rem) {
  .work-item__head { justify-content: flex-start; }
  .work-item__head .tag { margin-left: 0; }
}

@media (min-width: 48rem) {
  .work-item { grid-template-columns: 9rem minmax(0, 1fr);
               column-gap: var(--space-6); }
  .work-item__date { grid-column: 1; grid-row: 1; }
  .work-item > :not(.work-item__date) { grid-column: 2; }
  /* У запланированной работы даты ещё нет, и столбец под неё оставлять
     нельзя: содержимое съезжает на четверть экрана вправо */
  .work-item:not(:has(.work-item__date)) { grid-template-columns: minmax(0, 1fr); }
  .work-item:not(:has(.work-item__date)) > * { grid-column: 1; }
}

/* Экран подтверждения платного прогона. */
.estimate { margin: var(--space-6) 0 0; max-width: 46rem; }
.estimate__figure { padding: var(--space-5); border: var(--border-strong);
                    border-radius: 0;
                    background: var(--color-surface-sunken); }
.estimate__label { margin: 0; font-family: var(--font-display);
                   font-size: var(--text-xs); letter-spacing: var(--tracking-wide);
                   text-transform: uppercase; color: var(--color-ink-muted); }
.estimate__cost { margin: var(--space-2) 0 0; font-family: var(--font-display);
                  font-size: var(--text-2xl); font-weight: var(--weight-bold);
                  letter-spacing: var(--tracking-tight); line-height: 1; }
.estimate__note { margin: var(--space-2) 0 0; font-family: var(--font-display);
                  font-size: var(--text-sm); color: var(--color-ink-muted); }
.estimate__how { margin: var(--space-4) 0 var(--space-5); font-size: var(--text-sm);
                 color: var(--color-ink-muted); max-width: 46rem; }
.estimate__budget { width: 100%; border-collapse: collapse;
                    font-size: var(--text-sm); }
.estimate__budget th { padding: 0 var(--space-3) var(--space-2) 0;
                       border-bottom: 1px solid var(--color-ink);
                       font-family: var(--font-display); font-size: var(--text-xs);
                       letter-spacing: var(--tracking-wide); text-transform: uppercase;
                       color: var(--color-ink-muted); text-align: left; }
.estimate__budget td { padding: var(--space-3) var(--space-3) var(--space-3) 0;
                       border-bottom: var(--border); }
.estimate__budget .num { text-align: right; font-variant-numeric: tabular-nums; }
.estimate__budget .zero { color: var(--color-signal); font-weight: var(--weight-bold); }

.estimate__go { display: flex; flex-wrap: wrap; gap: var(--space-4);
                align-items: center; margin: var(--space-6) 0 0; }
.estimate__wait { font-family: var(--font-display); font-size: var(--text-xs);
                  color: var(--color-ink-faint); max-width: 24rem; }
.estimate__blocked { margin: var(--space-6) 0 0; padding: var(--space-4) var(--space-5);
                     border-left: 3px solid var(--color-signal);
                     background: var(--color-signal-wash);
                     border-radius: 0;
                     font-size: var(--text-sm); max-width: 46rem; }

/* Кто ждёт доступа. Стоит наверху экрана заявок намеренно: это
   единственное здесь действие, которого человек ждёт прямо сейчас. */
.waiting-access { margin: var(--space-5) 0 var(--space-7); padding: var(--space-5);
                  border: var(--border-strong); border-radius: 0;
                  background: var(--color-accent-wash); }
.waiting-access .app-h2 { margin-top: 0; }
.access { list-style: none; margin: var(--space-4) 0 0; padding: 0;
          display: grid; gap: var(--space-4); }
.access__item { display: flex; flex-wrap: wrap; gap: var(--space-4);
                align-items: center; justify-content: space-between;
                padding-bottom: var(--space-4); border-bottom: var(--border); }
.access__item:last-child { border-bottom: none; padding-bottom: 0; }
.access__who { margin: 0; font-size: var(--text-base); }
.access__when { margin: var(--space-1) 0 0; font-family: var(--font-display);
                font-size: var(--text-xs); color: var(--color-ink-faint); }
.access__form { display: flex; flex-wrap: wrap; gap: var(--space-2);
                align-items: center; }
.access__form select, .access__form input { font-family: var(--font-display);
                                            font-size: var(--text-sm);
                                            padding: 0.4rem 0.6rem;
                                            border: var(--border-strong);
                                            border-radius: 0;
                                            background: var(--color-surface);
                                            color: var(--color-ink); }
.access__or { font-family: var(--font-display); font-size: var(--text-xs);
              color: var(--color-ink-faint); }

/* Заявки. */
.leads { list-style: none; margin: var(--space-5) 0 0; padding: 0;
         display: grid; gap: var(--space-4); }
.leads__item { border: var(--border); border-radius: 0;
               padding: var(--space-5); }
.leads__head { display: flex; flex-wrap: wrap; gap: var(--space-3);
               align-items: baseline; justify-content: space-between; }
.leads__who { margin: 0; font-size: var(--text-md);
              font-family: var(--font-display); font-weight: var(--weight-medium); }
.leads__meta { margin: var(--space-1) 0 var(--space-3);
               font-family: var(--font-display); font-size: var(--text-xs);
               color: var(--color-ink-faint); }
.leads__message { margin: 0 0 var(--space-4); padding-left: var(--space-4);
                  border-left: 2px solid var(--color-line-strong);
                  font-size: var(--text-base); color: var(--color-ink-muted);
                  max-width: 60ch; }
.leads__actions { display: flex; flex-wrap: wrap; gap: var(--space-4);
                  align-items: center; }
.leads__actions form { display: flex; gap: var(--space-2); align-items: center;
                       margin: 0; }
.leads__actions select, .leads__actions input {
  font-family: var(--font-display); font-size: var(--text-sm);
  padding: 0.4rem 0.6rem; border: var(--border-strong);
  border-radius: 0; background: var(--color-surface);
  color: var(--color-ink); }
.leads__note { margin-top: var(--space-4); max-width: 46rem; }
.leads__note label { display: block; font-family: var(--font-display);
                     font-size: var(--text-xs); color: var(--color-ink-faint);
                     margin-bottom: var(--space-2); }
.leads__note textarea { width: 100%; font-family: var(--font-text);
                        font-size: var(--text-sm); padding: var(--space-2) var(--space-3);
                        border: var(--border-strong); border-radius: 0;
                        resize: vertical; background: var(--color-surface);
                        color: var(--color-ink); }
.leads__note textarea:focus-visible, .leads__actions select:focus-visible,
.leads__actions input:focus-visible, .access__form select:focus-visible,
.access__form input:focus-visible { outline: 2px solid var(--color-focus);
                                    outline-offset: 1px; }

/* Состояния заявки. Цвет не единственный признак: рядом всегда слово. */
.tag--new { color: var(--color-accent); border-color: var(--color-accent); }
.tag--qualified { color: var(--color-you); border-color: var(--color-you); }
.tag--spam, .tag--rejected { color: var(--color-ink-faint); }

/* Форма экспресс-скана. */
.express__form { margin: var(--space-6) 0 var(--space-7); padding: var(--space-5);
                 border: var(--border); border-radius: 0;
                 background: var(--color-surface-sunken); max-width: 52rem; }
.express__row { display: flex; flex-wrap: wrap; gap: var(--space-4);
                margin-bottom: var(--space-4); }
.express__form label { flex: 1; min-width: 12rem; font-family: var(--font-display);
                       font-size: var(--text-xs); color: var(--color-ink-faint); }
.express__form input { display: block; width: 100%; margin-top: var(--space-2);
                       font-family: var(--font-text); font-size: var(--text-base);
                       padding: var(--space-2) var(--space-3);
                       border: var(--border-strong); border-radius: 0;
                       background: var(--color-surface); color: var(--color-ink); }
.express__form input:focus-visible { outline: 2px solid var(--color-focus);
                                     outline-offset: 1px; }
.express__note { margin-left: var(--space-3); font-family: var(--font-display);
                 font-size: var(--text-xs); color: var(--color-ink-faint); }

/* Счётчик очереди модерации в шапке. */
/* Счётчик — не тревога, а число: сигнальный красный оставлен провалам
   и нулям, очередь считается акцентом */
.badge { display: inline-block; min-width: 1.25rem; padding: 0 0.3rem;
         border-radius: var(--radius-full); background: var(--color-accent);
         color: var(--color-accent-ink); font-size: var(--text-xs);
         font-weight: var(--weight-medium); text-align: center;
         line-height: 1.25rem; }
/* Тот же значок на кнопке: число рядом со словами, а не над строкой */
.button .badge { margin-left: 0.45em; vertical-align: -0.1em; }

/* Очередь модерации: карточка решения. */
.review { list-style: none; margin: var(--space-4) 0 var(--space-7); padding: 0;
          display: grid; gap: var(--space-4); }
.review__item { border: var(--border); border-radius: 6px;
                padding: var(--space-5); max-width: 52rem;
                background: var(--color-surface); }
/* Форма «добавить своё»: поля идут столбиком во всю ширину. Раньше они
   стояли в строку, и подпись в поле обрезалась на половине слова */
form.review__item { display: grid; gap: var(--space-3); }
form.review__item > input[type="text"], form.review__item > textarea { width: 100%; }
.review__title { margin: 0; font-size: var(--text-md);
                 font-family: var(--font-display);
                 font-weight: var(--weight-medium); }
.review__where { margin: var(--space-1) 0 var(--space-3);
                 font-family: var(--font-display); font-size: var(--text-xs);
                 color: var(--color-ink-faint); }
.review__main { margin: 0; }
.review__main textarea { width: 100%; font-family: var(--font-text);
                         font-size: var(--text-base); padding: var(--space-3);
                         border: var(--border-strong);
                         border-radius: 0; resize: vertical;
                         background: var(--color-surface); color: var(--color-ink); }
.review__row { display: flex; flex-wrap: wrap; gap: var(--space-3);
               align-items: center; margin-top: var(--space-3); }
.review__row form { margin: 0; }
.review__row input[type="text"] { flex: 1; min-width: 16rem;
                                  font-family: var(--font-text);
                                  font-size: var(--text-sm);
                                  padding: var(--space-2) var(--space-3);
                                  border: var(--border-strong);
                                  border-radius: 0;
                                  background: var(--color-surface);
                                  color: var(--color-ink); }
.review__row select { max-width: 26rem; font-family: var(--font-display);
                      font-size: var(--text-sm); padding: 0.4rem 0.6rem;
                      border: var(--border-strong);
                      border-radius: 0;
                      background: var(--color-surface); color: var(--color-ink); }
.review__row input:focus-visible, .review__row select:focus-visible,
.review__main textarea:focus-visible { outline: 2px solid var(--color-focus);
                                       outline-offset: 1px; }

/* Список отслеживаемых компаний. */
.watchlist { margin-top: var(--space-8); padding-top: var(--space-6);
             border-top: var(--border); }
.watchlist__items { list-style: none; margin: var(--space-4) 0 0; padding: 0;
                    max-width: 34rem; }
.watchlist__item { display: flex; align-items: center; gap: var(--space-3);
                   justify-content: space-between; padding: var(--space-2) 0;
                   border-bottom: var(--border); }
.watchlist__name { font-size: var(--text-base); }
.watchlist__item form { margin: 0; }

.watchlist__add { margin-top: var(--space-5); max-width: 34rem; }
.watchlist__add label { display: block; font-family: var(--font-display);
                        font-size: var(--text-xs); color: var(--color-ink-faint);
                        margin-bottom: var(--space-2); }
.watchlist__row { display: flex; gap: var(--space-3); }
.watchlist__row input { flex: 1; font-family: var(--font-text);
                        font-size: var(--text-base); padding: var(--space-3);
                        border: var(--border-strong);
                        border-radius: 0;
                        background: var(--color-surface); color: var(--color-ink); }
.watchlist__row input:focus-visible { outline: 2px solid var(--color-focus);
                                      outline-offset: 1px; }

/* Вопросы, предложенные клиентом. */
.suggest { margin-top: var(--space-8); padding-top: var(--space-6);
           border-top: var(--border); }
.suggest__form { margin: var(--space-4) 0 0; max-width: 44rem; }
.suggest__form label { display: block; font-family: var(--font-display);
                       font-size: var(--text-xs); color: var(--color-ink-faint);
                       margin-bottom: var(--space-2); }
.suggest__form textarea { width: 100%; font-family: var(--font-text);
                          font-size: var(--text-base);
                          line-height: var(--leading-normal);
                          padding: var(--space-3); border: var(--border-strong);
                          border-radius: 0; resize: vertical;
                          background: var(--color-surface); color: var(--color-ink); }
.suggest__form textarea:focus-visible { outline: 2px solid var(--color-focus);
                                        outline-offset: 1px; }
.suggest__row { display: flex; align-items: center; gap: var(--space-3);
                margin-top: var(--space-3); }
.suggest__left { font-family: var(--font-display); font-size: var(--text-xs);
                 color: var(--color-ink-faint); }

.suggest__list { list-style: none; margin: var(--space-6) 0 0; padding: 0;
                 display: grid; gap: var(--space-3); max-width: 44rem; }
.suggest__item { padding: var(--space-4); border: var(--border);
                 border-radius: 0; }
.suggest__item--rejected { background: var(--color-surface-sunken); }
.suggest__head { display: flex; flex-wrap: wrap; gap: var(--space-3);
                 align-items: baseline; justify-content: space-between; }
.suggest__text { margin: 0; font-size: var(--text-base); }
.suggest__state { margin: var(--space-2) 0 0; font-family: var(--font-display);
                  font-size: var(--text-xs); color: var(--color-ink-muted); }

/* Сообщение о результате действия. Показывается один раз. */
.flash { font-family: var(--font-display); font-size: var(--text-sm);
         border-left: 3px solid var(--color-accent);
         background: var(--color-accent-wash);
         padding: var(--space-3) var(--space-4); margin: var(--space-5) 0 0;
         border-radius: 0; }
.flash--problem { border-left-color: var(--color-signal);
                  background: var(--color-signal-wash); }
/* Удачный исход: тот же вид, но спокойнее. Класс используется в кабинете
   и раньше не имел правил вовсе — сообщение выглядело как ошибка */
.flash--done { border-left-color: var(--color-accent); }

/* --- Настройки --------------------------------------------------------- */
.settings__form { display: grid; gap: var(--space-4); justify-items: start;
                  margin-top: var(--space-5); max-width: 32rem; }
.settings__form .field { width: 100%; }
.field__error { margin: var(--space-2) 0 0; font-size: var(--text-sm);
                color: var(--color-signal); }
/* Факты, которые нельзя поправить здесь: адрес, номер счёта, пакет.
   Строкой, а не полем — иначе человек будет пытаться их править */
.settings__facts { margin: var(--space-6) 0 0; display: grid; gap: var(--space-4); }
.settings__facts dt { font-family: var(--font-display); font-size: var(--text-xs);
                      letter-spacing: 0.08em; text-transform: uppercase;
                      color: var(--color-ink-faint); margin-bottom: var(--space-1); }
.settings__facts dd { margin: 0; font-size: var(--text-base);
                      line-height: var(--leading-normal); max-width: 68ch; }
.settings__letters { list-style: none; margin: var(--space-4) 0 0; padding: 0;
                     display: grid; gap: var(--space-4);
                     padding-left: var(--space-5);
                     border-left: 1px solid var(--color-line); }
.settings__letter-text { display: block; margin-top: var(--space-1);
                         font-size: var(--text-sm); color: var(--color-ink-muted); }

/* Отчёты. Тот же вид, что у работ: список карточек, дата, действие. */
.report-list { list-style: none; margin: var(--space-5) 0 0; padding: 0;
               display: grid; gap: var(--space-4); }
.report-item { padding: var(--space-5) 0; border-bottom: var(--border); }
.report-item__head { display: flex; flex-wrap: wrap; gap: var(--space-3);
                     align-items: baseline; justify-content: space-between; }
.report-item__head h2 { font-size: var(--text-md); margin: 0; }
.report-item__meta { font-family: var(--font-mono); font-size: var(--text-xs);
                     font-variant-numeric: tabular-nums;
                     color: var(--color-ink-muted);
                     margin: var(--space-2) 0 var(--space-4); }
.report-item__warn { color: var(--color-signal); }

/* Действия менеджера в разделе отчётов. Отделены линией сверху: это
   не часть того, что видит клиент. */
.report-build { display: flex; flex-wrap: wrap; gap: var(--space-3);
                align-items: center; margin: var(--space-5) 0 0;
                padding: var(--space-4); border: var(--border);
                background: var(--color-surface-sunken); }
.report-build label { font-family: var(--font-display); font-size: var(--text-sm);
                      color: var(--color-ink-muted); }
.report-build select { font-family: var(--font-display); font-size: var(--text-sm);
                       padding: 0.4rem 0.6rem; border: var(--border-strong);
                       background: var(--color-surface); color: var(--color-ink); }
.report-build__note { font-family: var(--font-display); font-size: var(--text-xs);
                      color: var(--color-ink-faint); }
/* Привязка ресурса: список сохраняется сразу при выборе, без кнопки —
   строк по числу проектов, и кнопка у каждой превратила бы таблицу в панель */
.link-form select { font-family: var(--font-display); font-size: var(--text-sm);
                    border: var(--border); background: var(--color-surface);
                    padding: 0.3rem 0.5rem; max-width: 18rem; }

.google__actions { display: flex; flex-wrap: wrap; gap: var(--space-4);
                   align-items: center; margin: var(--space-4) 0 var(--space-6); }
.google__sub { display: block; margin-top: var(--space-6); }

.report-build__force { display: inline-flex; align-items: center; gap: var(--space-2);
                       font-family: var(--font-display); font-size: var(--text-xs);
                       color: var(--color-ink-muted); cursor: pointer; }

/* Кому ушёл отчёт: по строке на отправку, тише основного текста */
.report-sent { list-style: none; margin: var(--space-2) 0 0; padding: 0;
               display: grid; gap: var(--space-1);
               font-family: var(--font-display); font-size: var(--text-xs);
               color: var(--color-ink-muted); }
.report-sent--unknown { max-width: 42rem; color: var(--color-ink-faint); }

.report-staff { margin-top: var(--space-5); padding-top: var(--space-4);
                border-top: var(--border); display: grid; gap: var(--space-4); }
.report-staff label { display: block; font-family: var(--font-display);
                      font-size: var(--text-xs); color: var(--color-ink-faint);
                      margin-bottom: var(--space-2); }
.report-staff textarea { width: 100%; font-family: var(--font-text);
                         font-size: var(--text-base); line-height: var(--leading-normal);
                         padding: var(--space-3); border: var(--border-strong);
                         border-radius: 0; resize: vertical;
                         background: var(--color-surface); color: var(--color-ink); }
.report-staff textarea:focus-visible { outline: 2px solid var(--color-focus);
                                       outline-offset: 1px; }
.report-staff button { margin-top: var(--space-3); }
.report-staff form:last-child { display: flex; flex-wrap: wrap;
                                gap: var(--space-3); align-items: center; }
.report-staff form:last-child button { margin-top: 0; }
.report-staff__note { font-family: var(--font-display); font-size: var(--text-xs);
                      color: var(--color-ink-faint); max-width: 46ch; }

/* =====================================================================
   Кабинет: экраны менеджера и просмотр от лица клиента.
   ===================================================================== */

/* Полоса режима просмотра. Единственное место, где сигнальный цвет
   занимает всю ширину: забыть, что смотришь чужой кабинет, нельзя. */
.impersonating { background: var(--color-signal); color: #fff; }
.impersonating__inner {
  max-width: var(--page-max); margin: 0 auto;
  padding: var(--space-3) var(--page-gutter);
  display: flex; flex-wrap: wrap; gap: var(--space-3);
  align-items: center; justify-content: space-between;
  font-family: var(--font-display); font-size: var(--text-sm);
}
.impersonating b { font-weight: var(--weight-medium); }
/* Кнопка выхода из режима просмотра. Привязана к своей полосе: без
   этого она перебивала одноимённый размер кнопки в шапке сайта — там
   вместо зелёной пилюли получался сигнальный текст на белом. */
.impersonating .button--small { padding: 0.3rem 0.6rem;
                 background: var(--color-surface); color: var(--color-signal);
                 border: none; }

.app-header__link { font-family: var(--font-display); font-size: var(--text-sm);
                    color: var(--color-ink-muted); }
.app-header__link:hover { color: var(--color-ink); }

.org { margin-bottom: var(--space-8); }
.org__head { display: flex; flex-wrap: wrap; align-items: baseline;
             gap: var(--space-3); margin-bottom: var(--space-4); }
.org__head h2 { font-size: var(--text-lg); margin: 0; }
.warn { color: var(--color-signal); }
.tag--hidden { color: var(--color-signal); border-color: var(--color-signal); }
.run-error { font-family: var(--font-mono); font-size: var(--text-xs);
             white-space: pre-wrap; word-break: break-word; }

@media (max-width: 48rem) {
  .app-header__link { display: none; }   /* на телефоне менеджер не работает */
}


/* =====================================================================
   Кабинет на телефоне: цели касания.
   Палец промахивается по всему, что ниже 44px, а в кабинете кликают
   те же элементы, что на десктопе, — только пальцем.
   ===================================================================== */

@media (max-width: 48rem) {
  .lockup,
  .button--quiet,
  .project-picker select,
  .run-picker select,
  .engine-tabs a,
  .filters__set a {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
  /* Ссылки-фильтры стоят в ряд: без переноса строки они слипаются */
  .filters__set { gap: var(--space-4); row-gap: 0; }

  /* Ссылки внутри текста трогать нельзя: растянуть их до 44px значит
     разорвать абзац. Это общепринятое исключение из правила. */

}

/* Номер счёта клиента в шапке кабинета. На телефоне остаётся, в отличие
   от почты: шесть знаков места не занимают, а искать номер по разделам
   человек не должен. */
.app-account { font-family: var(--font-display); font-size: var(--text-xs);
               color: var(--color-ink-muted); font-variant-numeric: tabular-nums; }



/* =====================================================================
   Подсказки к метрикам кабинета.
   Признак подсказки — пунктир под названием, а не иконка со знаком
   вопроса: иконка занимает место в каждой ячейке и спорит с числами.
   ===================================================================== */

.hint {
  /* Кнопка обязана выглядеть как та надпись, вместо которой стоит:
     заголовок колонки, подпись карточки, название раздела */
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  text-align: inherit;
  margin: 0;
  padding: 0;
  background: none;
  border: 0;
  border-bottom: var(--border-width) dotted var(--color-ink-faint);
  cursor: help;
}
.hint:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
  border-radius: 2px;
}

.hint-box {
  position: fixed;
  top: 0; left: 0;
  /* Выше обеих липких шапок кабинета — и боковой, и узкой на телефоне:
     они перекрыли бы окно подсказки */
  z-index: 80;
  max-width: min(22rem, calc(100vw - 2rem));
  padding: var(--space-4);
  border: var(--border-strong);
  border-radius: var(--radius-sm);
  /* Чуть светлее подложки — без теней и хвостиков */
  background: color-mix(in oklab, var(--color-surface) 25%, white);
  color: var(--color-ink);
  /* Обычный кегль: подсказка объясняет, а не прячет */
  font-size: var(--text-md);
  line-height: var(--leading-normal);
  opacity: 0;
  visibility: hidden;
  transition: opacity 170ms var(--ease), visibility 0s linear 170ms;
}
.hint-box.is-open {
  opacity: 1;
  visibility: visible;
  transition-delay: 0s;
}

@media (prefers-reduced-motion: reduce) {
  .hint-box { transition: none; }
}


/* =====================================================================
   Первый экран: окно чата во всю ширину полосы.

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

   Весь сценарий — один прогон на 2.65 секунды. Ничего не зациклено;
   курсор мигает конечное число раз. При «уменьшить движение» показано
   сразу конечное состояние.
   ===================================================================== */

.hero-chat {
  padding: var(--space-6) 0 var(--space-8);
  /* Блок вылезает за окно вправо; в узком окне браузера это не должно
     давать горизонтальную прокрутку */
  overflow-x: clip;
}

.chat {
  border: var(--border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
}

/* Шапка окна: слева чей это интерфейс вообще, справа — что спрашивали
   не один сервис. Обе подписи мелкие и тихие. */
.chat__bar {
  display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-5);
  align-items: baseline; justify-content: space-between;
  padding: var(--space-3) var(--space-5);
  border-bottom: var(--border);
}
.chat__label, .chat__where {
  margin: 0; max-width: none;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-ink-faint);
}
.chat__where { letter-spacing: 0.06em; }

.chat__body { display: grid; }
.chat__talk { padding: var(--space-5); }

/* Подпись, чья реплика. Мелко и слева — пузыри рисовать незачем. */
.chat__who {
  margin: 0 0 var(--space-2); max-width: none;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-ink-faint);
}
.chat__who--reply { margin-top: var(--space-5); }

/* --- Строка ввода ------------------------------------------------------ */

.chat__composer {
  padding: 0.625rem;
  border: var(--border);
  border-radius: var(--radius-md);
  background: var(--color-surface-sunken);
}
.chat__ask {
  display: flex; align-items: baseline; gap: 0.5ch;
  margin: 0; max-width: none;
  font-family: var(--font-mono);
  /* Кегль плавный и подобран замером канвой на каждой ширине: строка
     печатается без переноса и обязана поместиться целиком — обрезанный
     конец читается как поломка. На 390 это 247 пикселей при 264. */
  font-size: clamp(0.45rem, 2.2vw, 0.75rem);
  color: var(--color-ink);
}
.chat__typed {
  display: inline-block; overflow: hidden; white-space: nowrap;
  animation: chat-type 0.85s steps(var(--len), end) forwards;
}

/* --- Ответ -------------------------------------------------------------- */

.chat__reply {
  margin: 0; max-width: none;
  font-size: clamp(0.875rem, 4.2vw, 1.125rem);
  line-height: 1.5;
  letter-spacing: var(--tracking-tight);
  color: var(--color-ink);
}
.chat__line {
  display: block; overflow: hidden; white-space: nowrap;
  width: 0;
  animation: chat-type 0.26s steps(var(--len), end) forwards;
  animation-delay: calc(0.9s + var(--n) * 0.26s);
}
/* Названные компании подчёркнуты акцентом. Линия проявляется вместе
   со строкой — отдельная анимация для этого не нужна. */
.chat__named {
  font-weight: var(--weight-medium);
  box-shadow: inset 0 -0.12em 0 var(--color-accent);
}

/* --- Курсор ------------------------------------------------------------- */

.chat__caret {
  display: inline-block;
  width: 0.5rem; height: 1.05em;
  background: var(--color-accent);
  vertical-align: text-bottom;
}
/* Мигает конечное число раз и гаснет. Бесконечного мигания нет. */
.chat__caret--ask {
  animation: chat-blink 0.5s steps(2, jump-none) 2, chat-hide 1ms linear 0.9s forwards;
}
.chat__caret--end {
  opacity: 0;
  /* Гаснет ровно тогда, когда блок дораскрылся */
  animation: chat-show 1ms linear 2.2s forwards,
             chat-blink 0.45s steps(2, jump-none) 2.2s 1,
             chat-hide 1ms linear 2.65s forwards;
}

/* --- Блок: пятое место ---------------------------------------------------- */

.chat__block {
  padding: var(--space-5);
  background: var(--color-accent);
  color: var(--color-accent-ink);
  border-radius: var(--radius-md);
  /* Раскрывается из точки наружу — вправо, влево, вверх и вниз сразу,
     а не выезжает откуда-то сбоку */
  clip-path: inset(50% 100% 50% 0);
  animation: chat-unfold 0.45s var(--ease) 2.2s forwards;
}
.chat__eyebrow { color: var(--color-ink-inverse-muted); }
/* Заголовок называет услугу словами, которыми её ищут, и набран как
   строка над лозунгом, а не как второй лозунг: два крупных текста подряд
   спорят друг с другом, и не читается ни один */
.chat__h1 { margin: var(--space-3) 0 0;
            font-size: var(--text-lg); font-weight: var(--weight-medium);
            line-height: var(--leading-snug); letter-spacing: -0.01em; }
.chat__slogan { margin-top: var(--space-2);
                font-size: clamp(1.5rem, 0.9rem + 2.4vw, 2.25rem); }
.chat__sub { margin-top: var(--space-4); max-width: 40ch;
             font-size: var(--text-md); line-height: var(--leading-normal);
             color: var(--color-ink-inverse-muted); }
.chat__actions { margin-top: var(--space-5); display: flex; flex-wrap: wrap;
                 align-items: center; gap: var(--space-4); }
.chat__aside { margin-top: var(--space-4); font-size: var(--text-sm);
               color: var(--color-ink-inverse-muted); }

/* Кнопки на акцентной подложке */
.button--light { background: var(--color-surface); color: var(--color-ink); }
.button--light:hover { background: var(--color-surface-sunken); }
.button--plain { background: none; color: var(--color-accent-ink);
                 padding-left: 0; padding-right: 0; }
.button--plain:hover { color: var(--color-ink-inverse-muted); }

/* --- Движение ----------------------------------------------------------- */

@keyframes chat-type { from { width: 0; } to { width: 100%; } }
@keyframes chat-blink { 50% { opacity: 0; } }
/* Гаснет и схлопывается: иначе оставляет отступ там, где стоял */
@keyframes chat-hide { to { opacity: 0; width: 0; } }
@keyframes chat-show { to { opacity: 1; } }
@keyframes chat-unfold { to { clip-path: inset(0 0 0 0); } }

@media (prefers-reduced-motion: reduce) {
  .chat__typed, .chat__line { width: auto; animation: none; }
  .chat__caret { display: none; animation: none; }
  .chat__block { clip-path: none; animation: none; }
}

/* --- Широкий экран -------------------------------------------------------- */

@media (min-width: 56rem) {
  /* Снизу отступ меньше обычного: блок и так выступает за нижний край
     окна и занимает эту высоту сам */
  .hero-chat { padding: var(--space-7) 0 var(--space-7); }

  .chat__bar { padding: var(--space-4) var(--space-6); }
  /* Разговор слева, место клиента справа. Правая колонка чуть уже:
     разговор — улика, и он главный. Высота задана, чтобы окно занимало
     экран, а не висело полоской в его середине. */
  .chat__body { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
                align-items: stretch; min-height: 27rem; }
  .chat__talk { padding: var(--space-6); display: flex; flex-direction: column; }
  .chat__composer { padding: var(--space-4); }
  /* В две колонки левая вдвое уже, и кегль вопроса считается от ширины
     окна иначе: на 900 это 283 пикселя при 301 доступном */
  .chat__ask { font-size: clamp(0.6rem, 1.2vw, 0.8125rem); }
  .chat__reply { font-size: clamp(1.125rem, 1.9vw, 1.75rem); line-height: 1.4; }
  /* Ответ прижат книзу колонки: курсор встаёт вровень с серединой блока,
     откуда тот и раскрывается */
  .chat__who--reply { margin-top: auto; }

  .chat__block {
    /* Выходит за правый и нижний край окна — заметно, а не на полпальца:
       наш ответ в их окно не помещается, и это видно сразу.
       Сверху отступ больше: правый край рамки должен остаться на виду,
       иначе окно читается обрезанным, а не перекрытым. */
    margin: 4.5rem calc(0px - var(--space-8)) -3rem 0;
    padding: var(--space-7) var(--space-7) var(--space-7) var(--space-6);
    border-radius: var(--radius-lg);
  }
  .chat__slogan { font-size: clamp(1.75rem, 2.6vw, 2.5rem); }
  .chat__sub { max-width: 38ch; }
}


/* =====================================================================
   Блок «Invisible loss». Главная мысль страницы: измеренное — малая
   часть спроса. Полотно во всю ширину окна, боковых полей нет, текст
   лежит поверх композиции.
   ===================================================================== */

.loss { margin-top: var(--space-8); }

.loss__stage {
  position: relative;
  /* Во всю ширину окна: поля здесь сломали бы мысль — круг обязан
     упираться в края и не помещаться в кадр */
  width: 100%;
  overflow: hidden;
}

/* Измерительная шкала на заднем плане. Не решётка: решётка спорит
   с содержимым, а шкала перекликается со смыслом продукта — здесь
   всё измеряют. Контраст такой, что если прищуриться, она исчезает,
   а круги и текст остаются. */
.loss__scale {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  pointer-events: none;
}
.loss__cross { stroke: var(--color-ink); stroke-opacity: 0.1; stroke-width: 1; }
/* Линия чуть заметнее крестиков, но всё равно на грани */
.loss__major { stroke: var(--color-ink); stroke-opacity: 0.055; stroke-width: 1; }
.loss__tick { stroke: var(--color-ink); stroke-opacity: 0.14; stroke-width: 1; }

.loss__field { position: relative; z-index: 1; display: block; width: 100%;
               height: auto; }
.loss__field--wide { display: none; }

/* Подпись к фигурам на телефоне: кружок-образец и строка обычным текстом.
   Прежде здесь были выноски прямо на чертеже — на этой ширине подпись
   в одиннадцать пикселей шла во всю ширину кадра, а её линия пересекала
   фигуру. Подпись под композицией читается и ничего не загораживает. */
.loss__key {
  position: relative; z-index: 2;
  margin: 0; padding: var(--space-5) var(--page-gutter) var(--space-6);
  list-style: none;
  display: grid; gap: var(--space-3);
  font-size: var(--text-sm); color: var(--color-ink-muted);
}
.loss__key li { display: flex; align-items: center; gap: var(--space-3); }
.loss__key-mark { flex: none; width: 1rem; height: 1rem; border-radius: var(--radius-full); }
/* Образцы повторяют сами фигуры: у большой пунктирный контур и заливка
   чуть плотнее фона, у малой сплошная акцентная заливка */
.loss__key-mark--all { background: var(--color-surface-sunken);
                       border: 1px dashed var(--color-line-strong); }
.loss__key-mark--seen { background: var(--color-accent); }
.loss__field--wide .loss__callout text { font-size: 19px; }

/* Большой круг: заливка едва отличается от фона, контур пунктирный */
.loss__all {
  fill: var(--color-surface-sunken);
  /* Полупрозрачная: сетка должна просвечивать и внутри круга,
     она фон всего блока, а не только его краёв */
  fill-opacity: 0.62;
  stroke: var(--color-line-strong);
  stroke-width: 2;
  stroke-dasharray: 9 11;
}

/* Маленький: сплошная заливка акцентом, чёткая граница */
.loss__seen { fill: var(--color-accent); }

.loss__dot { fill: var(--color-ink); opacity: 0.32; }
/* Те, кого не видит вообще никто, — ещё бледнее */
.loss__dot--outside { opacity: 0.16; }
/* Внутри акцентного круга точки светлее заливки, иначе их там нет */
.loss__dot--seen { fill: var(--chart-3); opacity: 0.9; }

/* Выноски в духе чертежа: волосок и точка на фигуре */
.loss__callout path { stroke: var(--color-ink-faint); stroke-width: 1; }
.loss__callout circle { fill: var(--color-ink-faint); }
.loss__callout text {
  font-family: var(--font-mono);
  /* Кегль в единицах системы координат. У узкой раскладки она мельче,
     и тот же размер выносил бы подпись за край кадра. */
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  fill: var(--color-ink-faint);
}

/* --- Текст поверх композиции ---------------------------------------- */

.loss__words {
  position: relative;
  /* Поверх полотна: иначе заливка круга ложится на буквы и съедает их */
  z-index: 2;
  max-width: var(--page-max);
  margin: 0 auto;
  padding: var(--space-8) var(--page-gutter) var(--space-7);
}
.loss__title {
  margin-top: var(--space-5);
  /* Крупнее остальных заголовков страницы: этот блок главный */
  font-size: clamp(2.25rem, 1.1rem + 5vw, 4rem);
  max-width: 18ch;
}
.loss__accent { color: var(--color-accent); }
.loss__sub {
  margin-top: var(--space-6);
  max-width: 54ch;
  /* Нормальный кегль: абзац уточняет, а не прячется */
  font-size: var(--text-lg);
  line-height: var(--leading-normal);
  color: var(--color-ink-muted);
}

/* --- Подпись под полотном ---------------------------------------------- */

.loss__foot {
  max-width: none;
  margin: 0;
  padding: var(--space-5) var(--page-gutter);
  border-top: var(--border);
  font-size: var(--text-md);
  color: var(--color-ink-muted);
}

/* --- Движение ----------------------------------------------------------- */
/* Точки разлетаются из маленького круга наружу: из немногих измеренных
   вырастает масса неизмеренных. Полтора прогона нет — один, и без
   повтора. Класс `is-armed` ставит скрипт; без него точки просто стоят
   на местах, и страница не зависит от JavaScript. */

.loss.is-armed .loss__dot { opacity: 0; }
.loss.is-armed.is-seen .loss__dot {
  animation: loss-scatter 0.62s var(--ease) forwards;
  animation-delay: calc(var(--i) * 0.006s);
}
.loss.is-armed.is-seen .loss__dot--outside { animation-name: loss-scatter-faint; }
.loss.is-armed.is-seen .loss__dot--seen { animation-name: loss-scatter-seen; }

@keyframes loss-scatter {
  from { opacity: 0; transform: translate(var(--dx), var(--dy)); }
  to { opacity: 0.32; transform: none; }
}
@keyframes loss-scatter-faint {
  from { opacity: 0; transform: translate(var(--dx), var(--dy)); }
  to { opacity: 0.16; transform: none; }
}
@keyframes loss-scatter-seen {
  from { opacity: 0; transform: translate(var(--dx), var(--dy)); }
  to { opacity: 0.9; transform: none; }
}

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

   Величины считаны в единицах системы координат полотна, а не в
   пикселях экрана: у широкой раскладки единица примерно равна пикселю,
   и 22 единицы — это те самые «чуть-чуть», которые замечаешь боковым
   зрением, но не ловишь глазом. */

.loss__all,
.loss__layer {
  transform: translate(calc(var(--px, 0) * var(--depth)),
                       calc(var(--py, 0) * var(--depth)));
  transition: transform var(--lag) var(--ease);
}
.loss__all { --depth: 5px; --lag: 0.9s; }
.loss__layer--crowd { --depth: 12px; --lag: 0.6s; }
.loss__layer--seen {
  --depth: 22px; --lag: 0.36s;
  /* Начало координат в середине группы, иначе она при наведении
     разъезжается от угла кадра, а не растёт от себя */
  transform-box: fill-box;
  transform-origin: center;
}

/* Наведение на измеренный круг. Он единственный кликабельно выглядящий
   объект в композиции, и отзываться должен он — вместе со своей
   выноской, чтобы связь между пятном и подписью была видна. */
.loss__layer--seen:hover {
  transform: translate(calc(var(--px, 0) * var(--depth)),
                       calc(var(--py, 0) * var(--depth))) scale(1.05);
}
.loss__seen, .loss__dot--seen, .loss__callout * {
  transition: fill 0.25s var(--ease), stroke 0.25s var(--ease),
              opacity 0.25s var(--ease), transform 0.25s var(--ease);
}
.loss__layer--seen:hover .loss__seen {
  fill: color-mix(in oklab, var(--color-accent) 86%, var(--color-ink));
}
/* Со звёздочкой не от хорошей жизни: разлёт точек оставлен в
   `forwards`, а конечный кадр анимации сильнее обычного объявления.
   Значение здесь то же самое, каким точка и так стоит, — только ярче. */
.loss__layer--seen:hover .loss__dot--seen { opacity: 1 !important; }

/* Выноска загорается вместе с фигурой — в обе стороны */
.loss__layer--seen:hover ~ .loss__callout--seen path,
.loss__callout:hover path {
  stroke: var(--color-ink);
}
.loss__layer--seen:hover ~ .loss__callout--seen text,
.loss__callout:hover text {
  fill: var(--color-ink);
}
.loss__layer--seen:hover ~ .loss__callout--seen .loss__anchor,
.loss__callout:hover .loss__anchor {
  fill: var(--color-ink);
  transform: scale(1.7);
  transform-box: fill-box;
  transform-origin: center;
}
.loss__field:has(.loss__callout--seen:hover) .loss__seen {
  fill: color-mix(in oklab, var(--color-accent) 86%, var(--color-ink));
}
.loss__field:has(.loss__callout--seen:hover) .loss__dot--seen { opacity: 1 !important; }

/* Волосок и подпись в 11px мышью не поймать. Прозрачная широкая линия
   поверх выноски делает её целиком нормальной целью для курсора. */
.loss__grab {
  stroke: transparent;
  stroke-width: 26;
  fill: none;
  pointer-events: stroke;
}

@media (prefers-reduced-motion: reduce) {
  /* С `is-seen` в селекторе: без него правило ниже по специфичности
     и движение остаётся включённым */
  .loss.is-armed .loss__dot,
  .loss.is-armed.is-seen .loss__dot { opacity: 0.32; animation: none;
                                      transform: none; }
  .loss.is-armed .loss__dot--outside,
  .loss.is-armed.is-seen .loss__dot--outside { opacity: 0.16; }
  .loss.is-armed .loss__dot--seen,
  .loss.is-armed.is-seen .loss__dot--seen { opacity: 0.9; }

  /* Ни смещения за курсором, ни роста при наведении: остаётся только
     смена цвета — она не движение */
  .loss__all,
  .loss__layer,
  .loss__layer--seen:hover { transform: none; transition: none; }
  .loss__seen, .loss__dot--seen, .loss__callout * { transition: none; }
  .loss__layer--seen:hover ~ .loss__callout--seen .loss__anchor,
  .loss__callout:hover .loss__anchor { transform: none; }
}

@media (min-width: 48rem) {
  .loss { margin-top: var(--space-9); }
  .loss__field--wide { display: block; }
  .loss__field--narrow { display: none; }
  /* На широком экране подписи говорят выноски на самом чертеже */
  .loss__key { display: none; }

  /* Текст ложится в пустой верх круга, слева, поверх полотна */
  .loss__words {
    position: absolute; inset: 0;
    display: flex; flex-direction: column; justify-content: center;
    padding-top: 0; padding-bottom: 0;
    pointer-events: none;
  }
  .loss__words > * { pointer-events: auto; }
  .loss__sub { font-size: 1.25rem; max-width: 46ch; }
  .loss__foot { font-size: var(--text-lg); padding: var(--space-6) var(--page-gutter); }
}


/* =====================================================================
   Блок «Why now». Слева выдача поиска, где заняты все десять мест,
   справа ответ ассистента, где занято три из пяти. Подложка блока
   разделена на два поля: слева тон плотнее, справа светлее почти
   до белого. Граница размыта и проходит по центру — текст лежит
   поперёк неё и ни к одной половине не относится.
   ===================================================================== */

.why {
  position: relative;
  /* Поля нет намеренно: тональное поле начинается сразу под предыдущим
     блоком, и воздух даёт паддинг внутри. С полем сверху между блоками
     набегало 320 пикселей пустоты — блок висел в воздухе. */
  margin-top: 0;
  padding-top: var(--space-8);
  /* На телефоне низ держит сам блок: перечней, которые давали его
     раньше, здесь нет. На широком экране паддинг обнуляется — там
     низ снова за перечнями */
  padding-bottom: var(--space-8);
}

/* --- Подложка ----------------------------------------------------------- */

.why__tones { position: absolute; inset: 0; overflow: hidden; }
.why__tone {
  position: absolute;
  /* Размытие, а не градиент: поля мягко перетекают друг в друга по
     границе. Каждое поле выходит за края блока настолько, чтобы
     размытие не тронуло внешние края — размывается только шов. */
  filter: blur(3.5rem);
}
/* Поиск: нейтральное поле плотнее страницы */
.why__tone--dense {
  inset: -6rem -6rem 50% -6rem;
  background: oklch(0.928 0.006 78);
}
/* Ассистенты: то же по светлоте, но уведено в акцент. Настолько слабо,
   что цвет не называется глазом, — но половины перестают быть одним
   полем, и та, что про нас, читается как наша. */
.why__tone--open {
  inset: 50% -6rem -6rem -6rem;
  background: oklch(0.982 0.014 152);
}

.why__inner { position: relative; }

/* --- Текст -------------------------------------------------------------- */

.why__title {
  margin-top: var(--space-5);
  font-size: clamp(2.25rem, 1.1rem + 5vw, 4rem);
  max-width: 26ch;
}
.why__accent { color: var(--color-accent); }

.why__text { margin-top: var(--space-7); }
.why__text p {
  max-width: 54ch;
  font-size: var(--text-lg);
  line-height: var(--leading-normal);
  color: var(--color-ink-muted);
}
.why__text p + p { margin-top: var(--space-5); }
.why__quiet { color: var(--color-ink-faint); }

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

/* На телефоне перечней нет. Они работают сравнением: десять занятых
   строк рядом с пятью просторными видны одним взглядом. В одну колонку
   они идут друг за другом, сравнивать нечего — остаётся две ведомости
   подряд на пол-экрана каждая. Мысль эти абзацы уже сказали словами. */
.why__lists { display: none; }

@media (min-width: 48rem) {
  .why__lists {
    margin-top: var(--space-8);
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-8);
    /* Низ блока: тональное поле обязано закончиться не впритык к подписи */
    padding-bottom: var(--space-9);
  }
}
/* Ширина перечня — по строке, а не по половине блока: линейка во всю
   половину читалась бы прочерком, а не строкой бланка */
.why__list { max-width: 22rem; }

.why__head {
  padding-bottom: var(--space-3);
  border-bottom: var(--border-width) solid var(--color-line-strong);
}
.why__head-title {
  margin: 0;
  font-size: var(--text-xl);
  line-height: var(--leading-snug);
}
/* Факт о сроке стоит при своём перечне, а не отдельной строкой внизу
   блока: двадцать лет слева, два года справа — разница видна сразу,
   потому что цифры стоят рядом */
.why__head-fact {
  margin: var(--space-2) 0 0;
  font-size: var(--text-md);
  color: var(--color-ink-muted);
}
/* Слабый акцент на стороне ассистентов: черта под заголовком и срок */
.why__list--open .why__head { border-bottom-color: var(--color-accent); }
.why__list--open .why__head-fact { color: var(--color-accent); }

.why__rows {
  margin: 0;
  padding: 0;
  list-style: none;
}
.why__rows li {
  display: grid;
  grid-template-columns: 1.75rem 1fr;
  gap: var(--space-4);
  align-items: baseline;
  border-bottom: var(--border);
  font-size: var(--text-md);
}
/* Слева тесно: строки идут подряд, интерлиньяж плотный */
.why__rows--dense li { padding: 0.34em 0; line-height: 1.35; }
/* Справа просторно: та же строка дышит втрое свободнее */
.why__rows--open li { padding: 1.05em 0; line-height: 1.5; }
/* Пустая строка обязана занимать столько же, сколько занятая */
.why__rows--open .why__name { display: block; min-height: 1.5em; }

.why__n {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  /* По правому краю: десятка встаёт под единицей, как в ведомости */
  text-align: right;
  color: var(--color-ink-faint);
}
.why__name { color: var(--color-ink); }

/* Тот же знак, что на первом экране: так помечена компания, которую
   ассистент назвал вслух */
.why__named {
  font-weight: var(--weight-medium);
  box-shadow: inset 0 -0.12em 0 var(--color-accent);
}
.why__ink { display: inline-block; }

.why__note {
  margin: var(--space-5) 0 0;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-ink-faint);
}

/* --- Движение ------------------------------------------------------------ */
/* Четвёртая строка ответа заполняется названием: место занимают прямо
   сейчас. Один прогон, медленно, без повтора. Классы ставит тот же
   скрипт, что и в предыдущих блоках; без него название просто стоит. */

.why.is-armed .why__ink { clip-path: inset(0 100% 0 0); }
.why.is-armed.is-seen .why__ink {
  animation: why-write 2.4s var(--ease) 0.9s forwards;
}
@keyframes why-write { to { clip-path: inset(0); } }

@media (prefers-reduced-motion: reduce) {
  /* С `is-seen` в селекторе — иначе правило слабее того, что выше */
  .why.is-armed .why__ink,
  .why.is-armed.is-seen .why__ink { clip-path: inset(0); animation: none; }
}

@media (min-width: 48rem) {
  .why { padding-top: var(--space-9); padding-bottom: 0; }

  /* Абзацы в две колонки: одной длинной полосой текст не тянется */
  .why__text {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-5) var(--space-8);
  }
  .why__text p + p { margin-top: 0; }
  .why__quiet { grid-column: 1; }

  /* Деление подложки становится вертикальным: слева тесно, справа
     свободно, и текст лежит поперёк шва */
  .why__tone--dense { inset: -6rem 50% -6rem -6rem; }
  .why__tone--open { inset: -6rem -6rem -6rem 50%; }

}


/* =====================================================================
   Блок «What we do». Пауза между плотными соседями: сплошная заливка
   осветлённым акцентом и три куска текста по диагонали. Заливка светлая
   намеренно — тёмная плашка здесь читалась бы провалом, а не паузой,
   поэтому текст на ней остаётся тёмным.
   ===================================================================== */

.doing {
  /* Поля нет: блок примыкает к предыдущему вплотную. Полоса фона между
     двумя залитыми блоками читалась пустотой, а не паузой — пауза
     здесь сама заливка, и воздух ей даёт внутренний паддинг. */
  margin-top: 0;
  /* Акцент, осветлённый до подложки: цвет узнаётся, но не давит */
  background: oklch(0.93 0.032 152);
  padding: var(--space-8) 0;
}

.doing__inner { display: grid; gap: var(--space-7); }

.doing__title {
  margin-top: var(--space-5);
  font-size: clamp(1.75rem, 0.9rem + 3vw, 2.6rem);
  line-height: var(--leading-tight);
}
.doing__accent { color: var(--color-accent); }

.doing__body {
  margin: 0;
  /* Не длиннее шестидесяти знаков: колонка узкая намеренно */
  max-width: 58ch;
  font-size: var(--text-lg);
  line-height: var(--leading-normal);
  color: var(--color-ink-muted);
}

.doing__close {
  /* На телефоне отступ сверху добирается полем: вывод обязан стоять
     отдельно от абзаца, а не идти следующим шагом списка */
  margin: var(--space-6) 0 0;
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 0.85rem + 1.5vw, 1.75rem);
  line-height: var(--leading-snug);
  letter-spacing: -0.01em;
  color: var(--color-ink);
}

@media (min-width: 48rem) {
  .doing { padding: var(--space-9) 0 var(--space-8); }

  /* Три части по диагонали: заголовок слева сверху, абзац правее и ниже,
     вывод внизу ближе к левому краю. Воздух между ними задают поля,
     а не пустые ячейки. */
  .doing__inner { grid-template-columns: repeat(12, 1fr); gap: 0; }
  .doing__head { grid-column: 1 / 11; }
  /* Абзац подтянут к заголовку, а весь воздух отдан выводу: пустота
     работает там, где по ней идёт глаз, а не слева от абзаца */
  .doing__body { grid-column: 7 / 13; margin-top: var(--space-6); }
  .doing__close { grid-column: 1 / 9; margin-top: var(--space-9); }
}


/* =====================================================================
   Блок «Your dashboard». Снимки настоящего кабинета: прямоугольник
   с волосяной границей, без рамок ноутбуков, теней и бликов. Крупные
   кадры подрезаны сверху и снизу — кусок продукта, а не картинка.

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

.shots { margin-top: var(--space-8); }

.shots__title {
  margin-top: var(--space-5);
  font-size: clamp(2rem, 1.1rem + 3.4vw, 3rem);
  max-width: 24ch;
}
.shots__accent { color: var(--color-accent); }
.shots__text {
  margin: var(--space-6) 0 0;
  max-width: 58ch;
  font-size: var(--text-lg);
  line-height: var(--leading-normal);
  color: var(--color-ink-muted);
}

/* --- Галерея ------------------------------------------------------------- */

.shots__gallery {
  margin-top: var(--space-8);
  display: grid;
  /* Воздух между кадрами обязателен: увеличенный кадр выходит за свои
     границы, и без просвета соседям было бы тесно */
  gap: var(--space-8);
}
.shots__row { display: grid; gap: var(--space-6); }

.shots__shot { position: relative; margin: 0; }

.shots__frame {
  display: block;
  overflow: hidden;
  border: var(--border);
  border-radius: var(--radius);
  background: var(--color-surface-sunken);
  /* Увеличение идёт от середины самого кадра */
  transform-origin: center;
}
.shots__frame img { display: block; width: 100%; height: auto; }

/* Крупные кадры: срез сверху и снизу вместо полного снимка. На телефоне
   среза нет — там кадр и так в ладонь шириной, резать нечего. */
@media (min-width: 48rem) {
  .shots__shot--wide .shots__frame { aspect-ratio: 1180 / 600; }
  .shots__shot--wide .shots__frame img { height: 100%; object-fit: cover; }
}

.shots figcaption {
  margin-top: var(--space-3);
  font-size: var(--text-sm);
  color: var(--color-ink-faint);
}

/* --- Увеличение при наведении -------------------------------------------- */
/* Только там, где есть курсор: на сенсорном экране «наведение» — это
   нажатие, и кадр дёргался бы от каждого касания. Там кадр открывается
   нажатием — ссылка ведёт на сам файл. */

@media (hover: hover) and (pointer: fine) {
  .shots__frame {
    transition: transform 380ms cubic-bezier(0.22, 1, 0.36, 1);
  }
  .shots__shot:hover,
  .shots__shot:focus-within { z-index: 2; }
  .shots__shot:hover .shots__frame,
  .shots__shot:focus-within .shots__frame { transform: scale(var(--zoom, 1.33)); }

  /* Крайние кадры ряда растут в сторону середины, а не за край окна */
  .shots__row .shots__shot:first-child .shots__frame { transform-origin: left center; }
  .shots__row .shots__shot:last-child .shots__frame { transform-origin: right center; }

  /* Крупный кадр уже во всю колонку: его увеличение ограничено шириной
     окна, иначе он вылезет за края. Потолок поднимается ступенями по
     мере того, как окну есть что дать. */
  .shots__shot--wide { --zoom: var(--zoom-wide); }
  .shots { --zoom-wide: 1.05; }
}

@media (prefers-reduced-motion: reduce) {
  /* Увеличение остаётся, движение — нет */
  .shots__frame { transition: none; }
}

@media (min-width: 48rem) {
  .shots { margin-top: var(--space-9); }
  .shots__row { grid-template-columns: repeat(3, 1fr); gap: var(--space-7); }
  .shots__gallery { gap: var(--space-9); }
}

/* Потолок увеличения крупного кадра: он уже во всю колонку, и больше
   ширины окна ему расти некуда. Ступени посчитаны от ширины колонки
   (1100 при упёртом в предел контейнере) с запасом в 16 пикселей. */
@media (min-width: 78.75rem) { .shots { --zoom-wide: 1.13; } }
@media (min-width: 84.375rem) { .shots { --zoom-wide: 1.21; } }
@media (min-width: 88.75rem) { .shots { --zoom-wide: 1.28; } }
@media (min-width: 95rem) { .shots { --zoom-wide: 1.33; } }


/* =====================================================================
   Блок «How we measure». Три довода без единой картинки: волосок
   сверху, номер, крупный подзаголовок, абзац. Подзаголовки набраны
   так, чтобы их хватило для понимания блока без чтения абзацев.
   ===================================================================== */

.measure { margin-top: var(--space-8); }

.measure__title {
  margin-top: var(--space-5);
  /* Кегль привязан к ширине окна, а не к шагам: длинная вторая строка
     обязана лечь в одну строку, и предел взят из её измеренной ширины
     (23.5 em) с запасом. Потолок — 2.5rem: крупнее строка уже не
     помещается в колонку, а заголовок и не должен идти во всю ширину. */
  font-size: clamp(1.75rem, 3.7vw, 2.5rem);
}
.measure__accent { color: var(--color-accent); }

.measure__cards {
  margin: var(--space-8) 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--space-8);
}

/* Карточка — не плитка: ни заливки, ни рамки, только линия сверху */
.measure__card {
  border-top: var(--border-width) solid var(--color-line-strong);
  padding-top: var(--space-4);
}

.measure__n {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  color: var(--color-ink-faint);
}

.measure__head {
  margin: var(--space-4) 0 0;
  /* Заметно крупнее абзаца: блок обязан читаться по одним заголовкам */
  font-size: clamp(1.3rem, 0.95rem + 1.1vw, 1.6rem);
  line-height: var(--leading-snug);
  max-width: 18ch;
}

@media (min-width: 48rem) {
  /* Место под две строки во всех трёх: иначе абзацы начинаются
     на разной высоте и ряд рассыпается */
  .measure__head { min-height: calc(2 * var(--leading-snug) * 1em); }
}

.measure__text {
  margin: var(--space-4) 0 0;
  font-size: var(--text-md);
  line-height: var(--leading-normal);
  color: var(--color-ink-muted);
}

@media (min-width: 48rem) {
  .measure { margin-top: var(--space-9); }
  .measure__cards {
    margin-top: var(--space-9);
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-7);
  }
}


/* =====================================================================
   Блок «Sample report». Переходный и намеренно низкий: текст слева,
   страница отчёта справа. Низ страницы срезан краем блока — документ
   продолжается, и это видно без подписи.
   ===================================================================== */

.sample {
  margin-top: var(--space-8);
  padding-top: var(--space-8);
  /* Низ блока и есть линия среза: нижнего паддинга нет намеренно.
     Обрезает сам кадр своей высотой, а не блок — иначе при наведении
     увеличенная страница упиралась бы в нижний край блока. */
  padding-bottom: 0;
}

.sample__inner { display: grid; gap: var(--space-7); align-items: start; }

.sample__title {
  margin-top: var(--space-5);
  /* Кегль подобран по замеренной ширине строки: заголовок обязан лечь
     в одну строку в своей колонке, а она здесь уже половины полосы */
  font-size: clamp(1.5rem, 2.4vw, 2rem);
}
.sample__text {
  margin: var(--space-5) 0 0;
  max-width: 48ch;
  font-size: var(--text-lg);
  line-height: var(--leading-normal);
  color: var(--color-ink-muted);
}
.sample__action { margin: var(--space-6) 0 0; }

/* Страница отчёта: прямоугольник с волоском по краю. Нижней границы
   нет — с ней лист выглядел бы законченным, а он продолжается. */
.sample__page {
  margin: 0;
  max-height: 24rem;
  overflow: hidden;
  border: var(--border-strong);
  border-bottom: 0;
  border-radius: var(--radius-md) var(--radius-md) 0 0;
  background: var(--color-surface-raised);
}
.sample__page img { display: block; width: 100%; height: auto; }

/* Увеличение при наведении — то же, что у снимков кабинета. Растёт
   влево и вниз от правого верхнего угла: вправо мешал бы край окна,
   вверх — предыдущий блок. */
@media (hover: hover) and (pointer: fine) {
  .sample__page {
    position: relative;
    transform-origin: right top;
    transition: transform 380ms cubic-bezier(0.22, 1, 0.36, 1);
  }
  .sample__page:hover,
  .sample__page:focus-within {
    transform: scale(1.33);
    z-index: 2;
  }
}

@media (prefers-reduced-motion: reduce) {
  .sample__page { transition: none; }
}

@media (min-width: 48rem) {
  .sample { margin-top: var(--space-9); padding-top: var(--space-9); }
  .sample__inner {
    /* Страница занимает примерно половину полосы, текстовой колонке
       отдано чуть больше — иначе заголовок не встаёт в строку */
    grid-template-columns: 1.15fr 0.85fr;
    gap: var(--space-8);
  }
  .sample__page { max-height: 26rem; }
}


/* =====================================================================
   Страница /sample-report. Отчёт показан листами в том же порядке,
   в каком он приходит клиенту: не пересказ и не выжимка, а сам документ.
   Лист — картинка, поэтому весь смысл несёт подпись под ним.
   ===================================================================== */

.sample-report__get {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-4) var(--space-5);
  margin-top: var(--space-6);
}
.sample-report__get .note { margin: 0; }

.pages { display: grid; gap: var(--space-7); }

.pages__page { margin: 0; }

/* Рамка в волосок: лист и так белый, ему нужна граница, а не тень */
.pages__frame {
  display: block;
  border: var(--border-strong);
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--color-surface-raised);
}
.pages__frame img { display: block; width: 100%; height: auto; }

.pages figcaption {
  margin-top: var(--space-4);
  max-width: 44ch;
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  color: var(--color-ink-muted);
}
/* Номер листа — тем же моноширинным, каким пронумерован сам отчёт */
.pages figcaption b {
  margin-right: var(--space-3);
  font-family: var(--font-mono);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  color: var(--color-accent);
}

@media (min-width: 60rem) {
  .pages { grid-template-columns: repeat(2, 1fr); gap: var(--space-8) var(--space-7); }
}


/* =====================================================================
   Блок «Pricing» на главной. Короткая версия страницы цен: четыре
   карточки без списков возможностей. Оформление карточек то же, что
   на /pricing, но выделенная отличается плотностью границы, а не
   цветом и не тенью — теней на главной нет нигде.
   ===================================================================== */

.tariffs { margin-top: var(--space-8); }

.tariffs__title {
  margin-top: var(--space-5);
  font-size: clamp(1.75rem, 3.2vw, 2.6rem);
}
.tariffs__text {
  margin: var(--space-5) 0 0;
  max-width: 54ch;
  font-size: var(--text-lg);
  line-height: var(--leading-normal);
  color: var(--color-ink-muted);
}

.tariffs__cards {
  margin: var(--space-8) 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--space-4);
}

.tariffs__card {
  border: var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
/* Выделенная плотнее соседей: граница темнее и толще. Внутренний
   отступ уменьшен ровно на прибавку, чтобы текст не сдвинулся. */
.tariffs__card--featured {
  border: 2px solid var(--color-ink);
  padding: calc(var(--space-5) - 1px);
}

.tariffs__name { margin: 0; font-size: var(--text-xl); line-height: var(--leading-snug); }
.tariffs__price {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: var(--weight-medium);
  line-height: 1.1;
}
.tariffs__price span {
  display: block;
  margin-top: var(--space-1);
  font-size: var(--text-xs);
  font-weight: var(--weight-regular);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-ink-faint);
}
.tariffs__summary { margin: 0; font-size: var(--text-sm); color: var(--color-ink-muted); }

.tariffs__list {
  margin: 0 0 var(--space-4);
  padding: var(--space-4) 0 0;
  border-top: var(--border);
  list-style: none;
  display: grid;
  gap: var(--space-3);
  font-size: var(--text-sm);
}
.tariffs__list li {
  display: grid;
  grid-template-columns: 1.1rem 1fr;
  gap: var(--space-3);
  align-items: start;
  color: var(--color-ink-muted);
}

/* Кнопка карточки — надпись при переключателе. Прижата к низу, чтобы
   у карточек разной длины кнопки стояли в одну линию. Контурная, пока
   пакет не выбран: заливка здесь означает выбор, а не важность. */
.tariffs__button {
  margin-top: auto;
  justify-content: center;
  background: none;
  color: var(--color-ink);
  border: var(--border-strong);
  transition: background var(--duration) var(--ease), color var(--duration) var(--ease),
              border-color var(--duration) var(--ease);
}
.tariffs__button:hover { border-color: var(--color-ink); }
.tariffs__pick:focus-visible + .tariffs__button {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}
/* Рекомендованную карточку отличает плотность границы, выбранную —
   цвет: иначе на экране две одинаково толстые рамки и непонятно, где
   совет, а где ваш выбор. Толщину не трогаем, чтобы текст не дрогнул. */
.tariffs__card:has(.tariffs__pick:checked) { border-color: var(--color-accent); }
.tariffs__card:has(.tariffs__pick:checked) .tariffs__button {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-accent-ink);
}

/* Форма раскрывается без скачка вёрстки: анимируется не высота,
   а доля строки сетки — от нуля до содержимого. */
.tariffs__ask {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 300ms var(--ease);
}
.tariffs__panel {
  overflow: hidden;
  /* Пока закрыта, поля не должны ловить фокус табуляцией */
  visibility: hidden;
  transition: visibility 0s linear 300ms;
}
.tariffs__panel > * { margin-top: var(--space-7); }
.tariffs:has(.tariffs__pick:checked) .tariffs__ask { grid-template-rows: 1fr; }
.tariffs:has(.tariffs__pick:checked) .tariffs__panel {
  visibility: visible;
  transition-delay: 0s;
}

.tariffs__note {
  margin: var(--space-6) 0 0;
  font-size: var(--text-md);
  color: var(--color-ink-muted);
}
.tariffs__compare { margin-left: var(--space-3); font-size: var(--text-sm); }

@media (prefers-reduced-motion: reduce) {
  .tariffs__ask { transition: none; }
}

/* На телефоне форма встаёт сразу под нажатой карточкой, а не в конец
   колонки: иначе после нажатия по первой пришлось бы прокрутить мимо
   трёх остальных. Порядок задают номера — по тому, что выбрано. */
@media (max-width: 47.9375rem) {
  .tariffs__cards { gap: 0; }
  .tariffs__card { margin-bottom: var(--space-4); }
  .tariffs__card:nth-child(1) { order: 10; }
  .tariffs__card:nth-child(2) { order: 20; }
  .tariffs__card:nth-child(3) { order: 30; }
  .tariffs__card:nth-child(4) { order: 40; }
  .tariffs__ask { order: 50; }
  .tariffs:has(#plan-1:checked) .tariffs__ask { order: 11; }
  .tariffs:has(#plan-2:checked) .tariffs__ask { order: 21; }
  .tariffs:has(#plan-3:checked) .tariffs__ask { order: 31; }
}

@media (min-width: 48rem) {
  .tariffs { margin-top: var(--space-9); }
  .tariffs__cards { grid-template-columns: repeat(4, 1fr); gap: var(--space-5); }
  /* Форма — во всю ширину под карточками */
  .tariffs__ask { grid-column: 1 / -1; }
  /* Поля занимают половину полосы: строка в две трети экрана читается хуже */
  .tariffs__panel > * { max-width: 34rem; }
}


/* =====================================================================
   Блок «Questions» на главной. Раскрывающиеся details: без скриптов,
   без плиток и заливок — только волосок между вопросами. Заголовки
   вопросов крупные намеренно: человек, который просматривает страницу,
   должен прочитать сами вопросы, ничего не открывая.
   ===================================================================== */

.asks { margin-top: var(--space-8); }

.asks__title {
  margin-top: var(--space-5);
  font-size: clamp(1.6rem, 2.6vw, 2.4rem);
}

.asks__list {
  /* Не во всю ширину: строка длиннее семидесяти знаков не читается */
  max-width: 42rem;
  margin-top: var(--space-7);
}

/* На широком экране вопросы идут двумя колонками: одна колонка в пол-листа
   рядом с блоками во всю ширину читается как недоделанная. Ширина строки
   при этом не растёт — растёт число колонок. */
@media (min-width: 64rem) {
  .asks__list {
    max-width: none;
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 34rem));
    column-gap: var(--space-8);
    align-items: start;
  }
  .asks__column:last-child { margin-top: 0; }
}

/* Один столбец там, где вопросов немного: пять пунктов, разложенные
   в две колонки, читаются обрывком таблицы, а не списком. Правило стоит
   после медиазапроса выше — иначе двухколоночное перебило бы его. */
.asks__list--flat { display: block; max-width: 42rem; }

.asks__item { border-top: var(--border); }
/* Нижняя граница у последнего в каждой колонке: иначе левый столбец
   остаётся без основания */
.asks__column > .asks__item:last-child,
.asks__list--flat > .asks__item:last-child { border-bottom: var(--border); }

.asks__q {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--space-5);
  padding: var(--space-5) 0;
  cursor: pointer;
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  /* Заметно крупнее ответа на любой ширине: 20px против 16.8 на
     телефоне и 24 против 16.8 на широком экране */
  font-size: clamp(1.25rem, 0.9rem + 0.9vw, 1.5rem);
  line-height: var(--leading-snug);
  /* Своего треугольника у браузера быть не должно: знак у нас свой */
  list-style: none;
}
.asks__q::-webkit-details-marker { display: none; }
.asks__q:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 4px; }

/* Знак раскрытия: две волосяные черты крестом. При открытии вертикальная
   поворачивается и остаётся одна — плюс становится минусом. */
.asks__mark {
  position: relative;
  flex: none;
  width: 0.875rem; height: 0.875rem;
  margin-top: 0.3em;
}
.asks__mark::before,
.asks__mark::after {
  content: '';
  position: absolute;
  left: 0; right: 0; top: 50%;
  border-top: var(--border-width) solid var(--color-ink-faint);
}
.asks__mark::after { transform: rotate(90deg); transition: transform 240ms var(--ease); }
.asks__item[open] .asks__mark::after { transform: rotate(0deg); }

.asks__wrap { display: grid; grid-template-rows: 1fr; }
.asks__a { overflow: hidden; padding-bottom: var(--space-5); }
.asks__a p {
  max-width: 62ch;
  font-size: var(--text-md);
  line-height: var(--leading-normal);
  color: var(--color-ink-muted);
}
.asks__a p + p { margin-top: var(--space-4); }

/* Раскрытие: высота растёт от нуля до содержимого, вёрстка не скачет.
   Анимация, а не переход: до открытия содержимого просто нет в потоке,
   и переходу не от чего отталкиваться. */
.asks__item[open] .asks__wrap { animation: ask-open 280ms var(--ease); }
@keyframes ask-open {
  from { grid-template-rows: 0fr; opacity: 0; }
  to { grid-template-rows: 1fr; opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .asks__item[open] .asks__wrap { animation: none; }
  .asks__mark::after { transition: none; }
}

@media (min-width: 48rem) {
  .asks { margin-top: var(--space-9); }
}


/* =====================================================================
   Блок цен на главной, вторая версия. Monitoring занимает всю ширину
   и набран плотнее прочих — основной выбор виден по площади, а не по
   наклейке «популярный». Карточки те же: волосок по краю, ни теней,
   ни заливок.
   ===================================================================== */

.offer { margin-top: var(--space-8); }

.offer__title { margin-top: var(--space-5); font-size: clamp(1.75rem, 3.2vw, 2.6rem); }
.offer__text {
  margin: var(--space-5) 0 0;
  max-width: 54ch;
  font-size: var(--text-lg);
  line-height: var(--leading-normal);
  color: var(--color-ink-muted);
}

/* --- Бесплатная проверка строкой --------------------------------------- */

.offer__free {
  margin-top: var(--space-6);
  padding: var(--space-5) 0;
  border-top: var(--border);
  border-bottom: var(--border);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  align-items: center;
  justify-content: space-between;
}
.offer__free p { max-width: 62ch; font-size: var(--text-md); color: var(--color-ink-muted); }

/* --- Что меняет цену ---------------------------------------------------- */

.offer__choices { margin-top: var(--space-7); display: grid; gap: var(--space-6); }
.offer__set { border: 0; margin: 0; padding: 0; }
.offer__legend {
  padding: 0;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-ink-muted);
}
.offer__chips { margin-top: var(--space-3); display: flex; flex-wrap: wrap; gap: var(--space-2); }
.offer__chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0.4rem 0.9rem;
  border: var(--border-strong);
  border-radius: var(--radius-full);
  font-family: var(--font-display);
  font-size: var(--text-sm);
  cursor: pointer;
  transition: background var(--duration) var(--ease), color var(--duration) var(--ease),
              border-color var(--duration) var(--ease);
}
/* Точка внутри фишки: пустая — выключено, закрашенная — включено.
   Без неё фишка читается подписью, а не переключателем. */
.offer__dot {
  width: 0.5rem; height: 0.5rem;
  border-radius: 50%;
  border: var(--border-width) solid currentColor;
  flex: none;
}
.offer__eng:checked + .offer__chip .offer__dot,
.offer__work:checked + .offer__chip .offer__dot { background: currentColor; }

.offer__eng:checked + .offer__chip,
.offer__work:checked + .offer__chip {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-accent-ink);
}
.offer__eng:focus-visible + .offer__chip,
.offer__work:focus-visible + .offer__chip,
.offer__pick:focus-visible + .offer__button {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}
.offer__hint {
  margin-top: var(--space-3);
  max-width: 62ch;
  font-size: var(--text-sm);
  color: var(--color-ink-muted);
}

/* --- Пакеты ------------------------------------------------------------- */

.offer__flow { margin-top: var(--space-7); display: flex; flex-direction: column; }

.offer__plan {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5);
  border: var(--border);
  border-radius: var(--radius-lg);
}
/* Главный пакет: больше воздуха внутри и плотнее набор снаружи */
.offer__plan--lead { padding: var(--space-6); border-color: var(--color-line-strong); }
.offer__plan--lead .offer__name { font-size: var(--text-2xl); }

.offer__head { display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-5);
               align-items: baseline; justify-content: space-between; }
.offer__name { margin: 0; font-size: var(--text-xl); line-height: var(--leading-snug); }
.offer__price {
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: var(--text-lg);
  white-space: nowrap;
}
.offer__price span {
  margin-left: var(--space-2);
  font-size: var(--text-xs);
  font-weight: var(--weight-regular);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-ink-faint);
}
.offer__summary { margin: 0; font-size: var(--text-md); color: var(--color-ink-muted); }

.offer__list {
  margin: var(--space-3) 0 var(--space-4);
  padding: var(--space-4) 0 0;
  border-top: var(--border);
  list-style: none;
  display: grid;
  gap: var(--space-3);
  font-size: var(--text-sm);
}
.offer__list li {
  display: grid;
  grid-template-columns: 1.1rem 1fr;
  gap: var(--space-3);
  align-items: start;
  color: var(--color-ink-muted);
}

/* Кнопка пакета — акцентом: контурную на светлом фоне просто не видно */
.offer__button {
  margin-top: auto;
  justify-content: center;
  background: var(--color-accent);
  border: var(--border-width) solid var(--color-accent);
  color: var(--color-accent-ink);
  transition: background var(--duration) var(--ease), border-color var(--duration) var(--ease);
}
.offer__button:hover {
  background: var(--color-accent-strong);
  border-color: var(--color-accent-strong);
}
.offer__plan:has(.offer__pick:checked) { border-color: var(--color-accent); }
/* Выбранный пакет отмечен рамкой карточки: кнопки и так все в цвете */
.offer__plan:has(.offer__pick:checked) { border-width: 2px; padding: calc(var(--space-5) - 1px); }
.offer__plan--lead:has(.offer__pick:checked) { padding: calc(var(--space-6) - 1px); }

.offer__oneoff {
  margin: var(--space-6) 0 var(--space-4);
  font-size: var(--text-md);
  color: var(--color-ink-muted);
}
.offer__pair { display: grid; gap: var(--space-4); }

/* --- Заявка ------------------------------------------------------------- */
/* Форма встаёт под нажатым пакетом: порядок в колонке переключается
   по тому, что выбрано, — иначе после нажатия по Monitoring пришлось бы
   прокрутить мимо двух остальных. */

.offer__plan--lead { order: 10; margin-bottom: var(--space-6); }
.offer__ask { order: 50; }
.offer__oneoff { order: 20; }
.offer__pair { order: 30; }
.offer:has(#pick-monitoring:checked) .offer__ask { order: 15; }

/* На телефоне пара стоит колонкой, и форма должна вставать под нажатой
   карточкой, а не под обеими. Для этого пара перестаёт быть отдельным
   ящиком, и её карточки встраиваются в общий порядок. */
@media (max-width: 47.9375rem) {
  .offer__pair { display: contents; }
  .offer__pair .offer__plan { margin-bottom: var(--space-4); }
  .offer__pair .offer__plan:nth-of-type(1) { order: 30; }
  .offer__pair .offer__plan:nth-of-type(2) { order: 40; }
  .offer:has(#pick-scan:checked) .offer__ask { order: 35; }
  .offer:has(#pick-foundation:checked) .offer__ask { order: 45; }
}

.offer__ask {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 300ms var(--ease);
}
.offer__panel {
  overflow: hidden;
  /* Пока закрыта, поля не должны ловить фокус табуляцией */
  visibility: hidden;
  transition: visibility 0s linear 300ms;
}
.offer__panel > :first-child { margin-top: var(--space-5); }
.offer:has(.offer__pick:checked) .offer__ask { grid-template-rows: 1fr; }
.offer:has(.offer__pick:checked) .offer__panel { visibility: visible; transition-delay: 0s; }

/* Что уйдёт в заявку: пакет, ассистенты и кто делает работу */
.offer__chosen { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: 0 0 var(--space-4); }
.offer__tag {
  display: none;
  padding: 0.2rem 0.6rem;
  border: var(--border);
  border-radius: var(--radius-full);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.06em;
  color: var(--color-ink-muted);
}
.offer:has(#pick-monitoring:checked) [data-pick="monitoring"],
.offer:has(#pick-scan:checked) [data-pick="scan"],
.offer:has(#pick-foundation:checked) [data-pick="foundation"],
.offer:has(#eng-1:checked) [data-eng="1"],
.offer:has(#eng-2:checked) [data-eng="2"],
.offer:has(#eng-3:checked) [data-eng="3"],
.offer:has(#eng-4:checked) [data-eng="4"],
.offer:has(#work-us:checked) [data-work="us"],
.offer:has(#work-you:checked) [data-work="you"] { display: inline-flex; }

.offer__note {
  margin: var(--space-7) 0 0;
  font-size: var(--text-md);
  color: var(--color-ink-muted);
}
.offer__compare { margin-left: var(--space-3); font-size: var(--text-sm); }

@media (prefers-reduced-motion: reduce) {
  .offer__ask { transition: none; }
}

@media (min-width: 48rem) {
  .offer { margin-top: var(--space-9); }
  .offer__choices { grid-template-columns: 1.6fr 1fr; gap: var(--space-8); }
  .offer__pair { grid-template-columns: 1fr 1fr; gap: var(--space-5); }
  /* Пять пунктов главного пакета в две колонки: полоса широкая,
     и в одну они растянулись бы на весь экран */
  .offer__plan--lead .offer__list { grid-template-columns: 1fr 1fr; gap: var(--space-3) var(--space-6); }
  /* Поля — в половину полосы: строка ввода во всю ширину читается хуже */
  .offer__panel .form { max-width: 34rem; }
}


/* =====================================================================
   Закрывающий блок главной. Та же светлая акцентная заливка, что
   в «What we do»: тёмный текст, ни графики, ни рамок. Одна фраза,
   одна кнопка и воздух вокруг них.
   ===================================================================== */

.last {
  margin-top: var(--space-8);
  /* Тёмная заливка, как у прежней полосы призыва: страница закрывается
     ею и отделяется от подвала */
  background: var(--color-surface-inverse);
  color: var(--color-surface);
  padding: var(--space-8) 0;
}

/* Текст начинается там же, где заголовки соседних блоков — у левого
   поля страницы, — но колонка узкая: фраза в две трети экрана
   не читается. Ширину держат сами абзацы, а не контейнер. */
/* Ширины у заголовка нет: фраза обязана лечь в одну строку, а кегль
   подобран так, чтобы она помещалась в колонку от 768 пикселей вверх */
.last__title { font-size: clamp(1.75rem, 3.4vw, 2.75rem); }
.last__text {
  margin: var(--space-5) 0 0;
  max-width: 48ch;
  font-size: var(--text-lg);
  line-height: var(--leading-normal);
  color: var(--color-ink-inverse-muted);
}
.last__action { margin: var(--space-7) 0 0; }

@media (min-width: 48rem) {
  .last { margin-top: var(--space-9); padding: var(--space-10) 0; }
}


/* =====================================================================
   Фон первого экрана внутренних страниц: два кольца, срезанных правым
   верхним углом, и точка на контуре. Слой лежит под содержимым
   и обрезан краями окна. Всё очень бледно: фон не даёт экрану
   выглядеть пустым и не спорит с заголовком.
   ===================================================================== */

.page-bg {
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 26rem;
  overflow: hidden;
  /* Под всем содержимым, но над фоном страницы */
  z-index: -1;
  pointer-events: none;
}

.page-bg__ring {
  position: absolute;
  border-radius: 50%;
  border: 1.5px solid var(--color-ink);
  opacity: 0.08;
  /* Мера от правого верхнего угла: кольцо срезано им при любой ширине */
  width: 30rem; height: 30rem;
  right: -9rem; top: -10rem;
}
.page-bg__ring--inner {
  width: 21rem; height: 21rem;
  right: -4.5rem; top: -5.5rem;
  border-style: dashed;
  opacity: 0.07;
}
/* Точка сидит на контуре пунктирного кольца — в просвете между шапкой
   и заголовком, а не под буквами */
.page-bg__dot {
  position: absolute;
  width: 0.875rem; height: 0.875rem;
  right: 16.3rem; top: 8.2rem;
  border-radius: 50%;
  background: var(--color-accent);
  opacity: 0.16;
}

@media (min-width: 48rem) {
  .page-bg { height: 30rem; }
  .page-bg__ring { width: 46rem; height: 46rem; right: -13rem; top: -15rem; }
  .page-bg__ring--inner { width: 32rem; height: 32rem; right: -6rem; top: -8rem; }
  .page-bg__dot { right: 25.4rem; top: 13.1rem; }
}

/* ---------------------------------------------------------------------
   Экраны кабинета на телефоне.

   Три правила, общие для всех разрезов:

   * таблица шире экрана прокручивается внутри себя, а не уносит вбок
     страницу, и первый столбец при этом стоит на месте — иначе числа
     уезжают от того, к чему относятся;
   * таблица, которая по смыслу список (строка на вопрос), становится
     карточками: пять колонок на 390px не читаются никак;
   * до кнопки и поля можно дотянуться пальцем — 44px, не меньше.
   --------------------------------------------------------------------- */

@media (max-width: 56.25rem) {
  /* --- таблицы --- */
  .table-wrap { position: relative; }
  .table-wrap th:first-child, .table-wrap td:first-child {
    position: sticky; left: 0; z-index: 1;
    background: var(--color-surface);
    /* Волосок по краю: видно, что столбец стоит, а не налез на соседний */
    box-shadow: 1px 0 0 var(--color-line);
  }
  /* Ваша строка держит свой цвет и в прилипшем столбце — иначе он один
     останется другого цвета. У таблицы кабинета и у образца отчёта
     на сайте эти цвета разные, поэтому правила два */
  .table-wrap tr.is-you td:first-child { background: var(--color-accent-wash); }
  .table-wrap .data-table tr.is-you td:first-child {
    background: var(--color-you-wash);
    box-shadow: inset 3px 0 0 var(--color-you), 1px 0 0 var(--color-line); }
  /* Отметка провала и волосок края — вместе, иначе один затирает другой */
  .data-table tr.is-gap td:first-child {
    box-shadow: inset 2px 0 0 var(--color-signal), 1px 0 0 var(--color-line); }

  /* --- вопросы карточками --- */
  .data-table.questions { display: block; min-width: 0; }
  .data-table.questions thead { display: none; }
  .data-table.questions tbody { display: block; }
  .data-table.questions tr {
    display: grid; grid-template-columns: minmax(0, 1fr) auto;
    gap: var(--space-2) var(--space-4);
    border: var(--border); border-left: 2px solid transparent;
    padding: var(--space-4); margin-bottom: var(--space-3);
  }
  /* Провал отмечен тем же волоском, что и в таблице, — слева у карточки */
  .data-table.questions tr.is-gap { border-left-color: var(--color-signal); }
  .data-table.questions td { display: block; border: 0; padding: 0;
                             box-shadow: none; }
  /* Ни прилипания, ни волоска края: в карточке первый столбец — заголовок,
     а отметку провала держит её левая рамка */
  .data-table.questions tr.is-gap td:first-child { padding-left: 0;
                                                   box-shadow: none; }
  .data-table.questions td:first-child { position: static; box-shadow: none;
                                         background: none; }
  /* Подпись столбца переезжает к значению и встаёт в ту же строку:
     четыре строки на карточку вместо восьми */
  .data-table.questions td[data-label]::before {
    content: attr(data-label); margin-right: 0.5em;
    font-family: var(--font-display); font-size: 0.66rem;
    letter-spacing: var(--tracking-wide); text-transform: uppercase;
    color: var(--color-ink-faint);
  }
  .data-table.questions .questions__text {
    /* width: 34% приходит от таблицы — в карточке вопрос занимает её всю */
    grid-column: 1 / -1; grid-row: 1; width: auto; max-width: none;
    position: static; font-weight: var(--weight-medium); }
  .data-table.questions td[data-label="Type"] { grid-column: 1; grid-row: 2; }
  .data-table.questions td.num { grid-column: 2; grid-row: 2;
                                 text-align: right; padding-right: 0; }
  .data-table.questions td[data-label="Answers"] { grid-column: 1 / -1;
                                                   grid-row: 3; }
  .data-table.questions td[data-label="Named instead"] { grid-column: 1 / -1;
                                                         grid-row: 4; }
  .data-table.questions .ticks { vertical-align: middle; }

  /* --- выбор из списка: фильтр во всю ширину, подпись над ним --- */
  .run-picker label { display: grid; grid-template-columns: minmax(0, 1fr);
                      gap: var(--space-2); }
  .run-picker select { width: 100%; flex: none; min-height: 2.75rem; }

  /* --- длинные ответы --- */
  /* В ответе попадается ссылка или строка кода без единого пробела:
     переносить её не по чему, и она уносит за край всю страницу.
     Разрешаем разрыв в любом месте — только на узком экране */
  .answer__body, .answer__full { overflow-wrap: anywhere; }

  /* --- вкладки ассистентов: если не влезли, едут пальцем --- */
  .engine-tabs { overflow-x: auto; }

  /* Выбор проекта — такая же цель для пальца, как кнопки */
  .picker__button { min-height: 2.75rem; }
  .picker__list a { min-height: 2.75rem; display: flex; align-items: center; }

  /* --- палец --- */
  /* Подсказка к метрике — слово внутри строки, и растягивать его отступом
     нельзя: пунктир отъедет от слова, а строка разъедется. Зону касания
     даёт псевдоэлемент с отрицательным inset — он ничего не двигает.
     Запас считан по самой тесной паре подсказок на всех экранах: по
     горизонтали соседи расходятся на 24px, по вертикали на 33px, поэтому
     зона растёт на 9 и 12 и всё равно не смыкается с соседней. Слово
     высотой 20px становится целью в 44px. */
  .app-body .hint { position: relative; }
  .app-body .hint::before { content: ""; position: absolute;
                            inset: -0.75rem -0.55rem; }
  /* На телефоне пунктир под словом — просто пунктир: наведения нет,
     и понять, что по слову можно нажать, неоткуда. Звёздочка знакома
     всем и обещает ровно то, что есть: сейчас объяснят. Цвет акцентный —
     им в кабинете отмечено всё действующее.

     «*» / «» — вторая часть это то, что достаётся программе чтения
     с экрана: пусто. Иначе к каждому заголовку столбца она добавляла бы
     «звёздочка», а объяснение и так лежит в самой подсказке. */
  .app-body .hint::after {
    content: "*" / ""; margin-left: 0.1em; letter-spacing: 0;
    color: var(--color-accent); font-weight: var(--weight-medium);
  }
  /* Название подраздела в обзоре — тем же приёмом: это заголовок строки,
     и поднимать его отступом значит разгонять список */
  .cut__name { position: relative; }
  .cut__name::before { content: ""; position: absolute;
                       inset: -0.55rem -0.5rem; }
  /* Имя проекта в списке клиентов — главная цель на экране менеджера,
     а строкой таблицы оно всего 18px. Строки стоят в 54px друг от друга,
     поэтому зоны по 44px не смыкаются */
  .app-body .data-table a.link { position: relative; display: inline-block; }
  .app-body .data-table a.link::before { content: ""; position: absolute;
                                         inset: -0.8rem -0.5rem; }

  /* --- экран подготовки отчёта --- */
  /* Галочка в 13px — не цель для пальца. Увеличиваем саму галочку:
     подпись рядом с ней и так нажимается, она внутри label */
  .app-body input[type="checkbox"], .app-body input[type="radio"] {
    width: 1.25rem; height: 1.25rem; }
  /* Целью служит вся подпись: по ней и нажимают, а не по самому квадрату */
  .app-body label:has(> input[type="checkbox"]),
  .app-body label:has(> input[type="radio"]) {
    display: inline-flex; align-items: center; gap: var(--space-2);
    min-height: 2.75rem; }
  /* Поле правки в две строки показывает полторы фразы из четырёх, и
     менеджер правит формулировку вслепую. Только на экране подготовки:
     в очереди разбора в поле лежит одна строка вопроса */
  .prep-screen textarea { min-height: 7rem; }
  /* Строка решений: вид находки — своей строкой, «Save» к правому краю.
     Иначе три разных по длине куска переносятся каждый раз по-новому */
  .prep-row .review__row { flex-wrap: wrap; row-gap: var(--space-3); }
  .prep-row .review__row > span.dim { flex: 1 0 100%; }
  .prep-row .review__row > button { margin-left: auto; }

  .app-body .button { min-height: 2.75rem; display: inline-flex;
                      align-items: center; justify-content: center; }
  .app-body .button--quiet { min-height: 2.75rem; }
  .app-body input[type="text"], .app-body input[type="email"],
  .app-body input[type="search"], .app-body input[type="url"],
  .app-body textarea { width: 100%; max-width: 100%; }
  .app-body input[type="text"], .app-body input[type="email"],
  .app-body input[type="search"], .app-body input[type="url"],
  .app-body select { min-height: 2.75rem; }
}

/* ─────────────────────────────────────────────────────────────────────
   Исходящие продажи

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

/* Заведение списка и загрузка файла — две строки подряд в одном ритме.
   Порядок не случаен: складывать компании некуда, пока списка нет */
.newlist, .upload { display: flex; flex-wrap: wrap; gap: var(--space-3);
                    align-items: center; margin: var(--space-4) 0;
                    padding: var(--space-4); border: var(--border);
                    border-radius: var(--radius-md);
                    background: var(--color-surface-raised); }
.newlist label, .upload label { font-family: var(--font-display);
                                font-size: var(--text-sm); white-space: nowrap; }
.newlist input[type="text"] { flex: 1 1 12rem; min-width: 8rem; }
.upload input[type="file"] { flex: 1 1 14rem; min-width: 0;
                             font-family: var(--font-display);
                             font-size: var(--text-sm); }
.upload .dim, .newlist .dim { flex: 1 0 100%; }

/* Ссылка на «Сегодня»: первое, что должно попасться на глаза */
.today-link { display: flex; flex-wrap: wrap; gap: var(--space-3);
              align-items: baseline; margin: var(--space-4) 0; }
.today-link > a { font-family: var(--font-display); font-weight: 600; }

.crumbs { margin: 0 0 var(--space-2); font-family: var(--font-display);
          font-size: var(--text-sm); color: var(--color-ink-muted); }
/* Крошки страницы: своя полоса над первым экраном, по той же сетке,
   что и содержимое. Внутри кабинета и статей они свои и уже на месте */
.crumbs--page { margin: 0; padding: var(--space-5) 0 0; }
.crumbs--page a { color: var(--color-ink-muted); }
.crumbs--page a:hover { color: var(--color-accent); }

/* Образная строка под заголовком: ключ ушёл в H1, а фраза, ради которой
   страницу читают, осталась — крупнее лида, тише заголовка */
.sample-report__slogan { margin: var(--space-4) 0 0;
                         font-size: clamp(1.25rem, 0.9rem + 1.4vw, 1.75rem);
                         line-height: var(--leading-snug);
                         letter-spacing: var(--tracking-tight); }

/* Списки выборок */
.cards { list-style: none; margin: var(--space-5) 0 0; padding: 0;
         display: grid; gap: var(--space-4); }
.cards__item { padding: var(--space-4); border: var(--border);
               border-radius: var(--radius-md); }
.cards__head { display: flex; flex-wrap: wrap; gap: var(--space-3);
               align-items: baseline; justify-content: space-between; }
.cards__head .app-h2 { margin: 0; }
.cards__count { margin: 0; font-family: var(--font-display);
                font-size: var(--text-sm); color: var(--color-ink-muted); }
.cards__due { margin: var(--space-3) 0 0; font-family: var(--font-display);
              font-size: var(--text-sm); }

/* Разбивка по состояниям: число рядом со словом, без столбиков —
   их тут нечем сравнивать между собой */
.pills { display: flex; flex-wrap: wrap; gap: var(--space-2);
         margin: var(--space-3) 0 0; }
.pill { display: inline-flex; gap: var(--space-2); align-items: baseline;
        padding: var(--space-1) var(--space-3);
        border: var(--border); border-radius: var(--radius-full);
        font-family: var(--font-display); font-size: var(--text-xs);
        text-decoration: none; }

/* Две кнопки под формой импорта: «посмотреть» и «записать».
   Своё имя, потому что .actions на сайте — нумерованный список шагов */
.slab-actions { display: flex; flex-wrap: wrap; gap: var(--space-3);
                margin: var(--space-5) 0; }
.slab-actions .button { flex: 1 1 14rem; }

/* Карточка компании собрана из панелей: у каждой свой вопрос */
.slab { margin: var(--space-5) 0; padding: var(--space-4);
         border: var(--border); border-radius: var(--radius-md); }
.slab > .app-h2:first-child { margin-top: 0; }
.slab form { display: flex; flex-wrap: wrap; gap: var(--space-3);
              align-items: center; margin-top: var(--space-3); }
.slab form label { font-family: var(--font-display);
                    font-size: var(--text-sm); white-space: nowrap; }
.slab textarea { flex: 1 0 100%; }
.or { font-family: var(--font-display); font-size: var(--text-sm);
      color: var(--color-ink-faint); }

/* Панель массового действия в очереди разбора: стоит над списком,
   потому что решение «делаю пачкой» принимают до того, как начали
   отмечать, а не после */
.bulk { display: flex; flex-wrap: wrap; gap: var(--space-3);
        align-items: center; margin: var(--space-4) 0;
        padding: var(--space-3) var(--space-4); border: var(--border);
        border-radius: var(--radius-md);
        background: var(--color-surface-raised); }
.bulk--tail { margin-top: var(--space-2); }
.bulk label { font-family: var(--font-display); font-size: var(--text-sm); }
.bulk input[type="number"] { width: 4.5rem; min-height: 2.5rem; }
.pick { margin-right: var(--space-2); vertical-align: -0.1em; }
/* «Отметить всё» и счётчик отмеченных. Ставится скриптом первым в панели:
   массовое действие без числа перед глазами — действие вслепую */
.bulk__all { display: inline-flex; align-items: center; gap: var(--space-1);
             font-family: var(--font-display); font-size: var(--text-sm);
             white-space: nowrap; cursor: pointer; }

/* Отправка скана клиенту: свёрнута, пока не нужна — на экране список
   сканов, а не форма, и раскрывать её должен тот, кто собрался слать */
.sendout { margin-top: var(--space-2); }
.sendout summary { font-family: var(--font-display); font-size: var(--text-sm);
                   cursor: pointer; }
.sendout form { display: grid; gap: var(--space-2); margin-top: var(--space-3);
                min-width: 18rem; }

/* Поля компании: подпись и значение в две колонки. Длинные ссылки
   переносятся, а не растягивают страницу */
.facts { display: grid; grid-template-columns: max-content minmax(0, 1fr);
         gap: var(--space-2) var(--space-5); margin: var(--space-3) 0 0; }
.facts dt { font-family: var(--font-display); font-size: var(--text-sm);
            color: var(--color-ink-muted); }
.facts dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }

.contacts, .scans { list-style: none; margin: var(--space-3) 0 0; padding: 0;
                    display: grid; gap: var(--space-3); }
.contacts__item { padding-bottom: var(--space-3); border-bottom: var(--border); }
.contacts__item:last-child { border-bottom: none; padding-bottom: 0; }
.contacts__who { margin: 0; font-weight: 600; }
.contacts__item p { margin: var(--space-1) 0 0; }
.scans__item { display: flex; flex-wrap: wrap; gap: var(--space-3);
               align-items: center; }
.scans__item form { margin: 0; }

/* Заготовка письма: моноширинный, потому что его копируют целиком */
.letter { width: 100%; font-family: var(--font-mono, monospace);
          font-size: var(--text-sm); line-height: 1.5; }

.counts { margin: var(--space-3) 0 0; padding-left: var(--space-5); }
.counts li { margin: var(--space-1) 0; }

/* Лента действий */
.feed { list-style: none; margin: var(--space-3) 0 0; padding: 0;
        display: grid; gap: var(--space-4); }
.feed__item { padding-left: var(--space-4);
              border-left: var(--border-width) solid var(--color-line); }
.feed__when { margin: 0; font-family: var(--font-display);
              font-size: var(--text-xs); color: var(--color-ink-faint); }
.feed__what { margin: var(--space-1) 0 0; }
.feed__body { margin: var(--space-2) 0 0; white-space: pre-wrap;
              color: var(--color-ink-muted); }

/* Экран «Сегодня» */
.waiting { list-style: none; margin: var(--space-3) 0 0; padding: 0;
           display: grid; gap: var(--space-4); }
.waiting__item { display: flex; flex-wrap: wrap; gap: var(--space-3);
                 align-items: center; justify-content: space-between;
                 padding-bottom: var(--space-4); border-bottom: var(--border); }
.waiting__item:last-child { border-bottom: none; padding-bottom: 0; }
.waiting__who { margin: 0; display: flex; flex-wrap: wrap;
                gap: var(--space-2); align-items: baseline; }
.waiting__why { margin: var(--space-1) 0 0; }

@media (max-width: 40rem) {
  /* С телефона поля в строку не помещаются: каждое своей строкой,
     иначе половина уезжает за край */
  .newlist, .upload, .slab form { flex-direction: column;
                                   align-items: stretch; }
  /* Разворот ряда в колонку меняет смысл `flex`: основа `12rem`
     задавала ширину, а стала задавать высоту — поля вырастали до 192
     и 224 точек и занимали весь экран. В колонке основа не нужна
     вовсе: поле и так во всю ширину */
  .newlist input[type="text"], .upload input[type="file"],
  .slab form input, .slab form select { flex: 0 0 auto; min-width: 0; }
  /* У поля выбора файла своя неустранимая ширина: кнопка «Choose File»
     плюс «No file chosen» дают 348 точек, и карточка в 297 протекала
     вправо. `min-width: 0` тут не помогает — помогает явная ширина */
  .upload input[type="file"] { width: 100%; max-width: 100%; }
  /* С телефона две колонки не помещаются: подпись над значением */
  .facts { grid-template-columns: minmax(0, 1fr); gap: var(--space-1); }
  .facts dd { margin-bottom: var(--space-3); }
  .newlist label, .upload label, .slab form label { white-space: normal; }
}


/* ─────────────────────────────────────────────────────────────────────
   Блог

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

/* Статью читают подряд — колонка узкая. Перечень и страница автора
   живут в общем контейнере сайта, как все остальные страницы */
.post__inner { max-width: 44rem; margin: 0 auto; padding: 0 var(--space-5); }

/* Блог в две колонки: текст и боковая панель. Без панели колонка
   в 44rem оставляла по трети экрана пустоты с каждой стороны, а шире
   строку делать нельзя — её перестают читать.

   Панель никуда не едет и ничего внутри себя не прокручивает. Липкая
   колонка с ограничением по высоте давала две полосы прокрутки на одном
   экране — внутри оглавления и внутри самой панели, — и выглядело это
   как поломка, а не как блог.

   На телефоне панель идёт под текстом: там она не навигация,
   а продолжение страницы. */
@media (min-width: 72rem) {
  .post__inner {
    max-width: 70rem;
    display: grid;
    grid-template-columns: minmax(0, 44rem) minmax(0, 18rem);
    column-gap: var(--space-8);
    align-items: start;
  }
  /* Колонка с текстом: `min-width: 0` обязателен, иначе широкая таблица
     внутри растянет колонку сетки и сломает страницу */
  .post__main { min-width: 0; }
}

/* Шапка перечня встаёт по той же сетке, что список со вкладкой:
   иначе заголовок начинается у края страницы, а список — на двести
   пикселей правее */
@media (min-width: 72rem) {
  .posts-head .section__inner { max-width: 70rem; }
}

.post__main { min-width: 0; }
.side { display: grid; gap: var(--space-4); margin-top: var(--space-7); }

/* Список начинается сразу под шапкой: два полных отступа подряд —
   шапки и секции — давали пустую полосу в треть экрана */
.posts { padding-top: var(--space-5); }

/* Строка разделов над списком нужна там, где боковой панели нет.
   С панелью это второй такой же список на одном экране */
@media (min-width: 72rem) {
  .posts .sections { display: none; }
}

/* Два оглавления в разметке, но показано всегда одно: на широком экране
   панельное, на узком — свёрнутое над текстом. Скрытое `display: none`
   скринридер не читает, так что дубля для человека нет */
.post__toc-mobile { margin: var(--space-5) 0; padding: var(--space-4) var(--space-5);
                    border: var(--border); border-radius: var(--radius-md);
                    background: var(--color-surface-raised); }
.post__toc-mobile summary { cursor: pointer; font-family: var(--font-display);
                            font-size: var(--text-sm); }
.post__toc-mobile ol { margin: var(--space-4) 0 0; padding-left: var(--space-5);
                       display: grid; gap: var(--space-2); font-size: var(--text-sm); }
@media (min-width: 72rem) {
  /* Селектор нарочно не из одного класса: правило `display: none` на голом
     классе ловит сторож стилей, и ловит правильно — так когда-то пропала
     целая карточка. Здесь скрытие осмысленное и привязано к раскладке */
  .post__inner .post__toc-mobile { display: none; }
}
@media (max-width: 71.99rem) {
  .side .post__toc { display: none; }
}
/* Каждый блок — карточка: иначе панель читается как вторая колонка
   текста, а не как навигация рядом с ней */
.side__block { padding: var(--space-5); border: var(--border);
               border-radius: var(--radius-md); background: var(--color-surface); }
.side__head { margin: 0 0 var(--space-4); font-family: var(--font-display);
              font-size: var(--text-xs); letter-spacing: 0.06em;
              text-transform: uppercase; color: var(--color-ink-faint); }
.side__list, .side__posts, .side__toc { list-style: none; margin: 0; padding: 0;
                                        display: grid; gap: var(--space-3); }
.side__list a, .side__posts a, .side__toc a {
  font-family: var(--font-display); font-size: var(--text-sm);
  line-height: var(--leading-snug); color: var(--color-ink); }
.side__list a:hover, .side__posts a:hover, .side__toc a:hover { color: var(--color-accent); }
.side__list a[aria-current] { color: var(--color-accent); }
.side__toc a { color: var(--color-ink-80); }
.side__posts li { display: grid; gap: var(--space-1); }
.side__meta { font-family: var(--font-mono); font-size: var(--text-xs);
              letter-spacing: var(--tracking-wide); text-transform: uppercase;
              color: var(--color-ink-faint); }
.side__tags { margin: 0; }
.side__cta { background: var(--color-surface-raised); }
.side__cta-text { margin: 0 0 var(--space-4); font-size: var(--text-sm);
                  line-height: var(--leading-normal); color: var(--color-ink-muted); }

/* Обложка статьи: во всю ширину колонки, пропорция 3:2 задана файлом.
   `fetchpriority` и отсутствие ленивой загрузки намеренно — это первый
   экран, и грузиться он должен сразу */
.post__cover { margin: var(--space-6) 0; }
.post__cover img { width: 100%; height: auto; display: block;
                   border-radius: var(--radius-md); }
.post__cover figcaption { margin-top: var(--space-2); font-size: var(--text-xs);
                          color: var(--color-ink-faint); }
.post__cover figcaption a { color: var(--color-ink-muted); }
.post__cover figcaption a:hover { color: var(--color-accent); }

/* Карточка в перечне: картинка слева, текст справа. Без картинки
   карточка остаётся как была — перечень не должен разваливаться
   из-за того, что к статье ещё не подобрали обложку */
.posts__cover { display: block; }
/* Текстовая часть карточки: в сетке ей нужен `min-width: 0`, иначе
   длинный заголовок без пробелов растянет колонку */
.posts__text { min-width: 0; }
.posts__cover img { width: 100%; height: auto; display: block;
                    border-radius: var(--radius-sm); }
@media (min-width: 40rem) {
  .posts__item--art { display: grid; grid-template-columns: 13rem minmax(0, 1fr);
                      gap: var(--space-5); align-items: start; }
}

/* Список статей не растягиваем на всю ширину контейнера: строка в
   полтора экрана не читается */
.posts__list { max-width: 48rem; }
.posts__list { list-style: none; margin: var(--space-6) 0 0; padding: 0;
               display: grid; gap: var(--space-7); }
.posts__item { padding-bottom: var(--space-6); border-bottom: var(--border); }
.posts__item:last-child { border-bottom: none; }
.posts__when, .post__by { margin: 0; font-family: var(--font-display);
                          font-size: var(--text-sm);
                          color: var(--color-ink-muted); }
.posts__title { margin: var(--space-2) 0 var(--space-3); }
.posts__lede { margin: 0 0 var(--space-3); color: var(--color-ink-muted); }

.post__by { margin-top: var(--space-3); }
/* Краткое резюме: это то, что ассистент извлечёт как готовый ответ,
   и человек прочтёт первым. Крупнее текста, но не заголовок */
.post__tldr { margin: var(--space-5) 0; padding-left: var(--space-5);
              border-left: var(--border-width) solid var(--color-accent);
              font-size: var(--text-lg); line-height: var(--leading-snug); }

.post__body { margin-top: var(--space-6); }
.post__body h2 { margin-top: var(--space-7); }
.post__body h3 { margin-top: var(--space-6); }
.post__body p, .post__body li { max-width: 68ch; }
.post__body ul, .post__body ol { padding-left: var(--space-5); }
.post__body li { margin: var(--space-2) 0; }
/* Таблицы сравнения — текстом, а не картинкой: картинку не прочитает
   ни ассистент, ни человек с телефона */
.post__body table { width: 100%; border-collapse: collapse;
                    margin: var(--space-5) 0; font-size: var(--text-sm); }
.post__body th, .post__body td { border-bottom: var(--border);
                                 padding: var(--space-3) var(--space-4)
                                          var(--space-3) 0;
                                 text-align: left; vertical-align: top; }
.post__body blockquote { margin: var(--space-5) 0; padding-left: var(--space-5);
                         border-left: var(--border-width) solid
                                      var(--color-line-strong);
                         color: var(--color-ink-muted); }

.post__faq { margin-top: var(--space-7); }
.post__faq dt { font-weight: 600; margin-top: var(--space-5); }
.post__faq dd { margin: var(--space-2) 0 0; max-width: 68ch; }

.post__end { margin-top: var(--space-7); padding-top: var(--space-5);
             border-top: var(--border); }

/* Оглавление статьи. Над текстом, а не сбоку: сбоку оно исчезает на
   телефоне, а читают чаще с телефона */
/* Оглавление живёт в боковой панели и оформлено её правилами.
   Здесь остаётся только отступ ступеней третьего уровня для случая,
   когда панель сложилась в один столбец */
.post__toc-3 { margin-left: var(--space-4); }
/* Отступ якорей задан один раз для всей страницы — `scroll-padding-top`
   на html. Отдельное правило для заголовков статьи убрано: два места
   для одного отступа однажды разойдутся */

/* Блок автора под статьёй. Фото слева, квалификация справа: имя без
   проверяемых фактов доверия не добавляет */
.author { display: flex; gap: var(--space-4); align-items: flex-start;
          margin: var(--space-6) 0; }
.author__photo { border-radius: var(--radius-full); flex: 0 0 auto; }
.author__name { margin: 0; font-weight: 600; }
.author__bio { margin: var(--space-2) 0 0; font-size: var(--text-sm);
               color: var(--color-ink-muted); max-width: 60ch; }

/* Шеринг: три ссылки, без виджетов и счётчиков */
.share { display: flex; flex-wrap: wrap; gap: var(--space-4);
         align-items: baseline; margin: var(--space-6) 0;
         font-family: var(--font-display); font-size: var(--text-sm); }
.share__label { color: var(--color-ink-muted); }

/* Картинки в статье: подпись под изображением, а не в атрибуте —
   её читают и человек, и модель */
.post__body figure { margin: var(--space-6) 0; }
.post__body figure img { width: 100%; height: auto; border: var(--border);
                         border-radius: var(--radius-md); }
.post__body figcaption { margin-top: var(--space-2);
                         font-family: var(--font-display);
                         font-size: var(--text-sm);
                         color: var(--color-ink-muted); }

/* Пара снимков рядом: один и тот же вопрос, заданный дважды, сравнивают
   глазами, а не листают. На телефоне всё равно друг под другом */
.post__shots { display: grid; gap: var(--space-4); margin: var(--space-6) 0; }
.post__shots figure { margin: 0; }
@media (min-width: 48rem) {
  .post__shots { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Разделы и метки блога. Разделы — навигация, метки — россыпь под
   списком: их больше и они сквозные */
.sections { display: flex; flex-wrap: wrap; gap: var(--space-4);
            margin: var(--space-5) 0; padding-bottom: var(--space-4);
            border-bottom: var(--border);
            font-family: var(--font-display); font-size: var(--text-sm); }
.posts__cat { font-family: var(--font-display); font-size: var(--text-xs);
              letter-spacing: 0.04em; text-transform: uppercase; }
.posts__list--tight { gap: var(--space-5); }

.tags { margin: var(--space-7) 0 0; padding-top: var(--space-5);
        border-top: var(--border); }
.tags__head { margin: 0 0 var(--space-3); font-family: var(--font-display);
              font-size: var(--text-xs); letter-spacing: 0.06em;
              text-transform: uppercase; color: var(--color-ink-muted); }
.tag { display: inline-flex; gap: var(--space-2); align-items: baseline;
       margin: 0 var(--space-2) var(--space-2) 0;
       padding: var(--space-1) var(--space-3);
       border: var(--border); border-radius: var(--radius-full);
       font-family: var(--font-display); font-size: var(--text-xs);
       text-decoration: none; }
.post__meta { display: flex; flex-wrap: wrap; gap: var(--space-2);
              align-items: baseline; margin: var(--space-3) 0 0; }

/* Соседние статьи под текстом */
.more { margin-top: var(--space-6); padding-top: var(--space-5);
        border-top: var(--border); }
.more__head { margin: 0 0 var(--space-3); font-family: var(--font-display);
              font-size: var(--text-xs); letter-spacing: 0.06em;
              text-transform: uppercase; color: var(--color-ink-muted); }
.more ul { list-style: none; margin: 0; padding: 0; display: grid;
           gap: var(--space-3); }

/* Страница автора */
.author-page .section__inner > * { max-width: 48rem; }
.author-page__top { display: flex; flex-wrap: wrap; gap: var(--space-6);
                    align-items: flex-start; margin-bottom: var(--space-7); }
.author-page__photo { border-radius: var(--radius-md); flex: 0 0 auto; }
.author-page__top > div { flex: 1 1 22rem; min-width: 0; }
.author-page__role { margin: 0 0 var(--space-4);
                     font-family: var(--font-display);
                     font-size: var(--text-sm); letter-spacing: 0.04em;
                     text-transform: uppercase; color: var(--color-ink-muted); }
.checkable { padding-left: var(--space-5); }
.checkable li { margin: var(--space-3) 0; max-width: 68ch; }

@media (max-width: 40rem) {
  .author-page__photo { width: 140px; height: 140px; }
  .author { flex-direction: column; }
}


/* Длинные пояснения на телефоне. Три-четыре строки серого текста под
   каждой таблицей — это половина экрана, которую на телефоне не читают,
   но пролистывают, теряя по дороге данные. Схлопываем до двух строк
   с многоточием; целиком читается по касанию. */
@media (max-width: 56.25rem) {
  .app-body .note:not(.note--open) {
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden;
  }
  /* Касание раскрывает: свойство переключает скрипт, добавляя класс */
  .app-body .note:not(.note--open) { cursor: pointer; }
  .app-body .note.note--open { cursor: auto; }
  /* Вводная строка экрана не схлопывается: это то, ради чего человек
     читает первые секунды, и прятать её значит прятать смысл экрана */
  .app-body .section-head__meta, .app-body .app-head__meta { -webkit-line-clamp: none; }
}

/* График числами вместо картинки — только на телефоне */
.trend-list { display: none; }
@media (max-width: 56.25rem) {
  .chart { display: none; }
  .trend-list { display: grid; gap: var(--space-3); list-style: none;
                margin: var(--space-5) 0 0; padding: 0; }
  .trend-list__row { display: grid;
                     grid-template-columns: minmax(0, 1fr) auto auto auto;
                     align-items: baseline; gap: var(--space-2) var(--space-3);
                     padding-bottom: var(--space-3); border-bottom: var(--border); }
  .trend-list__name { font-family: var(--font-display);
                      font-size: var(--text-sm); }
  .trend-list__was { font-family: var(--font-mono); font-size: var(--text-sm);
                     color: var(--color-ink-faint); }
  .trend-list__arrow { color: var(--color-ink-faint); }
  .trend-list__now { font-family: var(--font-mono); font-size: var(--text-md);
                     font-weight: var(--weight-medium); }
  .trend-list__row .delta { grid-column: 2 / -1; font-size: var(--text-xs); }
}

/* Точка состояния у названия ассистента. Цвет тот же, что у чисел:
   зелёная — называют часто, янтарная — через раз, красная — не называют
   вовсе. Слово рядом остаётся, поэтому человек, не различающий цвета,
   ничего не теряет: он просто откроет вкладку и прочтёт долю */
.dot { display: inline-block; width: 0.45rem; height: 0.45rem; flex: none;
       border-radius: var(--radius-full); margin-right: 0.45rem;
       vertical-align: 0.05em; background: var(--color-ink-faint); }
.dot--ok { background: var(--ok); }
.dot--warn { background: oklch(0.62 0.13 75); }
.dot--bad { background: var(--bad); }
.dot--flat { background: var(--color-line-strong); }

/* --- Таблица во весь экран ---------------------------------------------
   Накладка, в которую переносится таблица по кнопке «Expand».

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

   Разбор `rotate(90deg) translate(0, -100%)`: поворот вокруг левого
   верхнего угла уводит сцену влево за край, и сдвиг на собственную
   высоту (в её системе координат — до поворота) возвращает её на экран.
   Порядок именно такой: записанное правее применяется первым. */
.table-full { position: fixed; inset: 0; z-index: 200; overflow: hidden;
              background: var(--color-surface); }
body.is-table-full { overflow: hidden; }

.table-full__stage { display: flex; flex-direction: column;
                     width: 100%; height: 100%; }
.table-full--turned .table-full__stage {
  width: 100vh; height: 100vw;
  width: 100dvh; height: 100dvw;
  transform-origin: top left;
  transform: rotate(90deg) translate(0, -100%);
}

.table-full__bar { display: flex; justify-content: flex-end; flex: none;
                   padding: var(--space-2) var(--space-4);
                   border-bottom: var(--border); }
.table-full__close { min-height: 44px; padding: 0 var(--space-3);
                     border: 0; background: none; cursor: pointer;
                     font-family: var(--font-display); font-size: var(--text-sm);
                     color: var(--color-accent); }
.table-full__body { flex: 1; overflow: auto; padding: 0 var(--space-4) var(--space-4); }

/* В накладке места хватает: держать колонку с названием узкой и липкой
   больше незачем — ровно ради этого её и разворачивали */
.table-full__body .table-wrap { overflow: visible; background: none; }
.app-body .table-full__body .table-wrap th:first-child,
.app-body .table-full__body .table-wrap td:first-child {
  position: static; box-shadow: none; width: auto;
  min-width: 0; max-width: none; overflow-wrap: normal;
}
.app-body .table-full__body .table-wrap th,
.app-body .table-full__body .table-wrap td { font-size: var(--text-sm); }

/* --- Нижняя панель -----------------------------------------------------
   Только на телефоне. На широком экране есть боковая колонка, и вторая
   навигация там была бы лишней. */
.bottom-nav { display: none; }

@media (max-width: 56.25rem) {
  .bottom-nav {
    display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
    position: fixed; inset-inline: 0; bottom: 0; z-index: 55;
    background: var(--color-surface);
    border-top: var(--border);
    /* Запас под системную полосу жестов на iPhone: без него нижний ряд
       кнопок оказывается под ней и не нажимается */
    padding-bottom: env(safe-area-inset-bottom, 0);
    box-shadow: 0 -1px 3px oklch(0.19 0.0068 78 / 0.06);
  }
  .bottom-nav__item {
    display: flex; flex-direction: column; align-items: center;
    justify-content: center; gap: 0.15rem;
    min-height: 56px; padding: var(--space-2) 0;
    border: 0; background: none; cursor: pointer;
    font-family: var(--font-display); color: var(--color-ink-muted);
  }
  .bottom-nav__item .icon { width: 1.25rem; height: 1.25rem; }
  .bottom-nav__label { font-size: 0.68rem; line-height: 1; }
  .bottom-nav__item:hover { color: var(--color-ink); }
  /* Текущий раздел: цвет и черта сверху — та же отметка, что в боковом
     меню на широком экране */
  .bottom-nav__item[aria-current="page"] { color: var(--color-accent); }
  .bottom-nav__item[aria-current="page"]::before {
    content: ""; position: absolute; top: 0; width: 2.5rem; height: 2px;
    background: var(--color-accent);
  }
  .bottom-nav__item { position: relative; }

  /* Место под панель, иначе она закрывает последнюю строку страницы */
  .app-body main { padding-bottom: 4.5rem; }
  /* Раскрытое меню идёт поверх панели */
  .js .app-side[data-menu="open"] .app-side__inner { z-index: 60; }
}

/* =====================================================================
   Телефон: правила, которые обязаны выигрывать у всех предыдущих.
   Стоят в конце файла намеренно — у `.report-build select` и
   `.review__row input` та же весомость селектора, и побеждает то,
   что объявлено позже.
   ===================================================================== */

/* На телефоне поле обязано быть не мельче 16 пикселей. Safari на iOS
   увеличивает всю страницу при касании поля со шрифтом меньше 16 —
   и обратно сам не возвращает: человек остаётся на зумнутой странице
   и дальше ездит по ней пальцем. Это не предпочтение, а правило
   платформы, поэтому размер зашит числом, а не токеном.

   Заодно цели нажатия доводятся до 44 точек: промах мимо ссылки
   на телефоне раздражает сильнее всего остального. */
@media (max-width: 56.25rem) {
  .app-body input, .app-body textarea, .app-body select,
  .app-body .review__row input[type="text"], .app-body .review__row select,
  .app-body .report-build select, .app-body .link-form select,
  .app-body .field input, .app-body .field textarea { font-size: 16px; }
  .app-body .button { min-height: 44px; padding-top: 0.7rem; padding-bottom: 0.7rem; }
  .app-body .button--quiet { min-height: 44px; }
  /* Ссылки внутри строк текста не трогаем — они часть предложения,
     и растянуть их значит сломать абзац. Увеличиваем те, что стоят
     сами по себе: пункты меню, фильтры, вкладки, действия в карточках */
  .app-body .filters__set a, .app-body .engine-tabs a, .app-body .pill,
  .app-body .app-staff__nav a, .app-body .side__list a,
  .app-body .more__list a, .app-body .cards__due a, .app-body .today-link a {
    min-height: 44px; display: inline-flex; align-items: center;
  }
  .app-body .app-side__sub a, .app-body .app-side__nav > a,
  .app-body .app-side__group > a { min-height: 44px; }
}



/* ─────────────────────────────────────────────────────────────────────
   Плавающие кнопки: наверх и связаться

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

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

.floaty {
  /* Видимый кружок — 2.5rem, но нажимается область в 44 точки:
     прозрачная рамка добирает недостающее, не раздувая сам кружок */
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.5rem; height: 2.5rem; padding: 0;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-full);
  background: var(--color-surface);
  color: var(--color-ink-muted);
  cursor: pointer;
  box-shadow: 0 1px 3px oklch(0.19 0.0068 78 / 0.07);
  transition: color var(--duration) var(--ease),
              border-color var(--duration) var(--ease),
              background var(--duration) var(--ease),
              transform var(--duration) var(--ease);
}
.floaty .icon { width: 1.05rem; height: 1.05rem; }
.floaty:hover { color: var(--color-ink); border-color: var(--color-line-strong);
                background: var(--color-surface-raised); }
.floaty:active { transform: translateY(1px); }
.floaty:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* Положение. `env(safe-area-inset-*)` — запас под полосу жестов
   и скруглённые углы на телефонах, иначе кнопка оказывается под ними */
.floaty--up {
  position: fixed; z-index: 60;
  left: calc(var(--space-5) + env(safe-area-inset-left, 0px));
  bottom: calc(var(--space-5) + env(safe-area-inset-bottom, 0px));
}
.floaty-reach {
  position: fixed; z-index: 60;
  right: calc(var(--space-5) + env(safe-area-inset-right, 0px));
  bottom: calc(var(--space-5) + env(safe-area-inset-bottom, 0px));
  /* В столбик, а не в ряд: так пара занимает по ширине ровно одну
     кнопку и меньше закрывает текст на узком экране */
  display: flex; flex-direction: column; gap: var(--space-2);
}

/* WhatsApp узнают по цвету больше, чем по значку. Зелёный берём
   приглушённый и только на наведение: ровный зелёный кружок поверх
   страницы спорил бы со всем остальным */
.floaty--wa:hover { color: oklch(0.55 0.13 155); border-color: oklch(0.72 0.08 155); }

/* Кнопка «наверх» живёт по кнопке скрипта: до первой прокрутки
   возвращаться некуда, и кнопка была бы обещанием ни о чём.
   Без скрипта её нет вовсе — атрибут `hidden` стоит в разметке */
.floaty--up { opacity: 0; visibility: hidden;
              transform: translateY(0.5rem);
              transition: opacity var(--duration) var(--ease),
                          visibility var(--duration) var(--ease),
                          transform var(--duration) var(--ease); }
.floaty--up.is-shown { opacity: 1; visibility: visible; transform: none; }

@media (max-width: 40rem) {
  /* На телефоне кнопки ещё тише: экран маленький, и каждая точка,
     закрытая кружком, — это закрытая строка текста */
  .floaty { width: 2.25rem; height: 2.25rem; }
  .floaty .icon { width: 0.95rem; height: 0.95rem; }
  .floaty--up { left: calc(var(--space-4) + env(safe-area-inset-left, 0px));
                bottom: calc(var(--space-4) + env(safe-area-inset-bottom, 0px)); }
  .floaty-reach { right: calc(var(--space-4) + env(safe-area-inset-right, 0px));
                  bottom: calc(var(--space-4) + env(safe-area-inset-bottom, 0px)); }
}

/* Кнопки связи уходят, когда виден подвал: там те же почта и WhatsApp,
   подписанные словами. Класс ставит скрипт */
.floaty-reach { transition: opacity var(--duration) var(--ease),
                            visibility var(--duration) var(--ease); }
.floaty-reach.is-hidden { opacity: 0; visibility: hidden; }

@media print { .floaty, .floaty-reach { display: none; } }
