/* Karivox — оформление.
   Один файл на весь сайт и на админку. Цвета живут в переменных, поэтому
   тёмная тема — это переопределение полутора десятков строк, а не второй
   набор правил. CSP запрещает внешние шрифты, поэтому системный стек. */

:root {
  --синий:        #4657D6;
  --синий-тёмный: #3644B4;
  --синий-свет:   #EEF0FE;
  --графит:       #171A21;

  --фон:          #FBFBFD;
  --фон-2:        #FFFFFF;
  --фон-3:        #F2F3F7;
  --текст:        #171A21;
  --текст-2:      #5B6072;
  --текст-3:      #8A8FA3;
  --край:         #E3E5EC;
  --край-2:       #CFD2DE;

  --зелёный:      #1F9D63;
  --зелёный-фон:  #E8F6EF;
  --жёлтый:       #B37A00;
  --жёлтый-фон:   #FDF3DF;
  --красный:      #C8372D;
  --красный-фон:  #FCECEA;
  --серый-фон:    #F0F1F5;

  --тень:    0 1px 2px rgba(23,26,33,.06), 0 4px 16px rgba(23,26,33,.05);
  --тень-2:  0 8px 40px rgba(23,26,33,.14);
  --радиус:  14px;
  --радиус-с: 9px;

  /* Настоящую высоту липкой шапки меряет `подогнать_меню()` и пишет сюда
     же, поверх этого значения. Число здесь — запасное, на те секунды, пока
     app.js едет по мобильной сети, и на случай, если он не доедет вовсе.
     Зашивать его насовсем нельзя: на телефоне шапка другой высоты, а от
     этой величины зависит, спрячется ли заголовок раздела за шапкой. */
  --высота-шапки: 71px;

  --шрифт: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
           "Helvetica Neue", Arial, "Noto Sans", sans-serif;
  --моно: ui-monospace, SFMono-Regular, "SF Mono", Consolas,
          "Liberation Mono", monospace;
}

html[data-тема="тёмная"] {
  --синий:        #7A88F0;
  --синий-тёмный: #94A0F5;
  --синий-свет:   #1E2340;
  --графит:       #F2F3F7;

  --фон:          #101218;
  --фон-2:        #171A21;
  --фон-3:        #1E222C;
  --текст:        #ECEEF4;
  --текст-2:      #A2A8BC;
  --текст-3:      #757C92;
  --край:         #272C38;
  --край-2:       #363C4C;

  --зелёный:      #4ECB8E;
  --зелёный-фон:  #14301F;
  --жёлтый:       #E0A93A;
  --жёлтый-фон:   #332711;
  --красный:      #F0736A;
  --красный-фон:  #34181A;
  --серый-фон:    #1E222C;

  --тень:   0 1px 2px rgba(0,0,0,.4), 0 4px 16px rgba(0,0,0,.3);
  --тень-2: 0 8px 40px rgba(0,0,0,.55);
}

* { box-sizing: border-box; }

html, body {
  margin: 0; padding: 0;
  background: var(--фон);
  color: var(--текст);
  font-family: var(--шрифт);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

body.без-прокрутки { overflow: hidden; }

/* ── ПРОКРУТКА ПО ЯКОРЯМ: ЧЕЛОВЕК ДОЛЖЕН ВИДЕТЬ, КУДА ПРИЕХАЛ ────────
   Владелец: «нажал, оно перекрутилось, потом начинаешь пытаться прокрутить
   наверх, перекручиваешь, и хрен поймёшь, где ты находишься». Две причины
   лечатся здесь, третья — в js.

   ПЕРВАЯ. Шапка липкая и накрывает семьдесят с лишним точек сверху, а
   отступа под неё у разделов не было вовсе. Раздел вставал вплотную к
   верху окна, и его собственный заголовок оказывался ЗА шапкой: человек
   приезжал ровно туда, куда просил, и не видел ни одного слова, которое
   сказало бы ему об этом. Отступ берётся от НАСТОЯЩЕЙ высоты шапки
   (`--высота-шапки`, меряет `подогнать_меню()`), а не от зашитого числа:
   на телефоне шапка ниже, и лишние двадцать точек пустоты там так же
   заметны, как их нехватка на широком экране.

   `scroll-padding-top` у страницы и `scroll-margin-top` у самих разделов —
   не дубль: первое ловит переход по ссылке и по клавише, второе работает и
   для `scrollIntoView()`, который у нас зовётся из js в семи местах.

   ВТОРАЯ. Прокрутка была мгновенной: страница телепортировалась, и глаз не
   успевал понять, вверх уехали или вниз. Плавная даёт направление. Но
   плавность вредна тем, кому она вредна: `prefers-reduced-motion` — это не
   вкус, а вестибулярное расстройство, и системную настройку мы уважаем
   молча, не спрашивая. */
html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--высота-шапки) + 14px);
}
section[id], [id="top"] {
  scroll-margin-top: calc(var(--высота-шапки) + 14px);
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

a { color: var(--синий); text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3, h4 { line-height: 1.2; margin: 0 0 .5em; letter-spacing: -.02em; }
h1 { font-size: 2.9rem; font-weight: 750; }
h2 { font-size: 1.85rem; font-weight: 700; }
h3 { font-size: 1.18rem; font-weight: 650; }
p  { margin: 0 0 1em; }

.обёртка { max-width: 1140px; margin: 0 auto; padding: 0 24px; }
.узко    { max-width: 780px; margin: 0 auto; padding: 0 24px; }

/* ── шапка ─────────────────────────────────────────────────────────── */

/* Шапке даём больше ширины, чем тексту: в ней соревнуются за место логотип,
   шесть пунктов меню и четыре элемента справа. Текст страницы при этом
   остаётся в 1140 — читать длинные строки тяжело. */
header.верх .обёртка { max-width: 1340px; }

header.верх {
  /* `top` — не 0, а высота красной полосы (0, пока она скрыта). Полоса и
     шапка обе `position: sticky; top: …`, и без этого сдвига обе целились
     бы в одну и ту же строку экрана — шапка легла бы поверх полосы или под
     ней внахлёст, в зависимости от порядка отрисовки. `--полоса-высота`
     ставит `обновить_высоту_полосы()` в app.js, ЖИВЫМ ЗАМЕРОМ, а не числом
     в css: у нас 42 языка, и то, что по-английски одна строка, по-немецки
     две — высоту полосы заранее не знает никто. */
  position: sticky; top: var(--полоса-высота, 0px); z-index: 40;
  background: color-mix(in srgb, var(--фон) 88%, transparent);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--край);
}
.верх .ряд {
  display: flex; align-items: center; gap: 0;
  height: 70px;
}
.знак { display: flex; align-items: center; gap: 10px; flex: 0 0 auto; }
.знак img { width: 34px; height: 34px; display: block; }
.знак b { font-size: 1.22rem; font-weight: 700; letter-spacing: -.03em; color: var(--текст); }
.знак:hover { text-decoration: none; }

/* Меню.

   Две ошибки были здесь одновременно, и обе видны только на длинных языках.

   Первая: пункты — flex-элементы, у них по умолчанию flex-shrink: 1. Когда
   французского текста становится больше, пункты сжимались уже своей ширины,
   а nowrap не давал тексту переноситься — он просто вылезал за границы блока
   и наезжал на выбор языка.

   Вторая: position: relative на ссылке поднимает её над статичным соседом.
   Даже если бы блок не переполнялся, текст меню рисовался бы ПОВЕРХ правой
   части шапки.

   Теперь: пункты не сжимаются никогда, меню обрезает лишнее вместо наезда,
   правая часть лежит выше по стеку, а js прячет меню целиком, если оно
   не помещается — обрезанный наполовину пункт не лучше наехавшего. */
nav.меню {
  display: flex; gap: 2px; margin-inline-start: 20px;
  flex: 0 1 auto; min-width: 0; overflow: hidden;
}
nav.меню.спрятано { display: none; }
nav.меню a {
  flex: 0 0 auto;
  color: var(--текст-2); font-size: .9rem; font-weight: 500;
  padding: 8px 12px; border-radius: 8px;
  white-space: nowrap; position: relative;
}
nav.меню a:hover { background: var(--фон-3); color: var(--текст); text-decoration: none; }

/* «ТЫ ЗДЕСЬ». Восемь одинаковых слов в шапке, и ни одно не говорило, в
   каком разделе человек стоит: прокрутил — и потерялся. Отмечает текущий
   пункт `следить_за_разделами()` через IntersectionObserver; слушать
   прокрутку на каждый пиксель для этого нельзя — на телефоне это событий
   по шестьдесят в секунду ради одного класса.

   Отметка — цвет и подчёркивание снизу, а не фон: фон здесь уже занят
   наведением, и два разных смысла одной краской человек не различает. */
nav.меню a.тут { color: var(--текст); font-weight: 650; }
nav.меню a.тут::after {
  content: ""; position: absolute; left: 12px; right: 12px; bottom: 3px;
  height: 2px; border-radius: 2px; background: var(--синий);
}
.меню-панель a.тут { color: var(--синий); font-weight: 650; }

.верх-справа {
  display: flex; align-items: center; gap: 8px;
  flex: 0 0 auto; margin-inline-start: auto; padding-inline-start: 16px;
  position: relative; z-index: 3;
  background: transparent;
}

/* Компактное меню: появляется ровно тогда, когда полное не помещается.

   Имя класса приходится удваивать: у кнопки есть и .иконка-кнопка, и
   .меню-кнопка, вес у них одинаковый, а .иконка-кнопка со своим
   display: inline-flex стоит ниже по файлу — и побеждала. Гамбургер из-за
   этого висел в шапке всегда, даже рядом с полным меню, и вдобавок съедал
   свои сорок шесть пикселей из замера, из-за чего полное меню пряталось
   раньше, чем на самом деле переставало помещаться. */
.иконка-кнопка.меню-кнопка { display: none; }
.иконка-кнопка.меню-кнопка.видна { display: inline-flex; }

/* Тесная шапка.

   На телефоне правая часть требовала места больше, чем есть у всей строки:
   «Войти» и «Начать» вместе с выбором языка и гамбургером не помещаются в
   320 пикселей никаким подбором отступов. А правая часть не сжимается
   (flex: 0 0 auto) — и вместо того, чтобы сжаться, она вылезала за экран.
   Оттуда же уезжала и панель: она привязана к правому краю правой части
   (right: 0), а этот край был метров за двести правее видимой страницы.
   Отсюда и горизонтальная прокрутка, и «открывается сильно справа».

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

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

   Класс стоит прямо в разметке, а не только вешается из js: пока js едет по
   мобильной сети, шапка уже нарисована, и нарисована должна быть та, которая
   заведомо помещается. Подробности — в комментарии у шапки в index.html. */
.верх-справа.тесно > .кнопка { display: none; }

.меню-панель {
  position: absolute; top: calc(100% + 8px); inset-inline-end: 0;
  background: var(--фон-2); border: 1px solid var(--край);
  border-radius: 12px; box-shadow: var(--тень-2);
  padding: 8px; min-width: 220px; z-index: 60;
  display: flex; flex-direction: column; gap: 2px;
  /* Панель растёт влево от правого края. Без потолка длинное немецкое или
     греческое слово вытолкнуло бы её левый край за нулевую координату, а
     туда страница не прокручивается — пункт просто стал бы недостижим.

     Потолок меряется не в vw. На мобильных браузерах 100vw — это ширина
     вместе с полосой прокрутки, и она не дрожит вместе с адресной строкой
     только потому, что вообще не следит за видимой частью: величина берётся
     из макета, а не из того, что человек видит. --ширина-экрана ставит js
     из document.documentElement.clientWidth на каждый замер шапки, то есть
     из настоящей ширины страницы. 100vw остаётся запасным значением на тот
     случай, если разметка успела отрисоваться раньше первого замера. */
  max-width: calc(var(--ширина-экрана, 100vw) - 40px);
}
.меню-панель a {
  color: var(--текст); font-size: .95rem; font-weight: 500;
  padding: 10px 12px; border-radius: 8px;
  /* Переносить, а не резать: пункт в две строки читается, обрезанный — нет. */
  white-space: normal; overflow-wrap: anywhere;
}
.меню-панель a:hover { background: var(--фон-3); text-decoration: none; }

/* Черта отделяет действия аккаунта от пунктов страницы: в тесной шапке
   в одном списке оказывается и то, и другое. */
.меню-панель hr.разделитель {
  border: 0; border-top: 1px solid var(--край);
  margin: 6px 4px;
}

/* ── кнопки ────────────────────────────────────────────────────────── */

.кнопка {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font: inherit; font-weight: 600; font-size: .95rem;
  padding: 10px 20px; border-radius: var(--радиус-с);
  border: 1px solid transparent; cursor: pointer;
  background: var(--синий); color: #fff;
  transition: filter .12s, background .12s, border-color .12s;
  white-space: nowrap;
}
.кнопка:hover { filter: brightness(1.08); text-decoration: none; }
.кнопка:active { filter: brightness(.95); }
.кнопка[disabled] { opacity: .5; cursor: not-allowed; filter: none; }

.кнопка.тихая { background: transparent; color: var(--текст); border-color: var(--край-2); }
.кнопка.тихая:hover { background: var(--фон-3); filter: none; }
.кнопка.призрак { background: transparent; color: var(--текст-2); border-color: transparent; }
.кнопка.призрак:hover { background: var(--фон-3); color: var(--текст); }
.кнопка.опасная { background: var(--красный); }
.кнопка.мелкая { padding: 6px 12px; font-size: .85rem; }
.кнопка.крупная { padding: 14px 30px; font-size: 1.05rem; }
.кнопка.широкая { width: 100%; }

.иконка-кнопка {
  width: 38px; height: 38px; padding: 0; border-radius: 9px;
  background: transparent; border: 1px solid var(--край);
  color: var(--текст-2); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 1.05rem;
}
.иконка-кнопка:hover { background: var(--фон-3); color: var(--текст); }

/* ── поля ──────────────────────────────────────────────────────────── */

label.поле { display: block; margin-bottom: 14px; }
label.поле > span {
  display: block; font-size: .84rem; font-weight: 600;
  color: var(--текст-2); margin-bottom: 6px;
}
input[type=text], input[type=email], input[type=password],
input[type=number], select, textarea {
  width: 100%; font: inherit; font-size: .95rem;
  padding: 10px 13px; border-radius: var(--радиус-с);
  border: 1px solid var(--край-2); background: var(--фон-2);
  color: var(--текст); outline: none;
  transition: border-color .12s, box-shadow .12s;
}
input:focus, select:focus, textarea:focus {
  border-color: var(--синий);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--синий) 22%, transparent);
}
textarea { resize: vertical; min-height: 110px; line-height: 1.55; }
select { cursor: pointer; }
.подсказка { font-size: .82rem; color: var(--текст-3); margin-top: 5px; }

/* Ширина у выбора языка постоянная, а не по содержимому.

   Список языков приезжает с сервера, и до его приезда пустой select занимает
   63 точки вместо своих 120. Разница в 57 точек попадала прямо в замер шапки:
   на 430 точках он успевал решить, что «Войти» и «Начать» помещаются, показать
   их — и через полсекунды, когда языки доехали, убрать обратно. Кнопки прыгали
   на ровном месте. Постоянная ширина место под список резервирует сразу, и
   замер получается один и тот же до и после загрузки.

   Числа те же, что были в max-width: самое длинное название — «Chinese
   (Traditional)» — и так упиралось в потолок, так что на вид ничего
   не меняется. */
.выбор-языка {
  padding: 8px 30px 8px 11px; font-size: .875rem;
  width: 152px; min-width: 152px; max-width: 152px;
  border-color: var(--край); background: var(--фон-2);
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--текст-3) 50%),
                    linear-gradient(135deg, var(--текст-3) 50%, transparent 50%);
  background-position: calc(100% - 16px) 52%, calc(100% - 11px) 52%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}

/* ── карточки и блоки ──────────────────────────────────────────────── */

.карта {
  background: var(--фон-2); border: 1px solid var(--край);
  border-radius: var(--радиус); padding: 24px; box-shadow: var(--тень);
}
.карта + .карта { margin-top: 18px; }
/* ...но не внутри сетки: там расстояние задаёт gap, а margin-top съезжал бы
   на вторую и третью карточку и ронял всё выравнивание по горизонтали.
   Именно из-за этого тарифы стояли лесенкой. */
.сетка > .карта + .карта { margin-top: 0; }

section { padding: 76px 0; }
section.плотно { padding: 46px 0; }
.заголовок-раздела { text-align: center; max-width: 660px; margin: 0 auto 42px; }
.заголовок-раздела p { color: var(--текст-2); font-size: 1.06rem; margin: 0; }

/* Строка под четырьмя шагами: как мы считаем ВСЕГДА, у всякой стратегии.
   Стоит отдельно, а не мелким шрифтом внутри карточки, потому что это не
   уточнение к третьему шагу, а условие всей проверки. */
.как-срез {
  max-width: 660px; margin: 26px auto 0; text-align: center;
  color: var(--текст-2); font-size: 1.02rem;
}

.сетка { display: grid; gap: 18px; }
.сетка.к3 { grid-template-columns: repeat(3, 1fr); }
.сетка.к4 { grid-template-columns: repeat(4, 1fr); }
.сетка.к2 { grid-template-columns: repeat(2, 1fr); }

.метка {
  display: inline-block; font-size: .74rem; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase;
  padding: 4px 10px; border-radius: 20px;
  background: var(--синий-свет); color: var(--синий);
}
.метка.зелёная { background: var(--зелёный-фон); color: var(--зелёный); }
.метка.жёлтая  { background: var(--жёлтый-фон);  color: var(--жёлтый); }
.метка.красная { background: var(--красный-фон); color: var(--красный); }
.метка.серая   { background: var(--серый-фон);   color: var(--текст-2); }

/* ── первый экран ──────────────────────────────────────────────────── */

.экран {
  padding: 84px 0 68px;
  background:
    radial-gradient(760px 420px at 14% -8%,
      color-mix(in srgb, var(--синий) 15%, transparent), transparent 68%),
    radial-gradient(620px 380px at 92% 4%,
      color-mix(in srgb, var(--синий) 9%, transparent), transparent 64%);
}
/* Заголовок в две части: что мы делаем и что человек получает, если
   получилось. Вторая строка — самое сильное в предложении, поэтому она
   вынесена цветом, а не спрятана абзацем ниже. */
.экран h1 { max-width: 17ch; }
.экран h1 .h1-акцент {
  display: block; color: var(--зелёный); margin-top: .12em;
}
.экран .лид {
  font-size: 1.22rem; color: var(--текст-2);
  max-width: 56ch; margin-bottom: 30px;
}
/* Первый экран собран ОБЛАСТЯМИ, а не порядком в разметке, и это не
   украшательство. На широком экране обещание бесплатного бота стоит справа
   вверху, в одном ряду с заголовком: это единственное, чем мы отличаемся от
   всех остальных, и человек обязан увидеть его не прокручивая. На телефоне
   колонок нет, и там оно должно встать между лидом и кнопками — то есть
   МЕЖДУ двумя кусками левой колонки. Порядком в разметке так не выйдет ни
   при каком расположении блоков; областями — выходит, и обе раскладки
   получаются из одной разметки.

   `align-items: start` — чтобы правая колонка держалась верха, а не
   всплывала к середине двух строк левой. */
.экран-сетка {
  display: grid;
  grid-template-columns: 1.05fr .95fr;
  grid-template-areas: "текст справа" "низ справа";
  gap: 0 54px; align-items: start;
}
.экран-текст  { grid-area: текст; }
.экран-справа { grid-area: справа; }
.экран-низ    { grid-area: низ; }
.кнопки-ряд { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; }

.цифры { display: flex; gap: 34px; margin-top: 40px; flex-wrap: wrap; }
.цифры div b {
  display: block; font-size: 1.75rem; font-weight: 700;
  letter-spacing: -.03em; color: var(--текст);
}
.цифры div span { font-size: .85rem; color: var(--текст-3); }

/* Нарисованной карточки отчёта на первом экране БОЛЬШЕ НЕТ, и правила её
   оформления (`.проба`) убраны вместе с ней 05.09.2026. Она показывала
   выдуманные числа под видом отчёта; владелец: «она бессмысленная… не надо,
   чтобы никаких картинок на сайте было». `.строка-отчёта` при этом осталась
   — её собирает `факт()` в admin.js, и она живёт в панели, а не на витрине. */
.строка-отчёта {
  display: flex; justify-content: space-between; align-items: center;
  padding: 9px 0; border-bottom: 1px dashed var(--край);
  font-size: .9rem;
}
.строка-отчёта:last-child { border-bottom: 0; }
.строка-отчёта b { font-variant-numeric: tabular-nums; }

/* ── шаги ──────────────────────────────────────────────────────────── */

.шаг { position: relative; padding-inline-start: 54px; }
.шаг .номер {
  position: absolute; inset-inline-start: 0; top: 0;
  width: 38px; height: 38px; border-radius: 11px;
  background: var(--синий); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 1.02rem;
}
.шаг p { color: var(--текст-2); margin: 0; font-size: .95rem; }

/* ── тарифы ────────────────────────────────────────────────────────── */

/* Карточки тарифов выровнены по горизонтали: у всех одинаковые ряды —
   место под плашку, название, цена, подпись, список, кнопка. Каждый ряд
   фиксированной высоты, поэтому названия стоят на одной линии, цены на одной,
   и все галочки тоже. Раньше плашка «Most chosen» была только у Pro и
   сдвигала его колонку вниз относительно соседних. */
.тариф { display: flex; flex-direction: column; }
.тариф.главный { border-color: var(--синий); box-shadow: 0 0 0 1px var(--синий), var(--тень); }

.тариф .место-метки {
  min-height: 28px; margin-bottom: 10px;
  display: flex; align-items: flex-start;
}
.тариф h3 { min-height: 1.4em; margin-bottom: 0; }
.тариф .цена {
  font-size: 2.5rem; font-weight: 750; letter-spacing: -.04em;
  margin: 6px 0 2px; min-height: 1.15em; display: flex; align-items: baseline; gap: 6px;
}
.тариф .цена small { font-size: .95rem; font-weight: 500; color: var(--текст-3); }
/* подпись держит две строки: проверки и разборы */
.тариф > .подсказка { min-height: 3.1em; }
.тариф ul { list-style: none; padding: 0; margin: 14px 0 22px; flex: 1 1 auto; }
.тариф ul li {
  padding: 7px 0; padding-inline-start: 26px; position: relative;
  font-size: .93rem; color: var(--текст-2);
}
.тариф ul li::before {
  content: "✓"; position: absolute; inset-inline-start: 0; top: 7px;
  color: var(--зелёный); font-weight: 700;
}
.тариф ul li.нет::before { content: "—"; color: var(--текст-3); }

/* ── таблицы ───────────────────────────────────────────────────────── */

/* НИ ОДНА ТАБЛИЦА САЙТА НЕ ЕЗДИТ ВПРАВО-ВЛЕВО. ЭТО ЗАПРЕТ.
   ────────────────────────────────────────────────────────
   Владелец, увидев полосу в таблице счетов проп-фирмы:

     «scroll bar, который вправо-влево, его не должно никогда ни на
      каких таблицах выходить»

   Это третий заход на одну и ту же болезнь. Первые два лечили по одной
   таблице: сначала список «Your checks», потом — нет, потом снова. Каждый
   раз оставалось «а вот у этой колонок сколько придётся, ей можно».
   Оправдание всегда звучало разумно и всегда оказывалось неверным: колонок
   «сколько придётся» не бывает — бывает вёрстка, которая не умещает.

   Поэтому у обёртки БОЛЬШЕ НЕТ `overflow-x`, ни здесь, ни где-либо ещё, и
   разрешающего класса, которым таблицу можно было «пометить как хорошую»,
   тоже нет. Разрешение переехало в запрет: боковая прокрутка недоступна по
   умолчанию, и вернуть её отдельной таблице нечем.

   ЧТО УМЕЩАЕТ ВМЕСТО ПРОКРУТКИ. Прокрутка не умещает ничего — она прячет
   остаток за краем. Умещают три вещи, и каждая ниже в этом файле со своим
   разбором:

     * заголовки колонок переносятся по словам (`table.данные th`) — из-за
       них таблица MyFundedFutures просила 1131 точку при карточке в 1042:
       один заголовок «ATAS / DeepChart / NinjaTrader / Quantower /
       TradingView / Tradovate / Volumetrica» в одну строку это 626 точек;
     * имя счёта стоит в две строки (`клетка-счёт`) вместо одной в 239;
     * скидка ушла в короткий знак с всплывающей подсказкой (`.скидка`)
       вместо строки «up to 90% off with SAVENOW, until 2026-09-08 23:59»
       в 337 точек, которая и распирала колонку цены.

   Сторожит это `проверка_витрины.py`, проверка «БОКОВОЙ ПРОКРУТКИ НЕТ
   НИГДЕ»: она ищет `overflow-x: auto|scroll` во ВСЕХ файлах витрины —
   в css, в разметке, в стилях, которые ставит js, — и краснеет на каждом
   найденном, кроме перечисленных там же исключений с причиной у каждого.
   Список исключений в проверке, а не здесь: список таблиц устареет,
   признак — нет. */
.таблица-обёртка { border-radius: var(--радиус); }
table.данные {
  width: 100%; border-collapse: collapse; font-size: .9rem;
  background: var(--фон-2);
}
table.данные th, table.данные td {
  padding: 11px 14px; text-align: start;
  border-bottom: 1px solid var(--край);
  white-space: nowrap;
}
/* ЗАГОЛОВОК КОЛОНКИ ПЕРЕНОСИТСЯ ПО СЛОВАМ, А ЧИСЛО ПОД НИМ — НЕТ.

   Общий `nowrap` строчкой выше верен для клеток: разорванное «$-19,659»
   читается хуже целого. Для шапки он неверен, и вот чем это стоило.
   Колонка площадок подписана их перечислением, а перечисление приходит из
   данных фирмы: у MyFundedFutures это семь имён через косую черту, 626
   точек в одну строку. Ни одно число в таблице столько не занимает, и
   именно подпись, а не данные, выгоняла таблицу за карточку.

   Перенос по словам ломает такую строку по пробелам вокруг косых черт и
   стоит двух-трёх лишних строк в шапке — один раз на таблицу, а не на
   каждую из двадцати четырёх строк. Заодно чинятся «Daily loss» и «Passes
   from this share of start dates» на всех сорока одном языке сразу, а не
   только там, где мы догадались подрезать слово. */
table.данные th {
  font-size: .74rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--текст-3); background: var(--фон-3);
  white-space: normal;
}
/* Заголовок числовой колонки обязан стоять над числами, а не над пустотой:
   числа прижаты вправо, значит и подпись прижата вправо. */
table.данные th.число,
table.данные td.число { text-align: end; font-variant-numeric: tabular-nums; }
table.данные tbody td { color: var(--текст); }
table.данные tbody tr:nth-child(even) {
  background: color-mix(in srgb, var(--фон-3) 45%, transparent);
}
table.данные tbody tr:nth-child(even):hover { background: var(--фон-3); }
table.данные tbody tr:hover { background: var(--фон-3); }
table.данные tr:last-child td { border-bottom: 0; }

/* КЛЕТКИ С ФРАЗОЙ, А НЕ С ЧИСЛОМ, ПЕРЕНОСЯТСЯ ПО СЛОВАМ.

   Общее `white-space: nowrap` выше держит в одну строку числа, и там это
   верно: разорванное «$-19,659» читается хуже целого. Но две клетки
   таблицы рынков несут не число, а фразу — глубину истории («ES · minute
   data · 18 years · from 2008-01-11») и сам вердикт («It lost money on
   this history»). На них таблица разъезжалась до 1087 точек при карточке
   около девятисот, обёртка включала боковую прокрутку, и последняя
   колонка уезжала за правый край. Владелец видел на экране «IT LOST MONE»
   — обрезанный вердикт, то есть ровно то единственное, что он в таблице
   и искал.

   Перенос по словам чинит это на всех сорока двух языках сразу; подгонка
   ширин чинила бы только на английском, а самые длинные подписи у нас на
   сомалийском и тамильском. */
table.данные td.клетка-фраза { white-space: normal; }
table.данные td.клетка-фраза .метка { white-space: normal; }

/* ── ИМЯ СЧЁТА В ДВЕ СТРОКИ ─────────────────────────────────────────

   «NoActivationFee 25K Intraday» в одну строку — 239 точек, и стоит она в
   каждой из двадцати семи строк таблицы счетов. Владелец: «названия счетов
   нужно разделить на две строчки. И уже скролить вправо-влево так много не
   надо».

   Делится имя НЕ ЗДЕСЬ и не по пробелам: части приходят с сервера
   разобранными по ключу счёта («25000|RealTime|NoActivationFee»), потому
   что линейка бывает из нескольких слов — «Fast Track», — и разрез по
   пробелу попал бы в её середину. Дело css только в том, чтобы части
   встали друг под друга. */
table.данные td.клетка-счёт b { display: block; }
table.данные td.клетка-счёт b span { display: block; }
/* Вторая строка — размер и тип просадки — вторична по смыслу: линейку
   человек ищет глазами, размер читает следом. */
table.данные td.клетка-счёт b span + span {
  font-weight: 400; color: var(--текст-2);
}

/* ── КНОПКА «i»: ЧТО ЭТО ТАКОЕ ──────────────────────────────────────

   Владелец о таблице рынков: «поставь ты B6 маленькую кнопочку I, на
   которую можно навести, чтобы всплыло „British Pound Futures“ ... но так,
   чтобы это не занимало место в таблице целой строчкой».

   ОДИН КОМПОНЕНТ НА ДВА МЕСТА, и оба — про ширину. В таблице рынков в
   значок ушло полное имя контракта (271 точка из 874, треть таблицы); в
   таблице счетов — строка скидки под ценой («up to 90% off with SAVENOW,
   until 2026-09-08 23:59», 337 точек в КАЖДОЙ строке).

   ПОЧЕМУ ПОДСКАЗКА НЕ РАЗДВИГАЕТ ТАБЛИЦУ. `position: absolute` внутри
   самого значка — то есть вынута из потока. Клетка меряется по значку в
   15 точек, а не по тексту в 337. Ни ширины, ни высоты строки подсказка не
   меняет вовсе, и ради неё таблица не поедет вбок никогда.

   ПОЧЕМУ `display: none`, А НЕ `visibility: hidden`. Сначала было
   `visibility` — ради того, чтобы подсказку можно было измерить до показа
   (на этом держится разворот у края). Замер на стенде показал, чем это
   стоило: скрытая через `visibility` подсказка ЗАНИМАЕТ МЕСТО в раскладке,
   и на 375 точках таблица счетов просила 451 при карточке в 294, а
   страница ездила вбок на 116 точек — при том что ни одна подсказка не
   была открыта. То есть лекарство от боковой прокрутки само её и давало.

   Мерить при этом по-прежнему есть чем. `display: block` включает та же
   строка css, что и показ, а `разместить_подсказку` вызывается уже ПОСЛЕ
   того, как класс поставлен (или `:hover` сработал): к этой секунде
   размеры настоящие, а нарисовать браузер ещё не успел — он не рисует
   посреди обработчика события.

   НАВЕДЕНИЕ — ТОЛЬКО ТАМ, ГДЕ ЕСТЬ МЫШЬ. На тачскрине `:hover` залипает
   после касания и гаснет неизвестно когда: подсказка висела бы над
   таблицей. Поэтому наведение заперто в `@media (hover: hover)`, а на
   телефоне открывает нажатие — класс `открыта`, который ставит js. */
.что-это {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 15px; height: 15px; margin-inline-start: 6px;
  vertical-align: middle; flex: 0 0 auto;
  border: 1px solid var(--край); border-radius: 50%;
  background: var(--фон-3); color: var(--текст-3);
  font-size: .62rem; font-weight: 700; font-style: normal; line-height: 1;
  cursor: help; user-select: none;
}
.что-это:hover, .что-это:focus, .что-это.открыта {
  color: var(--текст); border-color: var(--текст-3); outline: none;
}
.что-это > .что-это-текст {
  position: absolute; z-index: 40;
  top: calc(100% + 7px); left: -8px;
  /* `max-content` — ширина по самой длинной строке, но не шире окна: без
     потолка «Micro E-mini Russell 2000» и код скидки развернули бы
     подсказку в одну строку через весь экран. */
  width: max-content; max-width: min(19rem, calc(100vw - 32px));
  padding: 8px 11px;
  border: 1px solid var(--край); border-radius: 9px;
  background: var(--фон-2); box-shadow: var(--тень-2);
  color: var(--текст); font-size: .8rem; font-weight: 400; line-height: 1.35;
  text-align: start; text-transform: none; letter-spacing: 0;
  /* Общий `nowrap` таблицы сюда не пускаем: подсказка обязана переноситься,
     иначе потолок ширины выше ничего не значит. И выделять текст в ней
     МОЖНО — ради этого щелчок её и приклеивает.

     `pre-line`, А НЕ `normal`: подсказка у галочки отписки несёт ДВА СПИСКА —
     что гаснет и что приходит всегда, — и склеенные в один абзац они
     отвечают на вопрос «а это письмо перестанет приходить?» хуже, чем не
     отвечают вовсе. Разметку внутрь пустить нельзя: `знак_что_это`
     экранирует текст целиком, и это не придирка — через него едут чужие
     слова из панели. Значит переносы. Прочим подсказкам `pre-line` ничего
     не меняет: там однострочные фразы без переводов строки, а лишние
     пробелы он схлопывает так же, как `normal`. */
  white-space: pre-line; user-select: text; cursor: text;
  display: none;
}
.что-это > .что-это-текст .выделено { font-weight: 700; color: var(--текст); }
@media (hover: hover) {
  .что-это:hover > .что-это-текст { display: block; }
}
.что-это:focus-visible > .что-это-текст,
.что-это.открыта > .что-это-текст { display: block; }
/* РАЗВОРОТ ВНУТРЬ У КРАЯ. Вбок подсказку вдвигает js числом — ставит
   `margin-left`, померив, сколько не хватило (см. `разместить_подсказку`).
   Классом это делать нельзя: «прижаться правым краем вместо левого»
   помогает, только пока подсказка уже половины окна, а на 375 точках она
   шире, и такой переворот уводил её левым краем за экран на 98 точек.

   Вверх — классом: положений всего два, под значком и над ним. */
.что-это.вверх > .что-это-текст { top: auto; bottom: calc(100% + 7px); }

/* ── КЛЕТКА С НАЗВАНИЕМ ─────────────────────────────────────────────

   Владелец о списке «Your checks»: «что абсолютно никак не приемлемо — это
   то, что скролить нужно вправо-влево. Смотрится по-дебильному».

   Виновата колонка SOURCE. С тех пор как в ней стоит НАЗВАНИЕ РОЛИКА, а не
   слово «YouTube», в неё попадают вот такие строки:

     «12x CHAMPION Reveals His "3-TOUCH" Strategy That Won Robbins Cup
      (Step-by-Step)»

   Общее `white-space: nowrap` держало это в одну строку. Замер на живой
   странице: таблица 1938 точек при карточке в 1043 — и человек ездил
   вправо-влево, чтобы добраться до кнопки «open» в последней колонке.

   ПРОКРУТКУ НЕ ЛЕЧАТ ПРОКРУТКОЙ. `overflow-x: auto` на обёртке и БЫЛ тем
   лечением: он прячет непоместившееся вместо того, чтобы уместить, и именно
   он превращал разъехавшуюся таблицу в полосу внизу. Его больше нет ни у
   одной обёртки — см. запрет наверху раздела, — и уместиться таблица
   обязана по-настоящему.

   Три правила, и каждое нужно своё:

     * клетка с названием переносится по словам — иначе всё остальное здесь
       бессмысленно;
     * её вклад в ширину ограничен сверху (`.название { max-width }`). Без
       потолка одно длинное название забирает всю карточку, а дата и
       состояние сжимаются в нечитаемое — а их владелец читает глазами;
     * `overflow-wrap: anywhere` — на случай слова без пробелов: адрес,
       хэштег, немецкое существительное. Одно такое слово распирает колонку
       ровно так же, как раньше распирала целая строка, и на сорока одном
       языке такие слова обычное дело.

   Ссылка — БЛОК, а не строчный элемент: нажимается всё название целиком,
   все три строки, а не первая из них.

   КЛАССА «УМЕЩАЕТСЯ» ЗДЕСЬ БОЛЬШЕ НЕТ, и это главная правка третьего
   захода. Он помечал ту таблицу, которой уже разрешено не ездить, — то
   есть был разрешением поверх запрета, которого не было. Пока разрешение
   раздавалось поштучно, каждая новая таблица рождалась с прокруткой, и
   владельцу приходилось показывать пальцем на очередную. Теперь наоборот:
   не ездит никто, и пометить таблицу как «этой можно» нечем.

   ЛИПКАЯ ШАПКА УШЛА ВМЕСТЕ С НЕЙ. `position: sticky` у `th` жил ради
   прокрутки ВНУТРИ обёртки и работал только благодаря ей: `overflow-x:
   auto` делал обёртку контейнером прокрутки по обеим осям, и шапка липла к
   её верху. Без контейнера sticky липнет к верху ЭКРАНА — шапка поехала бы
   поверх страницы через весь отчёт. Поэтому у `table.данные th` выше её
   нет вовсе. */
table.данные td.клетка-название { white-space: normal; overflow-wrap: anywhere; }
/* 30rem — ЗАМЕРЕНО, а не выбрано на глаз. На карточке в 1042 точки: при
   34rem и 32rem имя счёта «TopstepX 150K» ломалось на две строки, при 28rem
   самые длинные названия уходили в четыре. При 30rem названия держатся в
   одну-три строки (владелец просил «в две-три строчки»), а имя счёта
   остаётся целым. */
table.данные td.клетка-название .название { display: block; max-width: 30rem; }

/* ── ПАНЕЛЬ: ТАБЛИЦА «USERS» ─────────────────────────────────────────

   Та же болезнь, только в панели администратора: владелец увидел
   горизонтальную полосу именно на этой таблице (09.09.2026). Причиной был
   не общий `nowrap` сам по себе — он верен для коротких клеток (числа,
   дата, одиночная метка), — а то, что имя и метки состояния были ГОЛЫМИ
   `<td>`, без переносящего класса, и `.таблица-обёртка` панели пряталa
   несовпадение прокруткой вместо того, чтобы дать клеткам перенос. Обёртка
   починена в admin.html; здесь — сам перенос, тем же приёмом, что у
   `клетка-название` выше. */
table.данные td.клетка-имя { white-space: normal; overflow-wrap: anywhere; }
/* Метки ADMIN и LIFETIME встают ОДНА ПОД ДРУГОЙ, а не в строку через
   пробел. `.метка` сама по себе `inline-block` — для строки бейджей это и
   нужно везде, кроме этой клетки: две метки разом в одну строку широки на
   переводах длиннее английского («Administrator», «Lebenslang»), а бейдж —
   не то, что можно переносить ПОСЕРЕДИНЕ слова ради экономии места. Поэтому
   здесь `.метка` переопределена в блочную — каждая на своей строке. */
table.данные td.клетка-статус .метка { display: block; white-space: normal; }
table.данные td.клетка-статус .метка + .метка { margin-top: 4px; }

/* ── УЗКИЙ ЭКРАН: СТРОКА СТАНОВИТСЯ КАРТОЧКОЙ ───────────────────────

   Владелец смотрит и с телефона, и там дело уже не в названии. На 375
   точках не помещается ни одна из этих таблиц: одна только дата
   «2026-09-03 18:31» занимает 143 точки, а колонок шесть. Переносом тут не
   спасти — сжимать дату и состояние нельзя, они перестают читаться, а это
   ровно то требование, которое владелец и поставил.

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

   ПОДПИСЬ БЕРЁТСЯ ИЗ ШАПКИ ЭТОЙ ЖЕ ТАБЛИЦЫ — её ставит `подписать_клетки()`
   в app.js атрибутом data-подпись. Второй список слов в коде разошёлся бы
   с шапкой на первом же новом языке, и разошёлся бы молча: сорок один язык
   мы не читаем.

   900, а не 560, и число это ЗАМЕРЕНО, а не выбрано красиво. При 775 точках
   таблица рынков просит 751 при карточке в 725: восемь колонок дат и чисел
   не сжимаются никуда. Тот же 900 уже стоит в этом файле — на нём сетки
   складываются в одну колонку, — и второй границы рядом заводить незачем. */
@media (max-width: 900px) {
  table.данные.складная,
  table.данные.складная tbody,
  table.данные.складная tr,
  table.данные.складная td { display: block; width: auto; }
  table.данные.складная thead { display: none; }
  table.данные.складная tr {
    padding: 10px 14px; border-bottom: 1px solid var(--край);
  }
  table.данные.складная tr:last-child { border-bottom: 0; }
  table.данные.складная td {
    padding: 3px 0; border-bottom: 0;
    /* Общий nowrap снимается со ВСЕХ клеток разом: в карточке переносить
       можно и число — оно стоит на своей строке и ни с чем не спорит. */
    white-space: normal; text-align: start;
  }
  /* Пустая клетка карточку не занимает. У незавершённой проверки кнопки
     нет вовсе, и пустая строка под ней читалась бы как пропущенное поле. */
  table.данные.складная td:empty { display: none; }
  table.данные.складная td[data-подпись]::before {
    content: attr(data-подпись);
    display: inline-block; min-width: 7.5em; margin-inline-end: 8px;
    font-size: .7rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: .04em; color: var(--текст-3);
  }
  /* ИМЯ ЧЕЛОВЕКА ПОД АДРЕСОМ, А НЕ ПОД ПОДПИСЬЮ «EMAIL» (панель, вкладка
     Users → Checks; проверяющий, 30.09.2026). Ячейка почты несёт адрес и,
     вторым блоком, имя (`admin.js`, `ячейка_почты`). Подпись колонки —
     inline-block перед адресом, а имя — блок: он встаёт на новую строку с
     ЛЕВОГО края ячейки, то есть прямо под подписью, и читается как чья-то
     чужая строка, а не как имя владельца адреса. Сетка из двух колонок —
     подпись и всё остальное — ставит имя во вторую, ровно под адрес, без
     второго числа для отступа: ширину подписи задаёт `min-width` выше, и
     копия этого числа здесь разошлась бы с ним при первой же правке. Ячейка
     без имени рисуется как прежде: подпись слева, адрес справа. */
  table.данные.складная td.почта-ячейка {
    display: grid; grid-template-columns: auto minmax(0, 1fr);
    align-items: start;
  }
  table.данные.складная td.почта-ячейка > div { grid-column: 2; }

  /* Название — блок, поэтому оно само встаёт ПОД своей подписью и берёт
     всю ширину карточки. Рядом с подписью оно стало бы узким столбиком в
     шесть строк. Потолок ширины здесь снимается: карточка и есть потолок,
     а второй потолок внутри неё оставил бы пустое поле справа. */
  table.данные.складная td.клетка-название .название { max-width: none; }
}

/* Полоска под списком: сколько на странице, какая страница, две стрелки.
   Переносится по строкам, а не сжимается: на телефоне выбор и стрелки
   встают друг под друга, и ни то, ни другое не выезжает за карточку. */
.листалка {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px;
  margin-top: 12px;
}
.листалка select { width: auto; min-width: 90px; padding: 6px 10px; }
.листалка > .кнопки-пара { margin-inline-start: auto; }

/* ── ОРГАНЫ ЛИСТАНИЯ ──────────────────────────────────────────────────
   Одни и те же на витрине и в панели: номера с многоточиями, поле для
   номера страницы, размер страницы, строка «показано 26–50 из 1342»
   (правило 25). Рисует их `листалка` в app.js и `показать_список` в
   admin.js — двумя руками, но одними именами классов.

   ЖИВУТ ОНИ ЗДЕСЬ, А НЕ В РАЗМЕТКЕ. Такой же набор правил стоит вторым
   домом в `<style>` внутри `admin.html` (там он появился раньше, когда
   листалка была только у панели). Два дома у одного правила расходятся
   молча: поправят один, второй останется вчерашним. Этот файл читают обе
   страницы, значит дом должен быть один — этот, а копию из `admin.html`
   надо снять. Файл держит другая работа, поэтому здесь только запись.

   Полоса сама переносится по строкам: на телефоне номера, поле и выбор
   размера встают друг под друга и ничего не выезжает за карточку. */
.стр-строка { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.стр-кнопка {
  font: inherit; font-size: .85rem; min-width: 32px; padding: 5px 9px;
  background: var(--фон-2); border: 1px solid var(--край);
  border-radius: var(--радиус-с); color: var(--текст-2); cursor: pointer;
}
.стр-кнопка:hover:not(:disabled) { background: var(--фон-3); color: var(--текст); }
.стр-кнопка:disabled { opacity: .4; cursor: default; }
.стр-кнопка.выбрана {
  background: var(--синий-свет); border-color: var(--синий); color: var(--синий);
  font-weight: 650;
}
.стр-многоточие { padding: 0 4px; color: var(--текст-3); }
.стр-поле { display: flex; align-items: center; gap: 6px; margin: 0 0 0 10px; }
.стр-поле span { font-size: .8rem; color: var(--текст-3); }
.стр-поле input { width: 74px; padding: 5px 8px; font-size: .85rem; }
.стр-поле select { padding: 5px 8px; font-size: .85rem; }
.стр-итог { margin: 8px 0 0; }
/* Полоса на витрине состоит из двух этажей — ряда кнопок и строки
   «показано», — поэтому она перестаёт быть строкой и становится столбцом.
   Без этого `display:flex` выше поставил бы их рядом, и строка «показано»
   уехала бы вправо от кнопок. */
.листалка > .стр-строка { flex: 1 1 100%; }
.листалка > .стр-итог { flex: 1 1 100%; }

/* ── вердикт ───────────────────────────────────────────────────────── */

.вердикт { border-radius: var(--радиус); padding: 18px 20px; border: 1px solid; }
.вердикт h3 { margin: 0 0 6px; font-size: 1.05rem; }
.вердикт p { margin: 0; font-size: .92rem; }
.вердикт.зелёный { background: var(--зелёный-фон); border-color: var(--зелёный); }
.вердикт.зелёный h3 { color: var(--зелёный); }
.вердикт.жёлтый  { background: var(--жёлтый-фон);  border-color: var(--жёлтый); }
.вердикт.жёлтый h3 { color: var(--жёлтый); }
.вердикт.красный { background: var(--красный-фон); border-color: var(--красный); }
.вердикт.красный h3 { color: var(--красный); }
.вердикт.серый   { background: var(--серый-фон);   border-color: var(--край-2); }

/* ── предупреждение о правилах фирмы ───────────────────────────────

   Тот же `вердикт`, но заголовок у него `h4`, а не `h3`: блок стоит ВНУТРИ
   карточки фирмы, у которой заголовок уже `h3`, и второй `h3` внутри сломал
   бы порядок заголовков для читалки экрана. Цвет заголовка повторяется по
   состояниям — иначе h4 остался бы чёрным там, где рамка красная, и самое
   сильное предупреждение читалось бы как самое слабое. */
.вердикт h4 { margin: 0 0 6px; font-size: 1rem; }
.вердикт.зелёный h4 { color: var(--зелёный); }
.вердикт.жёлтый  h4 { color: var(--жёлтый); }
.вердикт.красный h4 { color: var(--красный); }

/* Цитата чужого правила. Границу между «сказала фирма» и «сказали мы»
   человек должен видеть глазами, а не вычитывать из формулировок. Фона нет
   намеренно: блок и так стоит на цветной подложке вердикта, и второй фон
   внутри первого читался бы как ошибка вёрстки. */
.цитата-фирмы {
  margin: 10px 0 0; padding: 8px 0;
  padding-inline-start: 12px;
  border-inline-start: 3px solid var(--край-2);
  font-size: .88rem; line-height: 1.45;
}
.цитата-фирмы footer { margin-top: 6px; }

/* ── ГЛАЗОК У ПАРОЛЯ ──────────────────────────────────────────────
   Кнопка стоит ВНУТРИ поля справа, а поле получает отступ под неё: иначе
   длинный пароль уезжает прямо под кнопку и последние знаки не прочитать —
   то есть глазок мешал бы ровно тому, ради чего заведён.
   Цвета переменными, а не числами: в правилах печати переменные сведены к
   чёрно-белому, и вбитый сюда цвет вылез бы на лист заливкой. */
.глазок-обёртка { position: relative; display: block; }
.глазок-обёртка > input { width: 100%; padding-inline-end: 38px; }
.глазок {
  position: absolute; top: 50%; inset-inline-end: 4px;
  transform: translateY(-50%);
  background: transparent; border: 0; cursor: pointer;
  font-size: 1rem; line-height: 1; padding: 4px 6px; border-radius: 6px;
  color: var(--текст-3);
}
.глазок:hover { background: var(--фон-3); }
.глазок:focus-visible { outline: 2px solid var(--синий); outline-offset: 1px; }

/* ── прогресс ──────────────────────────────────────────────────────── */

.полоса {
  height: 8px; border-radius: 99px; background: var(--фон-3);
  overflow: hidden; margin: 12px 0;
}
.полоса i {
  display: block; height: 100%; background: var(--синий);
  border-radius: 99px; transition: width .4s ease;
}

/* ── пульс карточки хода: три точки, шагающие по ответам сервера ─────

   ЗДЕСЬ НЕТ НИ ОДНОГО `animation` И ЭТО ГЛАВНОЕ В ЭТИХ ПРАВИЛАХ. Анимация
   живёт от часов браузера и потому идёт одинаково и когда работа идёт, и
   когда связь оборвалась: она сообщала бы, что браузер умеет двигать точку, а
   не что что-то происходит. Всё движение здесь делает js, переставляя класс
   `сейчас` РОВНО НА ОДИН ОТВЕТ СЕРВЕРА (`отметить_пульс` в app.js). Нет
   ответов — нет движения, и это не поломка, а единственно честное поведение.

   Отсюда же — почти нулевая цена: панель висит по двадцать пять минут, а
   браузеру за всё это время достаётся один переход прозрачности раз в
   полторы секунды. Ни кадров, ни перерисовки макета: `opacity` не двигает
   ничего вокруг себя.

   ЦВЕТ — `--текст-3`, самый тихий из трёх. Ожидание здесь длинное и
   тревожное: человек только что отдал деньги. Синяя мигалка добавила бы
   суеты к тому, к чему добавлять её незачем. */
.ход-пульс {
  display: flex; align-items: center; gap: 10px;
  margin: 12px 0 0; min-height: 18px;
}
.пульс { display: inline-flex; align-items: center; gap: 5px; }
.пульс i {
  display: block; width: 6px; height: 6px; border-radius: 50%;
  background: var(--текст-3); opacity: .22;
  transition: opacity .5s ease;
}
.пульс i.сейчас { opacity: 1; }
/* Строка про потерянную связь не должна выглядеть уведомлением об ошибке:
   работа-то идёт, оборвались только обновления на этой странице. */
#пульс-текст { margin: 0; }

/* СИСТЕМНАЯ НАСТРОЙКА «МЕНЬШЕ ДВИЖЕНИЯ» ГАСИТ ТОЧКИ ЦЕЛИКОМ, а не только их
   плавность. Часть людей от движения на экране укачивает, и полумера —
   «оставим, но без перехода» — оставила бы им ровно то, от чего настройка и
   заводилась: мигающую точку.

   Смысл при этом не теряется, потому что он и не жил в точках: пока ответы
   идут, рядом стоит настоящий счётчик минут, а как только они перестают
   доходить, `отметить_пульс` пишет об этом словами в `#пульс-текст`. Точки
   были вторым, наглядным путём того же сообщения, а не единственным. */
@media (prefers-reduced-motion: reduce) {
  .пульс { display: none; }
}

/* ── красная полоса: смена условий при живой подписке ────────────────
   (владелец, 9 сентября 2026, БИЗНЕС_МОДЕЛЬ.md, «Смена условий при живой
   подписке»). Высоты в CSS нарочно НЕТ — ни `height`, ни `min-height`:
   у нас 42 языка, и то, что по-английски одна строка, по-немецки две.
   Высота — по содержимому, перенос разрешён, а прилипает полоса к самому
   верху (`position: sticky; top: 0`), выше шапки — см. `header.верх`. */
.полоса-условия {
  position: sticky; top: 0; z-index: 50;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: 6px 16px;
  padding: 10px 20px;
  background: var(--красный-фон); color: var(--красный);
  border-bottom: 1px solid var(--красный);
  font-size: .89rem; text-align: center;
}
.полоса-условия-текст { font-weight: 600; }
.полоса-условия-кнопка {
  font: inherit; font-weight: 700; background: transparent; border: 0;
  color: inherit; text-decoration: underline; cursor: pointer; padding: 2px 0;
  white-space: nowrap;
}

/* ── модальные окна ────────────────────────────────────────────────── */

.тень-окна {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(10,12,18,.55); backdrop-filter: blur(3px);
  display: flex; align-items: flex-start; justify-content: center;
  padding: 6vh 20px 20px; overflow-y: auto;
}
/* Копия `.тень-окна`, а не та же самая ИМЕННО ПОТОМУ, ЧТО она та же самая
   визуально. `завести_окна()` в app.js вешает щелчок-мимо-закрывает на
   КАЖДЫЙ `.тень-окна`, а `закрыть_окна()` (её же зовёт Escape) прячет их
   все разом. Окну повторного согласия закрываться нельзя вовсе — ни
   крестиком (его и нет), ни щелчком мимо, ни Escape («без крестика и без
   „потом“» — БИЗНЕС_МОДЕЛЬ.md). Дать ему класс `.тень-окна` значило бы
   молча подключить его к обоим этим выключателям; свой класс с теми же
   правилами оставляет вид тем же, а поведение — другим. z-index на 5
   выше: если открыто окно покупки или окно условий (200), повторное
   согласие обязано лечь поверх, а не спрятаться под ним. */
.тень-неубираемая {
  position: fixed; inset: 0; z-index: 205;
  background: rgba(10,12,18,.72); backdrop-filter: blur(3px);
  display: flex; align-items: flex-start; justify-content: center;
  /* dvh, А НЕ vh — И ЗАПАСНАЯ СТРОКА ПЕРЕД НИМ, тот же довод, что у
     `.помощь-окно` выше: `100vh`/`4vh` меряют экран без адресной строки
     браузера, на телефоне она есть, и верхний отступ оказывается меньше
     видимого — окно повторного согласия, у которого нет крестика и
     закрыть его нельзя ничем (см. комментарий над классом), может лечь
     верхом ПОД адресную строку, и принять/отклонить будет нечем.
     ЗАПАСНАЯ СТРОКА ОБЯЗАТЕЛЬНА: браузер старше 2022 года не поймёт
     вторую и останется с первой, а не без отступа вовсе. */
  padding: 4vh 20px 20px; padding: 4dvh 20px 20px; overflow-y: auto;
}
.окно {
  background: var(--фон-2); border: 1px solid var(--край);
  border-radius: 18px; box-shadow: var(--тень-2);
  width: 100%; max-width: 460px; padding: 28px;
}
.окно.широкое { max-width: 860px; }
.окно .окно-шапка {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 14px; margin-bottom: 18px;
}
.окно h2 { margin: 0; font-size: 1.4rem; }
.закрыть {
  background: transparent; border: 0; cursor: pointer;
  font-size: 1.5rem; line-height: 1; color: var(--текст-3); padding: 2px 6px;
}
.закрыть:hover { color: var(--текст); }

.вкладки { display: flex; gap: 4px; margin-bottom: 20px; border-bottom: 1px solid var(--край); }
.вкладки button {
  font: inherit; font-weight: 600; font-size: .93rem;
  background: transparent; border: 0; cursor: pointer;
  padding: 9px 14px; color: var(--текст-2);
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.вкладки button.выбрана { color: var(--синий); border-bottom-color: var(--синий); }

/* ── сообщения ─────────────────────────────────────────────────────── */

.сообщение {
  padding: 11px 14px; border-radius: var(--радиус-с);
  font-size: .89rem; margin-bottom: 14px; border: 1px solid;
}
.сообщение.ошибка { background: var(--красный-фон); border-color: var(--красный); color: var(--красный); }
.сообщение.успех  { background: var(--зелёный-фон); border-color: var(--зелёный); color: var(--зелёный); }
/* Карточка-предупреждение: слабый разбор, спорный результат — всё, где
   человек рискует принять нашу догадку за факт. Жёлтый, не красный: это не
   поломка, а повод остановиться и прочитать. */
.карта.внимание { background: var(--жёлтый-фон); border-color: var(--жёлтый); }
.карта.внимание h4 { color: var(--жёлтый); }
.карта.внимание p { margin: 0 0 10px; }

/* Подпись справа от квадратика, а не над ним. */
label.поле.строкой { display: flex; align-items: flex-start; gap: 9px;
  margin-bottom: 0; cursor: pointer; }
label.поле.строкой > span { display: inline; font-weight: 400;
  color: var(--текст); margin: 0; font-size: .9rem; }
label.поле.строкой input { margin-top: 3px; flex: 0 0 auto; }

/* ЗНАЧОК «i» У ГАЛОЧКИ ОТПИСКИ — СОСЕД <label>, А НЕ ЕГО НАЧИНКА: щелчок
   внутри label переключает галочку, и человек, открывший подсказку, этим же
   щелчком от писем бы и отписался. Своя высота строки — чтобы кружок встал
   по середине ПЕРВОЙ строки подписи, а не уехал вверх, когда подпись на
   длинном языке переносится на вторую. */
.строка-отписки { display: flex; align-items: flex-start; }
.строка-отписки > #отписка-что-это {
  display: inline-flex; align-items: center; min-height: 22px;
}

.сообщение.внимание { background: var(--жёлтый-фон); border-color: var(--жёлтый); color: var(--жёлтый); }
.сообщение.нейтр  { background: var(--фон-3); border-color: var(--край); color: var(--текст-2); }

.уведомления {
  position: fixed; inset-inline-end: 20px; bottom: 20px; z-index: 200;
  display: flex; flex-direction: column; align-items: flex-end; gap: 10px;
  max-width: calc(var(--ширина-экрана, 100vw) - 40px);
}
/* Потолок у самого уведомления, а не только у стопки.

   У стопки он был, у отдельного уведомления — нет: триста восемьдесят
   пикселей шире, чем вся стопка на телефоне. Стопка прижата к правому
   краю (align-items: flex-end), поэтому лишнее уходило не вправо, а
   ВЛЕВО: на экране в 320 левый край уведомления оказывался на -80, и
   начало фразы было не прочитать. Горизонтальной прокрутки при этом не
   появлялось — влево страница не прокручивается вовсе, — так что беда
   была молчаливая. На языках справа налево то же самое зеркально.

   Меряем от --ширина-экрана по той же причине, что и всё остальное
   всплывающее: 100vw на мобильном шире видимой части. */
.уведомления > .уведомление:not(.держится) {
  max-width: min(380px, calc(var(--ширина-экрана, 100vw) - 40px));
}
.уведомление {
  background: var(--фон-2); border: 1px solid var(--край);
  border-inline-start: 3px solid var(--синий);
  border-radius: 10px; padding: 12px 16px; box-shadow: var(--тень-2);
  font-size: .9rem; animation: всплыть .2s ease;
}
.уведомление.ошибка { border-inline-start-color: var(--красный); }
.уведомление.успех  { border-inline-start-color: var(--зелёный); }
/* Сообщение, которое ждёт, пока его закроют. Крестик в углу, место под
   него в отступе, и перенос по строкам: ответ проверки ключей — это
   несколько строк, а не полслова. */
/* Шире и мельче обычного: строка вида
   «help chat — Claude claude-haiku-4-5-20251001: ok» в узкой колонке
   переносится трижды, и четыре строки ответа занимают пол-экрана.

   Потолок, а не заданная ширина: с тех пор как здесь висит любой отказ, а не
   только длинный ответ проверки ключей, короткое «DeepSeek failed» растянутое
   на 560 читается как пустая коробка. Многострочный ответ упирается в тот же
   потолок, что и раньше, а короткий сжимается по себе. На узком экране
   потолок тот же, что у обычного уведомления, и по той же причине: стопка
   прижата к правому краю, и лишняя ширина уехала бы за левый. */
.уведомление.держится {
  padding-inline-end: 34px; position: relative;
  white-space: pre-line; line-height: 1.45;
  max-width: min(560px, calc(var(--ширина-экрана, 100vw) - 40px));
  font-size: .84rem;
}
.закрыть-уведомление {
  position: absolute; top: 6px; inset-inline-end: 8px;
  background: none; border: 0; cursor: pointer;
  color: var(--текст-3); font-size: 1.15rem; line-height: 1;
  padding: 2px 6px; border-radius: 6px;
}
.закрыть-уведомление:hover { color: var(--текст); background: var(--фон-3); }

@keyframes всплыть { from { opacity: 0; transform: translateY(8px); } }

/* ── подвал ────────────────────────────────────────────────────────── */

footer.низ {
  border-top: 1px solid var(--край); background: var(--фон-2);
  padding: 52px 0 34px; margin-top: 40px;
}
.низ-сетка { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: 34px; }
.низ-сетка h4 {
  font-size: .78rem; text-transform: uppercase; letter-spacing: .07em;
  color: var(--текст-3); margin-bottom: 12px;
}
.низ-сетка a { display: block; color: var(--текст-2); font-size: .9rem; padding: 4px 0; }
.низ-сетка a:hover { color: var(--синий); }
.мелкий-шрифт {
  margin-top: 34px; padding-top: 22px; border-top: 1px solid var(--край);
  font-size: .79rem; color: var(--текст-3); line-height: 1.65;
}

/* ── разное ────────────────────────────────────────────────────────── */

.скрыт { display: none !important; }
.моно { font-family: var(--моно); font-size: .87rem; }
.тускло { color: var(--текст-3); }
.вторично { color: var(--текст-2); }
.по-центру { text-align: center; }
/* Строка «слева заголовок или подсказка, справа кнопки».

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

   Дальше начиналось самое неприятное, и видно его только в мобильном
   режиме. Когда страница шире экрана, мобильный браузер расширяет макетную
   область до ширины содержимого: при экране в 360 макет становился 447.
   Кнопка помощи стоит position: fixed; right: 12px — и меряется она от
   макета, а не от видимой части. То есть уезжала за правый край на
   семьдесят пять пикселей и доставалась только боковой прокруткой.
   На тамильском при 320 страница разъезжалась на 126 пикселей.

   Перенос по строкам решает это честно: не встали рядом — кнопки уходят
   под заголовок. min-width: 0 остаётся на крайний случай, когда элемент
   шире строки и в одиночку: без него он не сожмётся ниже min-content и
   всё равно вылезет, а с ним длинное слово переносится по body {
   overflow-wrap: break-word }. */
.вверх-между {
  display: flex; justify-content: space-between; align-items: center;
  gap: 14px; flex-wrap: wrap;
}
.вверх-между > * { min-width: 0; }
/* Кнопки внутри такой строки сгруппированы своим флексом (разметка задаёт
   ему display и gap прямо в атрибуте). Ему нужен тот же перенос и по той
   же причине: две кнопки рядом на длинном языке шире, чем есть места. */
.вверх-между > div { flex-wrap: wrap; }
.разделитель { height: 1px; background: var(--край); margin: 22px 0; }

/* ── мой профиль ────────────────────────────────────────────────────
   Почта и «Visa ···· 4242» — единственные строки на сайте, которые человек
   не выбирал и укоротить не может. Адрес вида
   very.long.name+tag@some-university-department.example.org длиннее карточки
   на телефоне, и переносить его негде: пробелов в нём нет. Без `anywhere`
   такая строка распирает окно, а окно тащит за собой страницу — и она едет
   вправо-влево, чего владелец не хочет нигде. Сторожит это
   `проверка_витрины.py`, проверка «НА ПРОФИЛЕ НЕТ БОКОВОЙ ПРОКРУТКИ». */
.профиль-раздел { margin: 0 0 6px; font-size: .95rem; }
.профиль-значение {
  font-size: 1rem; font-weight: 600; color: var(--текст);
  margin-bottom: 6px; overflow-wrap: anywhere;
}
/* Две ссылки в строку, а на узком — друг под другом. «My payments» и «My
   checks» на немецком или греческом вдвое длиннее английских. */
.профиль-ссылки { display: flex; flex-wrap: wrap; gap: 16px; }

.документ { line-height: 1.75; }
.документ h1 { font-size: 1.9rem; }
.документ h2 { font-size: 1.25rem; margin-top: 1.8em; }
.документ blockquote {
  margin: 1.2em 0; padding: 14px 18px;
  border-inline-start: 3px solid var(--край-2);
  background: var(--фон-3);
  border-start-start-radius: 0; border-end-start-radius: 0;
  border-start-end-radius: 8px; border-end-end-radius: 8px;
  font-size: .87rem; color: var(--текст-2);
}
.документ code { font-family: var(--моно); font-size: .88em; background: var(--фон-3); padding: 1px 5px; border-radius: 4px; }
.крутилка {
  width: 17px; height: 17px; border-radius: 50%;
  border: 2px solid var(--край-2); border-top-color: var(--синий);
  animation: верчение .7s linear infinite; display: inline-block;
}
@keyframes верчение { to { transform: rotate(360deg); } }

/* ── узкие экраны ──────────────────────────────────────────────────── */

@media (max-width: 900px) {
  h1 { font-size: 2.1rem; }
  h2 { font-size: 1.5rem; }
  /* Одна колонка — и порядок задаётся областями: текст, обещание
     бесплатного бота, и только потом кнопки с цифрами. Уйди обещание вниз,
     под цифры, — на телефоне его снова пришлось бы искать прокруткой, а
     ровно от этого его сюда и переносили. */
  .экран-сетка {
    grid-template-columns: 1fr;
    grid-template-areas: "текст" "справа" "низ";
    gap: 28px;
  }
  /* На широком экране этот отступ отделяет лид от кнопок — строки сетки
     стоят вплотную (row-gap: 0). В одну колонку зазор даёт сама сетка, и
     отступ сложился бы с ним в дыру почти в шестьдесят точек. */
  .экран .лид { margin-bottom: 0; }
  .сетка.к3, .сетка.к4, .сетка.к2 { grid-template-columns: 1fr; }
  .низ-сетка { grid-template-columns: 1fr 1fr; }
  section { padding: 50px 0; }
  .выбор-языка { width: 120px; min-width: 120px; max-width: 120px; }
}
@media (max-width: 560px) {
  .обёртка, .узко { padding: 0 16px; }
  .низ-сетка { grid-template-columns: 1fr; }
  .знак b { display: none; }
  .окно { padding: 20px; }
}


/* Брейкпоинтов для меню больше нет. Языков сорок два, длина слов у всех
   разная, и угадать ширину заранее нельзя — поэтому меню меряется на месте
   при загрузке, при смене языка и при изменении окна. */
@media (max-width: 620px) {
  .знак b { display: none; }
}


/* ── печать правил ──────────────────────────────────────────────────
   Человек уносит с собой ровно то, что мы поняли из его описания: список
   правил, наши допущения и то, что осталось неясным. Это его документ,
   и он должен читаться на бумаге без сайта вокруг. */
#печать { display: none; }

@media print {
  /* ── БУМАГА ВСЕГДА БЕЛАЯ, БУКВЫ ВСЕГДА ЧЁРНЫЕ ─────────────────────

     ЧТО БЫЛО. `#печать { color:#000; background:#fff }` ниже стояло с
     самого начала — и не спасало. Владелец сидит в тёмной теме, вызвал
     предпросмотр печати и получил белые буквы на чёрных плашках: лист,
     который съедает картридж целиком. Дословно: «Всегда на белом
     прозрачном фоне чёрные буквы. Распечатываются только так».

     ПОЧЕМУ НЕ СПАСАЛО. Тёмная тема живёт не в `#печать`, а в переменных
     на `html[data-тема="тёмная"]`, и её цвета приезжают на лист тремя
     дорогами сразу, мимо этих двух строк:

       * `html, body { background: var(--фон) }` — тёмное полотно всей
         страницы, которое браузер печатает как фон листа;
       * чересполосица строк таблицы (`tbody tr:nth-child(even)`),
         заголовки `thead th` и всё прочее, что берёт `var(--фон-3)`, —
         своего фона `#печать` им не навязывает, у них он свой;
       * `color: var(--текст)` у потомков — белый поверх всего этого.

     ПОЧЕМУ ПЕРЕОПРЕДЕЛЯЕМ ПЕРЕМЕННЫЕ, А НЕ КРОЕМ КАЖДОЕ МЕСТО. Мест
     этих полтораста, и завтра появится сто пятьдесят первое. Переменные
     же — единственная дорога, которой тема расходится по файлу: сведи
     их на бумаге к светлым значениям, и тёмной темы на листе не
     остаётся нигде, включая то, чего мы сегодня не перечислили. Селектор
     берёт и `:root`, и `html[data-тема="тёмная"]`: у второго вес выше, и
     без него он бы просто победил. */
  :root,
  html,
  html[data-тема="тёмная"] {
    --фон:          #FFFFFF;
    --фон-2:        #FFFFFF;
    --фон-3:        #FFFFFF;
    --текст:        #000000;
    --текст-2:      #333333;
    --текст-3:      #333333;
    --край:         #999999;
    --край-2:       #999999;
    --синий:        #000000;
    --синий-тёмный: #000000;
    --синий-свет:   #FFFFFF;
    --графит:       #000000;
    /* Цвет вердикта на бумаге не цвет, а рамка: см. `#печать .вердикт`
       и `#печать .метка` ниже. Зелёное и красное сведены в чёрное —
       иначе принтер либо съест тонер под заливку, либо не напечатает её
       вовсе, и метка станет пустым местом. */
    --зелёный:      #000000;
    --зелёный-фон:  #FFFFFF;
    --жёлтый:       #000000;
    --жёлтый-фон:   #FFFFFF;
    --красный:      #000000;
    --красный-фон:  #FFFFFF;
    --серый-фон:    #FFFFFF;
    --тень:         none;
    --тень-2:       none;
  }
  html, body { background: #fff !important; color: #000 !important; }

  body.печатаем > *:not(#печать) { display: none !important; }
  body.печатаем #печать { display: block; }

  /* И ковровое заглушение поверх переменных — на всё, что внутри листа.

     Переменных мало для двух случаев: цвет, вбитый в разметку прямо
     (`style="background:var(--фон-3)"` у блока с json, `style="color:
     var(--зелёный)"` у ответа помощника), и цвет, вбитый в правило
     числом. Инлайновый стиль сильнее любого селектора, поэтому здесь
     `!important`; исключения — заливку заголовка таблицы и серый цвет
     подсказок — приходится возвращать тоже с `!important`, иначе они не
     переспорят эту строку. Так и задумано: заливка на листе заводится
     осознанно и поштучно, а не приезжает с экрана сама. */
  #печать, #печать * {
    background: transparent !important;
    background-image: none !important;
    color: #000 !important;
    box-shadow: none !important;
    text-shadow: none !important;
    filter: none !important;
  }
  /* ORPHANS/WIDOWS ПО УМОЛЧАНИЮ В БРАУЗЕРЕ — ДВЕ СТРОКИ, И ИМЕННО ОНИ ГНАЛИ
     БЛОК НА НОВУЮ СТРАНИЦУ. Советчик 08.09.2026 намерил у образцов почти
     пустые страницы 3 и 13: абзацу или ячейке, которым на текущем листе
     оставалось меньше двух строк места, браузер не разрешал остаться —
     правило запрещает бросать меньше двух строк ни вверху, ни внизу
     страницы, — и целый блок уезжал на новый лист, а хвост прежнего листа
     оставался пустым. Здесь это правило нигде не переопределялось, значит
     работало умолчание браузера. Единица вместо двух снимает именно этот
     запрет и ничего больше: блок по-прежнему можно разбить по строке, а
     не выгонять целиком ради тех двух строк, которых теперь и не жалко. */
  #печать { background: #fff !important; color: #000; font-size: 11pt;
            orphans: 1; widows: 1; }
  /* ДВА ЧИСЛА КАРТОЧКИ, КРУПНО, НА ПЕРВОЙ СТРАНИЦЕ (см. `печатать` в
     app.js). Ради этого контраста образец и показывают, а на бумаге в
     12–13 страниц его иначе пришлось бы искать внутри документа. */
  #печать .печать-числа {
    display: flex; gap: 20px; flex-wrap: wrap;
    margin: 0 0 18px; break-inside: avoid; page-break-inside: avoid;
  }
  #печать .печать-число {
    border: 1px solid #000; border-radius: 6px; padding: 8px 16px;
  }
  #печать .печать-число b { display: block; font-size: 24pt; line-height: 1.15; }
  #печать .печать-число span {
    display: block; font-size: 8.5pt; color: #333 !important;
  }
  #печать .шапка-печати {
    display: flex; align-items: baseline; justify-content: space-between;
    border-bottom: 2px solid #000; padding-bottom: 8px; margin-bottom: 16px;
  }
  #печать .шапка-печати b { font-size: 15pt; letter-spacing: -.02em; }
  #печать .метка {
    background: none; color: #000; border: 1px solid #000;
    padding: 2px 7px; font-size: 8pt;
  }
  #печать .моно { font-family: monospace; font-size: 10pt; }
  /* json на бумаге не нужен — а вот таблицы проп-фирм нужны, и все сразу.
     На экране они свёрнуты, чтобы страница читалась сверху вниз; на листе
     прятать нечего, нажать там некуда, и свёрнутая таблица просто исчезла
     бы. Раскрывает их `печатать`, ставя `open` КОПИИ, а это правило лишь
     не даёт общему запрету на details утащить их с собой. */
  #печать details:not(.свёртка-фирмы) { display: none; }
  /* Свёрнутая строка на бумаге лишняя: имя фирмы стоит заголовком внутри
     самой карточки, и summary дал бы его вторым разом подряд. */
  #печать .свёртка-фирмы > summary { display: none; }
  /* Кнопки печатаются вместе с отчётом, если их не убрать: на листе
     появляется прямоугольник со словом «Печать», который ничего не
     делает и только сбивает с толку. */
  #печать button, #печать .кнопка { display: none !important; }

  /* Отчёт о прогоне. На экране он цветной, на бумаге цвет либо съедает
     тонер, либо не печатается вовсе и метка становится пустым местом.
     Поэтому на листе всё чёрно-белое, а вердикт держится рамкой. */
  .разрыв-страницы { break-before: page; page-break-before: always; }
  #печать .карта { border: 0; padding: 0; box-shadow: none; background: none; }

  /* СКЛАДНАЯ ТАБЛИЦА НА ПЕЧАТИ СНОВА ТАБЛИЦА, А НЕ ЛЕНТА КАРТОЧЕК.

     ПРИЧИНА ПОЛОМКИ. Печатное поле — 8.5in минус два раза `@page { margin:
     16mm }` ниже — это около 695 CSS-точек. 695 МЕНЬШЕ 900, значит
     `@media (max-width: 900px)` выше срабатывает НА ЛЮБОЙ печати, даже с
     монитора в 1920 точек: браузер меряет не экран, а лист. Ни один
     селектор в этом файле до сих пор не возвращал складную таблицу назад
     в `display: table` для печати — лист наследовал мобильную карточку
     целиком: шапка (`thead`) спрятана, `<tr>`/`<td>` расставлены
     `display: block` друг под другом, и `td[data-подпись]::before` перед
     каждой клеткой рисует подпись колонки текстом. Замер на образце с
     karivox.com 23.09.2026 — 43 листа вместо честных 18 (09.09 тот же
     образец печатался на 12, текста с тех пор прибавилось 3–4%): подписи
     ACCOUNT/PRICE/DRAWDOWN/DAILY LOSS печатались 77 раз на документ
     вместо 9 — по разу в шапке таблицы планов на каждом её листе, — а
     сами таблицы ушли в столбик телефонных карточек на листе Letter.

     ЧТО ВОЗВРАЩАЕМ И ПОЧЕМУ РОВНО ЭТО. Из блока на 816-й строке отменены
     только свойства, которые МЕНЯЮТ ФОРМУ — `display` у таблицы и её
     частей, — и `content` у `::before`, который рисует подпись:
       * `display: table` / `table-header-group` / `table-row-group` /
         `table-row` / `table-cell` возвращает браузеру обычный табличный
         рендер;
       * `content: none` гасит `::before` — без него подпись дублировалась
         бы перед каждой клеткой уже настоящей строки, те самые 77 раз;
         `display: none` рядом с ним — уже перестраховка (`content: none`
         сам по себе не рисует псевдоэлемент вовсе), но мобильный блок
         помимо `content` трогает у той же `::before` и `display:
         inline-block`, а сторож проверяет каждое свойство формы своей
         строкой и не обязан знать, что одно гасит другое по спецификации;
       * `td:empty { display: table-cell }` — отдельно: `display: none` из
         мобильного блока на пустой клетке в карточке просто убирает
         строку подписи, а в НАСТОЯЩЕЙ таблице вырезает ячейку из ряда
         целиком, и соседние столбцы у этой строки поехали бы на одну
         колонку влево;
       * `td.почта-ячейка { display: table-cell }` — пара к
         `td.почта-ячейка { display: grid }` из мобильного блока (админка:
         имя человека под адресом). На бумаге сетку и так переспорил бы
         общий `#печать … td` (он весомее), но сторож считает пары по
         подписи селектора, а не по соседним правилам, и полагаться на
         соседа значило бы держать возврат формы на чужой строке.
     Остальное из мобильного блока не тронуто — осознанно:
       * `padding`/`border-bottom` на `<tr>` (строки 822 и 825) браузер не
         рисует вовсе, когда у ряда `display: table-row` — возврат
         `display` выше уже обесточил их без единой лишней строки здесь;
       * `padding`/`border-bottom`/`text-align` на `<td>` (строка 826)
         печать и так переопределяет ниже своим `#печать table.данные
         td` — то правило весомее по каскаду (у него есть `#печать`), и
         повторять его тут незачем;
       * `td.клетка-название .название { max-width: none }` (строка 861)
         на печати не вредит: ширину столбца и так держит сама таблица
         через ширину листа, а не потолок в 30rem у span.
     Сторожит это `беды_печати_складной()` в `проверка_витрины.py`: он
     разбирает css правилами (селектор → свойства), а не ищет готовую
     строку, и красит любое НОВОЕ `display`/`content`-правило у складной
     таблицы в мобильном блоке, для которого здесь не нашлось пары, —
     или нашлась, но слабее мобильной по специфичности либо с тем же
     значением. Поэтому `#печать` в начале каждого селектора ниже не
     украшение: с одним `table.данные` правило проигрывает мобильному
     `table.данные.складная` (0,1,x против 0,2,x), и точный образец
     снова печатается на 43 листа с ACCOUNT 82 раза — замер 23.09.2026
     на местном сервере. */
  #печать table.данные.складная { display: table; }
  #печать table.данные.складная thead { display: table-header-group; }
  #печать table.данные.складная tbody { display: table-row-group; }
  #печать table.данные.складная tr { display: table-row; }
  #печать table.данные.складная td,
  #печать table.данные.складная th { display: table-cell; }
  #печать table.данные.складная td:empty { display: table-cell; }
  #печать table.данные.складная td.почта-ячейка { display: table-cell; }
  #печать table.данные.складная td[data-подпись]::before {
    content: none; display: none;
  }

  #печать table.данные { width: 100%; border-collapse: collapse; font-size: 9pt; }
  #печать table.данные th,
  #печать table.данные td {
    border: 1px solid #999; padding: 4px 6px; text-align: start;
  }
  /* ЕДИНСТВЕННАЯ ЗАЛИВКА НА ВСЁМ ЛИСТЕ, и она светло-серая. Шапка
     таблицы без неё сливается со строками: колонок восемь, и на второй
     странице человек уже не помнит, какая из них какая. `!important` —
     чтобы переспорить ковровое `background: transparent` выше; без него
     заливка не появится вовсе. */
  #печать table.данные th { background: #eee !important; font-weight: 600; }
  #печать table.данные td.число,
  #печать table.данные th.число { text-align: end; }
  #печать .таблица-обёртка { overflow: visible; }
  /* На экране таблица рынков уезжает вбок внутри своей обёртки, и это
     нормально: там есть прокрутка. На листе прокрутки нет, обёртка выше
     нарочно раскрыта — и таблица, которая шире бумаги, просто уходит за
     край. Виноват nowrap в ячейках: он живёт в общем правиле и на печать
     приходит вместе со всем остальным. При содержимом A4 в 672 точки
     таблица выходила на 843 на сомалийском, 823 на тамильском и 768 на
     армянском — правые колонки, вердикт в том числе, принтер срезал.

     Поэтому на бумаге ячейкам разрешено переносить. Строка в две строчки
     читается, срезанная колонка — нет. */
  #печать table.данные th,
  #печать table.данные td { white-space: normal; overflow-wrap: break-word; }
  #печать .вердикт {
    border: 2px solid #000; background: none; color: #000;
    padding: 8px 10px; margin-bottom: 12px;
    /* Сам вердикт — та строка, ради которой открывают отчёт: разбить её
       рамку пополам между двумя листами значило бы потерять её с той же
       страницы, где стоят числа. Блок короткий, оторвать ему есть куда. */
    break-inside: avoid; page-break-inside: avoid;
  }
  #печать .метка { border: 1px solid #000; background: none; color: #000; }
  /* Подсказки серым, а не чёрным: на листе они и правда второстепенны.
     `!important` — по той же причине, что и у заливки шапки: без него их
     съедает ковровое `color: #000`. */
  #печать .подсказка, #печать .тускло { color: #333 !important; }
  /* Таблица не должна рваться по строке посреди рынка. */
  #печать table.данные tr { break-inside: avoid; page-break-inside: avoid; }
  #печать .подвал-печати {
    margin-top: 22px; padding-top: 10px; border-top: 1px solid #999;
    font-size: 8.5pt; color: #333 !important;
  }
  a[href]::after { content: none !important; }
  @page { margin: 16mm; }
}


/* ── бесплатный бот на первом экране ────────────────────────────────
   Самое сильное, что есть в предложении, и до сих пор оно было спрятано
   в середине страницы. Зелёная полоса, а не ещё одна кнопка: это не
   действие, это обещание, и оно должно читаться как врезка.

   05.09.2026 переехало из левой колонки, из-под кнопок, в правую — туда,
   где стояла нарисованная карточка отчёта. Отступ снизу отдан колонке
   (`gap`), у самой врезки его больше нет: под ней теперь стоит ссылка на
   образцы, и двойной зазор развалил бы пару. */
.подарок {
  display: block; margin: 0;
  padding: 16px 20px; border-radius: var(--радиус);
  background: var(--зелёный-фон);
  border: 1px solid color-mix(in srgb, var(--зелёный) 45%, transparent);
  border-inline-start: 4px solid var(--зелёный);
  color: var(--текст); text-decoration: none;
  transition: filter .12s;
}
.подарок:hover { text-decoration: none; filter: brightness(1.02); }
.подарок .подарок-метка {
  display: block; font-size: .74rem; font-weight: 700;
  letter-spacing: .07em; text-transform: uppercase;
  color: var(--зелёный); margin-bottom: 3px;
}
.подарок b {
  display: block; font-size: 1.02rem; font-weight: 650;
  line-height: 1.4; margin-bottom: 6px;
}
.подарок > span:last-child {
  display: block; font-size: .92rem; color: var(--текст-2); line-height: 1.55;
}
@media (max-width: 560px) {
  .подарок b { font-size: 1.15rem; }
}

/* Правая колонка первого экрана: обещание и ссылка под ним. Зазор здесь, а
   не отступом у врезки, — колонка знает про обе свои части, врезка про
   соседку не знает. */
.экран-справа { display: grid; gap: 14px; justify-items: start; }
.экран-справа .подарок { justify-self: stretch; }

/* Ссылка на образцы отчётов и ссылка на видео-гайды — тот же класс
   поведения (текст со штриховым подчёркиванием, не кнопка), поэтому один
   правило на обе: они стоят рядом в `.экран-справа` и должны выглядеть
   парой, а не «основной» и «случайно похожей». Ссылка на образцы отчётов.
   Ссылка, а не карточка: рисованный образец с выдуманными числами с этого
   места только что убран, и заменять его вторым рисунком значило бы
   вернуть ту же беду в другом виде. */
.образцы, .видео-ещё {
  font-size: .92rem; font-weight: 500; color: var(--текст-2);
  border-bottom: 1px dashed var(--край-2); padding-bottom: 1px;
}
.образцы:hover, .видео-ещё:hover {
  color: var(--синий); border-bottom-color: var(--синий);
  text-decoration: none;
}

/* Карточка образца в разделе `#samples`. Хвост карточки прижат к низу:
   подписи у двух образцов разной длины, и без этого кнопки встали бы на
   разной высоте — глаз читает такую пару как «одна из них важнее».

   ХВОСТ — БЛОК `.образец-низ`, А НЕ САМА ССЫЛКА, с тех пор как у карточки
   появилась вторая дверь («Open in Karivox») и подсказка про тему рядом с
   ней: `margin-top:auto` двигает вниз ЦЕЛИКОМ то, что внизу, а не только
   первый нажимаемый элемент. */
.образец { display: flex; flex-direction: column; }
.образец h3 { margin: 0 0 10px; font-size: 1.06rem; }
.образец p { margin: 0 0 18px; color: var(--текст-2); }
.образец-низ { margin-top: auto; }
.образец-низ .подсказка { margin: 0 0 8px; }
.образец-низ .кнопки-пара { flex-wrap: wrap; }


/* Предупреждение про Caps Lock под полем пароля. Жёлтым, а не красным:
   это не ошибка, а положение клавиши — красный здесь читался бы как «ты
   уже ошибся», хотя человек ещё ничего не отправил. */
.капслок {
  margin: 6px 0 0; font-size: .86rem; font-weight: 500;
  color: var(--жёлтый, #b8860b);
}

/* ── страница только про видео (`/guides`) ────────────────────────────
   Разметка одна на главную и на эту страницу (сервер отдаёт на оба адреса
   тот же `index.html`), и лишнее убирается здесь, а не в js: стили знают
   про «все разделы» одним селектором, а js пришлось бы держать их список
   поимённо — и разойтись с разметкой в первый же день.

   `:not(#guides)` — единственное исключение, и оно названо один раз.
   Окна, полоса условий и уведомления лежат вне `section`, их это не
   касается: войти и прочитать условия человек обязан мочь с любой
   страницы. */
body.страница-видео > .экран,
body.страница-видео > section:not(#guides) { display: none; }

/* На своей странице раздел занимает её целиком, и верхний отступ ему нужен
   свой: на главной над ним всегда стоял другой раздел, а здесь — только
   шапка. */
body.страница-видео > #guides { padding-top: 34px; }

/* ── первый ролик в первом экране главной ─────────────────────────────
   Карточка та же, что на странице видео (тот же класс `.видео-гайд`, тот
   же переключатель, те же субтитры) — здесь только ширина: в правой
   колонке первого экрана она обязана занять её всю, как и обещание
   бесплатного бота под ней. */
.экран-видео { justify-self: stretch; width: 100%; }
.экран-видео .видео-гайд { margin: 0; }
/* Мобильная версия ролика — вертикальная, и в первом экране ей нельзя
   давать вырасти во весь рост колонки: рядом стоит текст, и кадр 9:16
   высотой в полтора экрана оттеснил бы вниз всё остальное. Тот же предел,
   что у карточек раздела, только мягче по ширине. */
.экран-видео .видео-гайд-медиа.ориент-mobile { max-width: 220px; }

/* ── видео-гайды ──────────────────────────────────────────────────────
   Карточка того же семейства, что `.образец` выше (`.карта`, хвост прижат
   вниз тем же `margin-top: auto`), плюс медиа-блок сверху. */
.видео-гайд { display: flex; flex-direction: column; }
.видео-гайд h3 { margin: 0 0 6px; font-size: 1.06rem; }
.видео-гайд-покаж { margin: 0 0 10px; color: var(--текст-2); }
.видео-гайд-низ { margin-top: auto; }

/* РАЗМЕР ЗАРЕЗЕРВИРОВАН ДО ЗАГРУЗКИ — `aspect-ratio`, а не «подрастёт,
   когда придёт постер»: хэндофф, «Use responsive dimensions or aspect-
   ratio to reserve player space before media loads and prevent layout
   shift». Два разных соотношения — потому что у desktop- и mobile-роликов
   и правда разная нативная геометрия (1920×1080 и 1080×1920, см.
   `DELIVERY_MANIFEST.md`), и растягивать одно под другое строго запрещено
   тем же документом: «never stretch the picture or crop one orientation
   to imitate the other». */
.видео-гайд-медиа {
  position: relative; width: 100%; overflow: hidden;
  border-radius: 10px; background: var(--фон-3); margin-bottom: 14px;
}
.видео-гайд-медиа.ориент-desktop { aspect-ratio: 16 / 9; }
.видео-гайд-медиа.ориент-mobile { aspect-ratio: 9 / 16; max-width: 260px; margin-inline: auto; }
.видео-гайд-медиа video,
.видео-гайд-медиа img.видео-гайд-постер { display: block; width: 100%; height: 100%; object-fit: contain; background: #000; }

/* Заглушка — «neutral Karivox-branded placeholder with the video title and
   play control», пока Андрей не одобрил постер (хэндофф, «Poster
   assets»). Не кадр, не рамка в никуда: подписанный текстом блок. */
.видео-гайд-заглушка {
  display: flex; align-items: center; justify-content: center; text-align: center;
  width: 100%; height: 100%; padding: 18px; box-sizing: border-box;
  background: linear-gradient(135deg, var(--синий), var(--фон-3));
  color: #fff; font-weight: 650; font-size: .98rem;
}
.видео-гайд-плей {
  position: absolute; inset: 0; width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center;
  background: transparent; border: 0; padding: 0; cursor: pointer;
}
.видео-гайд-плей::after {
  content: "▶"; display: flex; align-items: center; justify-content: center;
  width: 56px; height: 56px; border-radius: 50%; padding-inline-start: 4px;
  background: rgba(0,0,0,.55); color: #fff; font-size: 1.25rem;
}
.видео-гайд-плей:hover::after { background: rgba(0,0,0,.75); }

/* Переключатель Desktop/Mobile — кнопки, не вкладки: `role="group"` из
   app.js уже несёт смысл, а `.вкладки` тянет за собой нижнюю черту на всю
   ширину, которая здесь ни при чём. */
/* ── свой выход из полного экрана ─────────────────────────────────────
   Зачем он вообще нужен — в app.js, `завести_видео_гайды`, «ВЫХОД ИЗ
   ПОЛНОГО ЭКРАНА ДОЛЖНО БЫТЬ ВИДНО». Здесь только вид.

   В ОБЫЧНОМ РАЗМЕРЕ кнопка маленькая и в углу кадра: она не должна спорить
   с родной полосой управления, которая стоит снизу. В ПОЛНОМ ЭКРАНЕ —
   крупная, с рамкой и всегда видимая: она и есть та дверь, которой не
   хватало. Не прячется ни через две секунды, ни при неподвижной мыши —
   в этом вся разница с родной. */
.видео-гайд-медиа { position: relative; }
.видео-гайд-фуллскрин {
  position: absolute; top: 8px; right: 8px;
  width: 34px; height: 34px; line-height: 1;
  display: flex; align-items: center; justify-content: center;
  font-size: 1rem; cursor: pointer;
  color: #fff; background: rgba(0,0,0,.55);
  border: 1px solid rgba(255,255,255,.35); border-radius: 8px;
}
.видео-гайд-фуллскрин:hover { background: rgba(0,0,0,.8); }
.видео-гайд-медиа.в-полный-экран .видео-гайд-фуллскрин {
  top: 16px; right: 16px; width: 54px; height: 54px; font-size: 1.6rem;
  background: rgba(0,0,0,.75); border-width: 2px;
}
/* Развёрнутая рамка — это теперь весь экран, и кадр в ней обязан стоять по
   центру на чёрном, а не растянуться на всю ширину, потеряв пропорции.
   `aspect-ratio` с рамки снимается: на весь экран его задаёт сам экран. */
.видео-гайд-медиа.в-полный-экран {
  aspect-ratio: auto; max-width: none; width: 100%; height: 100%;
  background: #000; display: flex; align-items: center; justify-content: center;
}
.видео-гайд-медиа.в-полный-экран video { width: 100%; height: 100%; }

.видео-гайд-переключатель { display: inline-flex; gap: 4px; margin-bottom: 10px; }
.видео-гайд-переключатель button {
  padding: 5px 12px; font-size: .82rem; border-radius: 999px;
  border: 1px solid var(--край-2); background: transparent;
  color: var(--текст-2); cursor: pointer;
}
.видео-гайд-переключатель button[aria-pressed="true"] {
  background: var(--синий); border-color: var(--синий); color: #fff;
}
.видео-гайд-переключатель button[disabled] { opacity: .4; cursor: not-allowed; }

.видео-гайд-субтитры {
  display: flex; align-items: center; gap: 6px; font-size: .85rem; margin-bottom: 2px;
}
.видео-гайд-субтитры-статус { margin: 0 0 8px; }


/* ── переключатель темы у логотипа ──────────────────────────────────
   Он стоит рядом с логотипом на каждой странице — и на сайте, и в панели.
   Без рамки: это не действие вроде «войти», а мелкий переключатель вида,
   и обводить его в коробку значит требовать к нему внимания, которого он
   не стоит. */
.знак-блок { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }

.тема-кнопка {
  background: none; border: 0; padding: 4px 6px; cursor: pointer;
  font-size: 1.05rem; line-height: 1; border-radius: 7px;
  color: var(--текст-3);
  transition: color .12s, background .12s;
}
.тема-кнопка:hover { color: var(--текст); background: var(--фон-3); }


/* ── чат помощи ─────────────────────────────────────────────────────
   Кнопка внизу справа, уведомления подняты над ней, чтобы не спорили
   за один угол. */
.уведомления { bottom: 88px; }

.помощь-кнопка {
  position: fixed; inset-inline-end: 20px; bottom: 20px; z-index: 90;
  display: inline-flex; align-items: center; gap: 8px;
  font: inherit; font-size: .93rem; font-weight: 600;
  padding: 11px 18px; border-radius: 99px; cursor: pointer;
  background: var(--синий); color: #fff; border: 0;
  box-shadow: var(--тень-2);
}
.помощь-кнопка span[aria-hidden] {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: 50%;
  background: rgba(255,255,255,.22); font-size: .82rem;
}
.помощь-кнопка:hover { filter: brightness(1.08); }

.помощь-окно {
  position: fixed; inset-inline-end: 20px; bottom: 20px; z-index: 95;
  width: min(390px, calc(var(--ширина-экрана, 100vw) - 40px));
  /* dvh, А НЕ vh — И ЗАПАСНАЯ СТРОКА ПЕРЕД НИМ.
     Окно прибито низом (`bottom: 20px`) и растёт ВВЕРХ, поэтому его потолок
     решает, где окажется шапка, — а в шапке крестик «закрыть». `100vh` меряет
     экран так, будто адресной строки браузера нет; на телефоне она есть, и
     окно выходит выше видимого: крестик уезжает за верхний край, и закрыть
     чат нечем — при том что снизу он виден целиком.
     ВЫЛЕЗАЕТ НЕ ВЕЗДЕ, и потому осталось незамеченным: ветка `620px`
     перекрывает ветку с высотой экрана, пока экран выше 660 точек. Значит
     страдает телефон, повёрнутый набок (видимая высота 330–430), и узкое
     окно на столе, а не обычный телефон стоймя.
     ЗАПАСНАЯ СТРОКА ОБЯЗАТЕЛЬНА: `dvh` понимают браузеры с 2022 года, а
     `min()` и `inset-inline-end` по соседству — с 2020-го, то есть файл
     сегодня работает и там, где `dvh` не знают. Браузер постарше не поймёт
     вторую строку и оставит первую; выброси её — и он останется БЕЗ потолка
     вовсе, а это хуже сегодняшнего. */
  max-height: min(620px, calc(100vh - 40px));
  max-height: min(620px, calc(100dvh - 40px));
  display: flex; flex-direction: column;
  background: var(--фон-2); border: 1px solid var(--край);
  border-radius: 16px; box-shadow: var(--тень-2); overflow: hidden;
}
.помощь-шапка {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 16px; border-bottom: 1px solid var(--край);
  background: var(--фон-3);
}
.помощь-шапка b { font-size: 1rem; }
.помощь-лид {
  margin: 0; padding: 12px 16px; font-size: .82rem; line-height: 1.5;
  color: var(--текст-3); border-bottom: 1px solid var(--край);
}
.помощь-лента {
  flex: 1 1 auto; overflow-y: auto; padding: 14px 16px;
  display: flex; flex-direction: column; gap: 10px; min-height: 120px;
}
.помощь-реплика {
  padding: 10px 13px; border-radius: 12px; font-size: .9rem; line-height: 1.55;
  max-width: 88%; white-space: pre-wrap;
}
.помощь-реплика.мой {
  align-self: flex-end; background: var(--синий); color: #fff;
  border-bottom-right-radius: 4px;
}
.помощь-реплика.его {
  align-self: flex-start; background: var(--фон-3); color: var(--текст);
  border-bottom-left-radius: 4px;
}
.помощь-реплика.сбой { background: var(--красный-фон); color: var(--красный); }
.помощь-низ {
  display: flex; gap: 8px; padding: 12px 16px;
  border-top: 1px solid var(--край);
}
.помощь-низ input { flex: 1 1 auto; }
.помощь-почта {
  margin: 0; padding: 0 16px 12px; font-size: .78rem; color: var(--текст-3);
}
.помощь-почта a { color: var(--текст-3); text-decoration: underline; }

@media (max-width: 560px) {
  .помощь-окно { right: 10px; left: 10px; bottom: 10px; width: auto; }
  .помощь-кнопка { inset-inline-end: 12px; bottom: 12px; }
}


/* Почта — самое длинное в таблице пользователей, и именно она распирала её
   вбок. Горизонтальной прокрутки в списке людей быть не должно.

   ПРАВКА 09.09.2026: раньше адрес обрезался многоточием, а целиком лежал
   только в подсказке при наведении — то есть скрывался, хоть и не
   прокруткой. Владелец про боковую прокрутку вообще: «его не должно никогда
   ни на каких таблицах». Читать это как «прячь чем угодно, лишь бы не
   полосой» — обманывать себя формальным соблюдением: спрятанный адрес и
   обрезанный многоточием почти неотличимы от него же за прокруткой — в
   обоих случаях человек не видит часть без лишнего действия. Поэтому вместо
   обрезания — перенос по символам: адрес виден целиком, просто в несколько
   строк. `title` остаётся — безобидная подсказка при наведении, хоть
   адрес теперь виден и без неё.

   СЕЛЕКТОР — `table.данные td.почта-ячейка`, А НЕ ГОЛЫЙ `.почта-ячейка`, И
   ЭТО НЕ УКРАШЕНИЕ. Замерено на живой странице 09.09.2026: с голым классом
   правило проигрывало общему `table.данные th, table.данные td { white-space:
   nowrap; }` — тот селектор ЧЕТЫРЕХ уровней специфичности (`table` + `.данные`
   + `td`), «.почта-ячейка» — одного, и specificity решает, а не порядок в
   файле. Пока оба правила соглашались на `nowrap`, разницы никто не видел;
   как только здесь понадобился `normal`, общее правило стало побеждать
   молча — вычислено computed-style на живой странице, а не увидено глазом.
   Тем же приёмом уже написаны `клетка-название`, `клетка-имя`,
   `клетка-статус` рядом — специфичность у всех одна и та же. */
table.данные td.почта-ячейка {
  max-width: 260px;
  white-space: normal;
  overflow-wrap: anywhere;
}


/* Кнопка не шире того, во что её положили.

   Это не про меню, но без этого требование «никакой горизонтальной
   прокрутки» не выполняется. У .кнопка стоит white-space: nowrap, а
   греческое «Δημιούργησε δωρεάν λογαριασμό» в одну строку длиннее
   трёхсотдвадцатипиксельного телефона: подпись не переносится, кнопка
   вылезает из карточки, и вылезает она уже за край экрана — вся страница
   начинает ездить вбок. Правило добавлено отдельным блоком, а не внутри
   .кнопка, чтобы не спорить за одни и те же строки с другими правками. */
.кнопка {
  max-width: 100%;
  white-space: normal;
}


/* Длинное неразрывное слово не должно распирать страницу.

   Тоже не про меню, но из того же требования. На армянском и тамильском
   одно слово в заголовке первого экрана оказывается шире телефона. Колонка
   сетки меряется по min-content, то есть по самому длинному слову, — и
   растягивалась под него вместе со всей страницей: на тамильском до 448
   пикселей при экране в 320, и страница ездила вбок от любого касания.

   min-width: 0 снимает этот распор, а break-word разрешает перенести слово
   там, где иначе оно вылезло бы за край. Ни то, ни другое ничего не меняет
   для текста, который и так помещается.

   Правило нужно всем сеткам, а не только первому экрану: на тамильском
   так же расползались четыре карточки «как это работает» на планшете. */
.экран-сетка > *,
.сетка > *,
.низ-сетка > * { min-width: 0; }
body { overflow-wrap: break-word; }

/* Пара кнопок в углу карточки — «Print» и «Close» у отчёта.
   Стоят вместе нарочно: два действия над одним и тем же блоком, и
   выглядеть они должны парой, а не случайно сошедшимися. */
.кнопки-пара { display: inline-flex; gap: 8px; align-items: center; }

/* ── свёрнутая проп-фирма ────────────────────────────────────────────

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

   ПОЛОСКИ БЕЗ ФОНА И БЕЗ РАМКИ ЗДЕСЬ НЕ ХВАТИЛО БЫ: строка обязана
   выглядеть нажимаемой, иначе человек решит, что это подпись, и станет
   искать кнопку. Отсюда фон, скруглeние и курсор-палец. */
.свёртка-фирмы { margin-top: 18px; }
.свёртка-фирмы > summary {
  cursor: pointer; list-style: none;
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
  padding: 13px 16px; border: 1px solid var(--край);
  border-radius: 14px; background: var(--фон-2);
}
.свёртка-фирмы > summary::-webkit-details-marker { display: none; }
/* Своя стрелка, а не браузерная: браузерная у каждого своя и в списке из
   пяти строк они разъезжались бы по вертикали. */
.свёртка-фирмы > summary::after {
  content: "▾"; margin-inline-start: auto; color: var(--текст-3);
  transition: transform .15s ease;
}
.свёртка-фирмы[open] > summary::after { transform: rotate(180deg); }
.свёртка-фирмы > summary:hover { border-color: var(--синий); }
.свёртка-фирмы > summary b { font-size: 1.02rem; }
/* Карточка внутри уже держит свой отступ сверху; второй сложился бы с
   ним и оторвал таблицу от строки, которой её открыли. */
.свёртка-фирмы > .карта { margin-top: 10px !important; }

/* СТРОКА, КОТОРУЮ НАЗВАЛ АВТОР, В ЛЕСТНИЦЕ РАЗМЕРОВ.

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

   Подсветка, а не жирность: жирная строка в таблице читается как «эта
   лучшая», а она не лучшая — она просто его. */
table.данные tbody tr.строка-автора {
  background: var(--фон-3);
  box-shadow: inset 2px 0 0 var(--синий);
}
table.данные tbody tr.строка-автора:nth-child(even) { background: var(--фон-3); }

/* ── SWING TRADING: СТРАНИЦА BOTS И ДВА РАЗДЕЛА ОТЧЁТА (03.10.2026) ──────

   Все стили раздела — здесь, а не строкой в разметке или в app.js: файл
   отдан заходу Р (SPEC 10.1), и строчный стиль перекрыл бы правило
   таблицы стилей.

   Выбор «Prop firm or trading style» на странице Bots. Пункт «SWING
   TRADING · No prop firm we know allows bots to hold trades overnight»
   длиннее имени фирмы; на 420px он обрезался. 560px — пункт читается
   целиком на настольном экране; на телефоне список родной и ширину берёт
   свою. */
#выбор-фирмы-ботов { max-width: 560px; }

/* Полоса «One strategy, measured two ways» над вкладками отчёта: две
   строки, по одной на раздел. Строка нажимается и открывает свою вкладку,
   поэтому выглядит нажимаемой — рамка, курсор-палец. */
.полоса-разделов { margin: 0 0 14px; display: grid; gap: 8px; }
.полоса-разделов > h4 { margin: 0; }
.полоса-раздела {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  padding: 10px 14px; border: 1px solid var(--край); border-radius: 12px;
  background: var(--фон-2); cursor: pointer; text-align: start;
  font: inherit; color: inherit; width: 100%;
}
.полоса-раздела:hover { border-color: var(--синий); }
.полоса-раздела > b { min-width: 9em; }

/* Две вкладки — «Prop firm» / «Swing trading». Открытая — синяя полоса
   снизу, как у вкладок админки; закрытая — обычный текст. Пояснение под
   вкладками — у каждой своё, видно только у открытой. */
.вкладки-отчёта {
  display: flex; flex-wrap: wrap; gap: 4px; margin: 6px 0 6px;
  border-bottom: 1px solid var(--край);
}
.вкладка-отчёта {
  font: inherit; color: var(--текст-2); background: none; border: 0;
  border-bottom: 3px solid transparent; padding: 10px 14px; cursor: pointer;
}
.вкладка-отчёта[aria-selected="true"] {
  color: var(--текст); border-bottom-color: var(--синий); font-weight: 600;
}
.пояснение-вкладки { margin: 6px 0 16px; }
/* Переехавший из шапки фрагмент «фирма · счёт · лимит дней» открывает
   проп-раздел своей строкой (SPEC 7.1, п.1): тот же узел, что стоял в
   шапке, только теперь — строкой над вердиктом. */
section[data-вид-отчёта="проп"] > .подсказка:first-child {
  display: block; margin: 0 0 12px;
}
/* Строки под рынком в таблице Swing trading и подробности рынка. */
.свой-под-рынком { display: block; margin-top: 2px; }
.свёртка-свой > summary { cursor: pointer; color: var(--текст-2); }
.свёртка-свой[open] > summary { margin-bottom: 6px; }
.свёртка-свой p { margin: 2px 0; }
/* Карта-итог раздела: пары «подпись: число» столбиком. */
.пары-итога { margin: 8px 0 0; padding: 0; list-style: none; }
.пары-итога li { margin: 2px 0; }

@media print {
  /* НА БУМАГЕ — ОБА РАЗДЕЛА, И SWING TRADING С НОВОЙ СТРАНИЦЫ (SPEC 7.1).
     Копию отчёта собирает `печатать` в app.js: снимает «скрыт» с обеих
     секций, раскрывает подробности рынков и «How this is measured». Здесь
     — чтобы общий запрет на details их не утащил, вкладки и полоса (они
     про экран) не печатались, а заголовок раздела встал на новый лист. */
  #печать details.свёртка-свой { display: block; }
  /* Подпись свёртки на листе — заголовком: «How this is measured», «More
     about this market», «The swing trading ladder» без треугольника. */
  #печать details.свёртка-свой > summary { list-style: none; font-weight: 600; }
  #печать details.свёртка-свой > summary::-webkit-details-marker { display: none; }
  #печать .вкладки-отчёта, #печать .полоса-разделов { display: none !important; }
  #печать section[data-вид-отчёта="свой"] {
    break-before: page; page-break-before: always;
  }
  #печать .заголовок-раздела-печати { display: block !important; }
}
/* Заголовок раздела для бумаги — на экране его заменяют вкладки. */
.заголовок-раздела-печати { display: none; }
