/* Onest — кириллица первым классом, это жёсткое требование для русского текста
   и оно само по себе отсекает большинство модных гарнитур без кириллицы.
   Файлы самохостятся: часть пользователей сидит под ограничением скорости,
   и внешний CDN там либо медленный, либо недоступен. unicode-range оставлен —
   браузер тянет только нужное подмножество, латиница русскому не грузится. */
@font-face {
  font-family: "Onest";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/onest-400-cyrillic-ext.woff2") format("woff2");
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
@font-face {
  font-family: "Onest";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/onest-400-cyrillic.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "Onest";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/onest-400-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Onest";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/onest-400-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Onest";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("fonts/onest-500-cyrillic-ext.woff2") format("woff2");
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
@font-face {
  font-family: "Onest";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("fonts/onest-500-cyrillic.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "Onest";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("fonts/onest-500-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Onest";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("fonts/onest-500-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/jbmono-400-cyrillic-ext.woff2") format("woff2");
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/jbmono-400-cyrillic.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/jbmono-400-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/jbmono-400-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* light-dark() вместо двух наборов переменных и media-запроса: значение выбирается
     по color-scheme, а его переключает кнопка через data-theme на <html>.
     Без этого пришлось бы держать палитру в двух местах и однажды их рассинхронить. */
  color-scheme: light dark;

  --paper:       light-dark(#ffffff, #14140f);
  --ink:         light-dark(#141413, #eceae2);
  --ink-soft:    light-dark(#5c5b57, #9c988c);
  --rule:        light-dark(#dcdcd8, #302e28);
  --rule-strong: light-dark(#b9b9b3, #4a473e);

  /* Сигнальная охра — единственный акцент, и он несёт смысл: этим цветом помечено
     то, что требует внимания или действия. На тёмном фоне исходный #b4531b даёт
     контраст около 3:1 и проваливается, поэтому там она светлее. */
  --signal:      light-dark(#b4531b, #e08a4a);
  --signal-soft: light-dark(#f6ece5, #2a2018);

  /* Только под фактическое состояние узла, больше нигде. */
  --up:   light-dark(#2e7d46, #6bbf83);
  --down: light-dark(#b3261e, #e2685f);

  --text: "Onest", "Helvetica Neue", Arial, sans-serif;
  --mono: "JetBrains Mono", "SF Mono", Menlo, Consolas, monospace;

  --measure: 68ch;
}

:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"]  { color-scheme: dark; }

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

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--text);
  font-size: 16px;
  line-height: 1.55;
  font-feature-settings: "tnum" 1;
}

a {
  color: var(--signal);
  text-decoration: none;
  border-bottom: 1px solid currentColor;
}

a:hover {
  background: var(--signal-soft);
}

.wrap {
  max-width: 940px;
  margin: 0 auto;
  padding: 0 24px;
}

/* --- шапка ------------------------------------------------------------- */

.masthead {
  border-bottom: 2px solid var(--ink);
  padding: 28px 0 18px;
}

.masthead__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
}

.wordmark {
  font-size: 26px;
  font-weight: 500;
  letter-spacing: -0.015em;
  margin: 0;
}

.wordmark a {
  color: inherit;
  border-bottom: 0;
}

.wordmark a:hover {
  background: none;
}

.wordmark span {
  color: var(--signal);
}

.masthead__meta {
  margin: 0;                 /* это <p>: без сброса шапка документов выше главной */
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-soft);
  letter-spacing: 0.02em;
}

/* Правый угол шапки кабинета: «выйти» и переключатель темы. */
.masthead__right {
  display: flex;
  align-items: center;
  gap: 16px;
}

.standfirst {
  margin: 14px 0 0;
  max-width: var(--measure);
  font-size: 19px;
  line-height: 1.45;
}

.standfirst strong {
  font-weight: 500;
}

/* Вход на главной. Шапку он не должен перевешивать: это не призыв к действию,
   а дверь для тех, кто и так пришёл войти. Отсюда сдержанные отступы и обычный
   размер текста — крупная кнопка во весь экран сделала бы из витрины лендинг
   товара, чем она не является. */
/* Шапка витрины: слева что это и сколько стоит, справа вход. Вход не должен
   перевешивать рассказ — отсюда пропорция и разделяющая линейка, а не рамка. */
.lead {
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  gap: 48px;
  margin-top: 18px;
  align-items: start;
}

.lead__sub {
  margin: 12px 0 0;
  max-width: 44ch;
  color: var(--ink-soft);
}

.lead__entry {
  border-left: 1px solid var(--rule);
  padding-left: 32px;
}

.lead__label,
.masthead__login {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.lead__label { margin: 0 0 12px; }
.masthead__login { font-size: 12px; text-decoration: none; border-bottom: 1px solid var(--rule); }
.masthead__login:hover { color: var(--ink); }

/* Три факта в ряд: цена, период, устройства. Моно, чтобы читались как данные,
   а не как ещё один абзац. */
.facts {
  display: flex;
  gap: 28px;
  flex-wrap: wrap;
  margin: 18px 0 0;
  padding-top: 18px;
  border-top: 1px solid var(--rule);
}

.facts dt {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.facts dd { margin: 4px 0 0; font-family: var(--mono); font-size: 22px; }

.entry {
  margin-top: 20px;
  max-width: var(--measure);
}

.entry .alt-lead {
  margin: 16px 0 8px;
}

.entry .field {
  max-width: 320px;
}

.entry__none {
  margin: 16px 0 0;
  font-size: 14px;
}

/* --- кабинет: доступ, шкала месяца, подключение ------------------------- */

/* Главный факт кабинета — дата окончания. Крупная и моноширинная не ради вида:
   за ней сюда и приходят, а в списке определений она читалась наравне с
   расходом трафика. */
.access {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 32px;
  align-items: end;
  margin-top: 18px;
}

.access__label {
  margin: 0;
  font-size: 14px;
  color: var(--ink-soft);
}

.access__date {
  margin: 2px 0 0;
  font-family: var(--mono);
  font-size: 46px;
  line-height: 1.05;
  letter-spacing: -0.02em;
}

.access__none {
  margin: 6px 0 0;
  font-size: 22px;
}

.access__left {
  margin: 10px 0 0;
  font-size: 15px;
  color: var(--ink-soft);
  max-width: 46ch;
}

.access__act {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  text-align: right;
  gap: 8px;
}

.access__ways {
  margin: 0;
  font-size: 13px;
  color: var(--ink-soft);
  max-width: 30ch;
}

/* Шкала оплаченного периода. Число делений равно числу дней, поэтому колонки
   не перечисляем, а раздаём поровну автоматически. */
.monthbar {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 2px;
  height: 26px;
  align-items: end;
  margin-top: 22px;
}

.monthbar i { display: block; }
.monthbar__past { height: 26px; background: var(--ink); }
.monthbar__now  { height: 26px; background: var(--signal); }
.monthbar__next { height: 12px; background: var(--rule); }

.monthbar__legend {
  display: flex;
  justify-content: space-between;
  margin: 6px 0 0;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-soft);
}

/* Табы устройств. Ряд появляется только со скриптом: без него панели идут
   подряд со своими заголовками, и прятать их нечем. */
.tabs__row {
  display: flex;
  align-items: baseline;
  border-bottom: 1px solid var(--rule);
  margin-bottom: 24px;
  flex-wrap: wrap;
}

.tabs__tab {
  appearance: none;
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  padding: 0 18px 10px 0;
  font: inherit;
  font-size: 15px;
  color: var(--ink-soft);
  cursor: pointer;
}

.tabs__tab + .tabs__tab { padding-left: 18px; }
.tabs__tab.is-on { color: var(--ink); font-weight: 500; border-bottom-color: var(--ink); }

.tabs__hint {
  margin-left: auto;
  padding-bottom: 10px;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-soft);
}

.tabpanel__title { margin: 0 0 14px; font-size: 17px; font-weight: 500; }

.connect {
  display: grid;
  grid-template-columns: 1fr 180px;
  gap: 32px;
  align-items: start;
}

.connect__link {
  border-top: 1px solid var(--rule);
  margin-top: 18px;
  padding-top: 16px;
}

.connect__qr {
  border: 1px solid var(--rule);
  padding: 14px;
}

/* Внутри колонки у QR своей рамки быть не должно — рамка тут уже одна. Белая
   подложка остаётся: инвертированный код читают не все камеры, и в тёмной теме
   без неё QR перестаёт сканироваться.

   Вместо рамки — уголки, как в макете: сплошная линия спорит с «тихой зоной»
   кода и мешает камерам, уголки её не трогают. Восемь полосок фоном, по две на
   угол: лишние элементы в разметке ради украшения того не стоят. Цвета заданы
   числами, а не токенами: полоски лежат на белой подложке кода, и в тёмной теме
   светлый var(--ink) на ней исчез бы. */
.connect__qr .qr {
  display: block;
  margin: 0;
  padding: 8px;
  border: 0;

  --mark: 18px;                 /* длина уголка */
  --mark-w: 2px;                /* толщина */
  background-image:
    linear-gradient(#141413 0 0), linear-gradient(#141413 0 0),   /* ↖ */
    linear-gradient(#141413 0 0), linear-gradient(#141413 0 0),   /* ↗ */
    linear-gradient(#141413 0 0), linear-gradient(#141413 0 0),   /* ↙ */
    linear-gradient(#b4531b 0 0), linear-gradient(#b4531b 0 0);   /* ↘ акцентный */
  background-repeat: no-repeat;
  background-size:
    var(--mark) var(--mark-w), var(--mark-w) var(--mark),
    var(--mark) var(--mark-w), var(--mark-w) var(--mark),
    var(--mark) var(--mark-w), var(--mark-w) var(--mark),
    var(--mark) var(--mark-w), var(--mark-w) var(--mark);
  background-position:
    left top, left top,
    right top, right top,
    left bottom, left bottom,
    right bottom, right bottom;
}

.connect__qrlabel {
  margin: 0 0 10px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.connect__qr .muted { margin: 10px 0 0; font-size: 13px; }

.step { margin: 16px 0 8px; }

.invite-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 32px;
  align-items: start;
}

/* Кнопка-ссылка внутри строки определений: «выйти на всех устройствах» — это
   действие, но по весу оно часть предложения, а не отдельная кнопка. */
.inline-form { display: inline; }

.linklike {
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--signal);
  text-decoration: underline;
  cursor: pointer;
}

/* Подвал кабинета — сноска, а не раздел: одна строка вместо двух колонок.
   Проверка подключения отодвинута вправо: она нужна редко, но когда нужна —
   ищут глазами именно с краю. */
.foot__line {
  display: flex;
  gap: 28px;
  flex-wrap: wrap;
  font-size: 14px;
  color: var(--ink-soft);
}

.foot__check { margin-left: auto }

/* Крупный код. Диалог нативный, поэтому подложку и центрирование задаём сами. */
.bigqr {
  border: 1px solid var(--rule);
  background: var(--paper);
  color: var(--ink);
  padding: 24px;
  max-width: 92vw;
}

.bigqr::backdrop { background: rgba(0, 0, 0, .55) }

/* Флекс-колонка, а не auto-поля: у элемента с width:max-content автоматические
   поля не дают диалогу растянуться по содержимому, и он схлопывается в точку. */
.bigqr form {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

.bigqr .qr { margin: 0 }
.bigqr .muted { margin: 0; text-align: center }

/* --- админка: сводка, фильтры, плотная таблица --------------------------- */

.admin__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
}

.filters {
  display: flex;
  align-items: baseline;
  gap: 18px;
  flex-wrap: wrap;
  font-size: 14px;
}

/* Активный фильтр подчёркнут, а не покрашен: цвет в этом интерфейсе уже занят
   состоянием доступа, и второй смысл у него был бы обманом. */
.filters__on {
  text-decoration: none;
  color: var(--ink);
  border-bottom: 2px solid var(--ink);
  padding-bottom: 2px;
}

.filters__off { color: var(--ink-soft); border-bottom-color: transparent; }
.filters__off:hover { color: var(--ink); }

.field--small { font-size: 14px; padding: 5px 9px; max-width: 190px; }

/* Код входа: моноширинный и разреженный, чтобы шесть цифр читались как шесть
   цифр, а не как число. Ширина по содержимому — поле во всю строку под шесть
   символов выглядит как ошибка вёрстки. */
/* Столбики онлайна за сутки. Те же div'ы, что и шкала месяца: ни библиотеки,
   ни canvas, и в тёмной теме это тот же токен, что у остальных «живых» цифр. */
.spark {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 64px;
  margin-top: 20px;
  padding-top: 4px;
  border-bottom: 1px solid var(--rule);
}

.spark i {
  flex: 1;
  min-height: 1px;
  background: var(--ink-soft);
}

.spark i:last-child { background: var(--signal); }


.sub {
  margin: 22px 0 8px;
  font-size: 13px;
  font-weight: 500;
  text-transform: lowercase;
  color: var(--muted);
}


/* Матрица «провайдер × нода»: её читают взглядом по столбцу и по строке,
   поэтому клетки узкие, цифры без хвостов, а цвет несёт основную нагрузку. */
.matrix td,
.matrix th {
  text-align: right;
  padding: 5px 8px;
  white-space: nowrap;
}

.matrix td:first-child,
.matrix th:first-child {
  text-align: left;
  max-width: 240px;
  overflow: hidden;
  text-overflow: ellipsis;
}

.matrix .ok {
  color: var(--muted);
}

.matrix .soso {
  color: var(--signal);
  font-weight: 500;
}

.matrix .bad {
  color: var(--down);
  font-weight: 600;
}

.matrix__foot td {
  border-top: 1px solid var(--rule);
  font-weight: 500;
}

.matrix .row__sub {
  display: block;
  font-size: 10px;
  color: var(--muted);
  font-weight: 400;
}

/* Карточка человека: пары «что — значение» в две колонки. dl, а не таблица —
   это не данные для сравнения строк, а свойства одного объекта. */
.card {
  margin: 0 0 8px;
}

.card > div {
  display: grid;
  grid-template-columns: 180px 1fr;
  gap: 12px;
  padding: 7px 0;
  border-bottom: 1px solid var(--rule);
}

.card dt {
  color: var(--muted);
  font-size: 13px;
  text-transform: lowercase;
}

.card dd {
  margin: 0;
}

.tiny {
  font-size: 11px;
}

@media (max-width: 640px) {
  .card > div {
    grid-template-columns: 1fr;
    gap: 2px;
  }
}

/* Таблица людей: инструменты над ней и строка правки под человеком. Правка
   скрыта по умолчанию — семь кнопок в каждой из полутора сотен строк дают
   стену, а не таблицу. */
.tools {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}

.people th[data-sort] {
  cursor: pointer;
  user-select: none;
}

.people th[data-sort]:hover {
  color: var(--signal);
}

.editor__row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 4px 0;
}

.editor__sep {
  width: 1px;
  height: 20px;
  background: var(--rule);
  margin: 0 4px;
}

.editor__out {
  font-size: 13px;
  min-height: 18px;
}

.note--bad {
  border-left: 2px solid var(--down);
  padding-left: 12px;
}


/* Лента событий человека под строкой в админке. Мелкая и плотная: её читают
   глазами по диагонали, ища момент, о котором говорит клиент. */
.editor__log {
  margin-top: 8px;
  max-height: 320px;
  overflow: auto;
}

.log {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
  font-family: var(--mono, ui-monospace, monospace);
}

.log td {
  padding: 2px 10px 2px 0;
  border: 0;
  vertical-align: top;
}

.log tr:nth-child(even) {
  background: color-mix(in srgb, var(--rule) 25%, transparent);
}

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

.lim__box {
  font-size: 13px;
  color: var(--ink-soft);
  white-space: nowrap;
}

.field--code {
  font-family: var(--mono);
  font-size: 20px;
  letter-spacing: 0.24em;
  max-width: 9ch;
  text-align: center;
}

/* Сводка: четыре числа, которые отвечают на вопрос «есть ли сейчас работа». */
.tally {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
  margin: 22px 0 26px;
  padding-bottom: 22px;
  border-bottom: 1px solid var(--rule);
}

.tally dt {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.tally dd { margin: 6px 0 0; font-family: var(--mono); font-size: 28px; }
.tally--up { color: var(--up); }
.tally--soon { color: var(--signal); }

/* Вторая строка в ячейке: логин под именем, остаток под датой. Это подпись к
   факту, а не отдельная колонка — раньше их было семь и таблица не читалась. */
.row__sub {
  display: block;
  margin-top: 3px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-soft);
}

.row__act { text-align: right; white-space: nowrap; }
.row__act form { display: inline-block; }

.more--inline { display: inline-block; margin-left: 10px; }
.more--inline > summary { font-size: 13px; color: var(--ink-soft); }

@media (max-width: 760px) {
  .tally { grid-template-columns: repeat(2, 1fr); }
}

/* Форма промокода: строка полей, а не столбик — их шесть и все короткие. */
.promo-form {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: center;
  margin: 20px 0 10px;
}

.promo-form .field { margin: 0; width: auto; min-width: 90px }
.promo-form .field[name="code"] { min-width: 130px }
.promo-form .field[name="note"] { min-width: 160px; flex: 1 }

/* --- возврат с оплаты ---------------------------------------------------- */

/* Узкая колонка: на этой странице ровно один факт и одно действие, широкая
   мера чтения тут только мешает искать глазами. */
.done { max-width: 460px; }

.done__label {
  margin: 0;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.done__date {
  margin: 8px 0 0;
  font-family: var(--mono);
  font-size: 34px;
  letter-spacing: -0.02em;
}

.done__lead { margin: 12px 0 0; font-size: 17px; }

/* Полоса ожидания: движение без цифр, потому что честного прогресса у нас нет —
   мы не знаем, сколько банк будет думать. */
.waitbar {
  height: 2px;
  background: var(--rule);
  margin: 20px 0 14px;
  overflow: hidden;
}

.waitbar i {
  display: block;
  height: 2px;
  width: 30%;
  background: var(--signal);
  animation: waitslide 1.6s linear infinite;
}

@keyframes waitslide {
  from { transform: translateX(-100%); }
  to   { transform: translateX(400%); }
}

@media (prefers-reduced-motion: reduce) {
  .waitbar i { animation: none; width: 100%; }
}

/* --- выбор периода и способа оплаты -------------------------------------- */

.choice {
  border: 0;
  padding: 0;
  margin: 0 0 26px;
  max-width: var(--measure);
}

.choice__legend {
  padding: 0;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.choice__row {
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  align-items: baseline;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--rule);
  cursor: pointer;
}

.choice--inline { display: flex; gap: 28px; flex-wrap: wrap; align-items: baseline; }
.choice--inline .choice__legend { flex-basis: 100%; }
.choice--inline .choice__row { border: 0; grid-template-columns: auto auto; }

/* Системная синева переключателей — единственный чужой цвет, который лезет в
   интерфейс сам. Отдаём им акцент страницы. */
.choice input { accent-color: var(--signal); }

.choice__price { font-family: var(--mono); }
.choice__note { font-size: 13px; color: var(--signal); min-width: 11ch; text-align: right; }

@media (max-width: 760px) {
  .lead { grid-template-columns: 1fr; gap: 28px; }
  .lead__entry { border-left: 0; padding-left: 0; border-top: 1px solid var(--rule); padding-top: 22px; }
  .access { grid-template-columns: 1fr; }
  .access__act { align-items: flex-start; text-align: left; }
  .access__date { font-size: 38px; }
  .connect { grid-template-columns: 1fr; }
  .connect__qr { max-width: 200px; }
  .invite-grid { grid-template-columns: 1fr; }
  .choice__note { text-align: left; }
}

/* --- общая сетка секций ------------------------------------------------- */

.section {
  border-bottom: 1px solid var(--rule);
  padding: 30px 0;
}

.section:last-of-type {
  border-bottom: 0;
}

.section__head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin: 0 0 16px;
}

.section__num {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-soft);
  padding-top: 2px;
}

.section__title {
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin: 0;
}

.prose {
  max-width: var(--measure);
}

.prose p {
  margin: 0 0 12px;
}

.prose p:last-child {
  margin-bottom: 0;
}

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

.state {
  font-family: var(--mono);
  font-size: 13px;
  white-space: nowrap;
}

.state--up {
  color: var(--up);
}

.state--down {
  color: var(--down);
}

/* Ждёт, а не сломалось: тот же сигнальный цвет, что у «кончается за 3 дня». */
.state--soon {
  color: var(--signal);
}

.state::before {
  content: "";
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-right: 7px;
  vertical-align: 1px;
  background: currentColor;
}

/* --- шаги --------------------------------------------------------------- */

.steps {
  list-style: none;
  counter-reset: step;
  margin: 0;
  padding: 0;
  max-width: var(--measure);
}

.steps li {
  counter-increment: step;
  position: relative;
  padding: 0 0 14px 40px;
  margin: 0 0 14px;
  border-bottom: 1px solid var(--rule);
}

.steps li:last-child {
  border-bottom: 0;
  margin-bottom: 0;
  padding-bottom: 0;
}

.steps li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: 1px;
  font-family: var(--mono);
  font-size: 13px;
  color: var(--ink-soft);
  border: 1px solid var(--rule-strong);
  width: 24px;
  height: 24px;
  display: grid;
  place-items: center;
}

.steps b {
  font-weight: 500;
}

.pending {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--signal);
  border: 1px solid var(--signal);
  padding: 1px 5px;
  margin-left: 8px;
  white-space: nowrap;
}

/* --- определения (клиенты) ---------------------------------------------- */

.defs {
  margin: 0;
  display: grid;
  grid-template-columns: minmax(140px, 200px) 1fr;
  gap: 0;
  font-size: 15px;
}

.defs dt {
  font-weight: 500;
  padding: 9px 16px 9px 0;
  border-bottom: 1px solid var(--rule);
}

.defs dd {
  margin: 0;
  padding: 9px 0;
  border-bottom: 1px solid var(--rule);
  color: var(--ink-soft);
}

.defs dt:last-of-type,
.defs dd:last-of-type {
  border-bottom: 0;
}

.defs code {
  font-family: var(--mono);
  font-size: 13px;
  color: var(--ink);
}

/* --- врезка ------------------------------------------------------------- */

.note {
  border-left: 2px solid var(--signal);
  padding: 2px 0 2px 16px;
  max-width: var(--measure);
}

.note p {
  margin: 0 0 10px;
}

.note p:last-child {
  margin-bottom: 0;
}

/* --- действие ----------------------------------------------------------- */

.action {
  display: inline-block;
  font-family: var(--text);
  font-size: 16px;
  font-weight: 500;
  color: var(--paper);
  background: var(--ink);
  /* рамка прозрачная, а не нулевая: у второстепенной кнопки она видимая, и без
     этого две кнопки в одном ряду разъезжались бы по высоте на 2px */
  border: 1px solid transparent;
  padding: 10px 20px;
  cursor: pointer;
}

/* Второстепенное действие: запасной способ сделать то же самое. Рядом с главной
   кнопкой должно быть видно, что нажимать в первую очередь. */
.action--quiet {
  color: var(--ink);
  background: none;
  border-color: var(--rule-strong);
}

.action--small {
  font-size: 14px;
  padding: 5px 12px;
}

.action:hover {
  background: var(--signal);
  border-color: var(--signal);
  color: var(--paper);
}

.action:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 2px;
}

/* Выключенная кнопка — сплошная заливка, а не рамка: рамку уже носит
   второстепенная кнопка, и выключенное нельзя путать с «нажми сюда». */
.action[disabled] {
  background: var(--rule);
  color: var(--ink-soft);
  border-color: transparent;
  cursor: not-allowed;
}

.action-row {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 4px;
}

.action-row--spaced {
  margin-top: 18px;
}

.action-row__hint {
  font-size: 14px;
  color: var(--ink-soft);
}

/* --- правовые документы -------------------------------------------------- */

.doc {
  /* только вертикальные: сокращённая запись затирала бы боковые отступы .wrap,
     и на телефоне текст прилипал к краю экрана */
  padding-top: 30px;
  padding-bottom: 10px;
  max-width: 76ch;
}

.doc h2 {
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin: 30px 0 12px;
  padding-top: 22px;
  border-top: 1px solid var(--rule);
}

.doc h2:first-of-type {
  border-top: 0;
  padding-top: 0;
  margin-top: 22px;
}

.doc ol {
  margin: 0;
  padding-left: 0;
  list-style: none;
  counter-reset: clause;
}

.doc ol li {
  counter-increment: clause;
  position: relative;
  padding-left: 44px;
  margin-bottom: 10px;
}

.doc ol li::before {
  content: attr(data-num);
  position: absolute;
  left: 0;
  top: 0;
  font-family: var(--mono);
  font-size: 13px;
  color: var(--ink-soft);
}

.doc__lead {
  font-size: 17px;
  margin: 0 0 6px;
}

.doc__date {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-soft);
  margin: 0 0 22px;
}

.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 15px;
  margin-top: 6px;
}

.data-table th {
  text-align: left;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  padding: 0 14px 8px 0;
  border-bottom: 1px solid var(--rule-strong);
  vertical-align: bottom;
}

.data-table td {
  padding: 9px 14px 9px 0;
  border-bottom: 1px solid var(--rule);
  vertical-align: top;
}

.data-table td:last-child,
.data-table th:last-child {
  padding-right: 0;
}

.back {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.04em;
}

/* --- переключатель темы -------------------------------------------------- */

.theme {
  position: relative;
  width: 30px;
  height: 30px;
  display: inline-grid;
  place-items: center;
  padding: 0;
  color: var(--ink-soft);
  background: none;
  border: 1px solid var(--rule);
  cursor: pointer;
  flex: none;
}

/* Рисуем кнопку в 30px, а пальцем ловим 44px: значок в шапке не должен расти
   ради попадания, но и промахиваться по нему на телефоне нельзя. */
.theme::after {
  content: "";
  position: absolute;
  inset: -7px;
}

.theme:hover {
  color: var(--ink);
  border-color: var(--rule-strong);
}

.theme:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 2px;
}

/* Показываем иконку того состояния, в которое кнопка переключит: в светлой теме
   луна, в тёмной солнце. Здесь нужен media-запрос, потому что light-dark()
   работает только со цветом и переключить display им нельзя. */
.theme .sun  { display: none; }
.theme .moon { display: block; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .theme .moon { display: none; }
  :root:not([data-theme]) .theme .sun  { display: block; }
}

:root[data-theme="dark"]  .theme .moon { display: none; }
:root[data-theme="dark"]  .theme .sun  { display: block; }
:root[data-theme="light"] .theme .moon { display: block; }
:root[data-theme="light"] .theme .sun  { display: none; }

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

.foot {
  border-top: 2px solid var(--ink);
  margin-top: 8px;
  padding: 22px 0 40px;
  font-size: 14px;
}

.foot__cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 22px;
}

.foot h3 {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 0 0 8px;
}

.foot ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.foot li {
  margin-bottom: 5px;
}

.foot__legal {
  margin-top: 22px;
  padding-top: 14px;
  border-top: 1px solid var(--rule);
  color: var(--ink-soft);
  max-width: var(--measure);
}

@media (max-width: 620px) {
  .data-table {
    display: block;
    overflow-x: auto;
    white-space: normal;
  }
  .data-table td,
  .data-table th {
    min-width: 8rem;
  }

  .defs {
    grid-template-columns: 1fr;
  }
  .defs dt {
    border-bottom: 0;
    padding-bottom: 0;
  }
  .standfirst {
    font-size: 17px;
  }
}

/* --- поле ввода --------------------------------------------------------- */

.field {
  font-family: var(--text);
  font-size: 16px;              /* меньше 16px — iOS Safari зумит страницу при фокусе */
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--rule-strong);
  padding: 10px 12px;
  min-width: 0;                 /* иначе flex не даёт полю сжиматься на узком экране */
  flex: 1 1 260px;
}

.field:focus {
  outline: 2px solid var(--signal);
  outline-offset: -1px;
}

.field::placeholder {
  color: var(--ink-soft);
}

.form-row {
  display: flex;
  align-items: stretch;
  gap: 10px;
  flex-wrap: wrap;
  max-width: var(--measure);
}

.form-row--spaced {
  margin-top: 18px;
}

/* Поле с ошибкой помечаем и цветом, и текстом рядом: одного цвета мало, его
   видят не все. */
.field--bad {
  border-color: var(--down);
}

.form-error {
  margin: 10px 0 0;
  font-size: 14px;
  color: var(--down);
  max-width: var(--measure);
}

.alt-lead {
  margin: 22px 0 10px;
}

.defs--spaced {
  margin-top: 20px;
}

.after-list {
  margin-top: 14px;
}

/* --- ссылка приглашения (кабинет) --------------------------------------- */

/* Класс стоял в разметке кабинета, но описан не был — ссылка рисовалась
   браузерным дефолтом и на узком экране упиралась в край. */
.invite-row {
  display: flex;
  /* stretch, а не center: высоты блока и кнопки иначе разъезжаются на несколько
     пикселей, и это меняется от гарнитуры — подбирать отступы бессмысленно */
  align-items: stretch;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 12px;
}

.invite {
  display: flex;
  align-items: center;
  font-family: var(--mono);
  font-size: 14px;
  color: var(--ink);
  background: var(--signal-soft);
  padding: 6px 10px;
  overflow-wrap: anywhere;   /* код приглашения может быть длиннее экрана */
  min-width: 0;
}

/* --- подключение (кабинет) ----------------------------------------------- */

/* Подложка белая в обеих темах и намеренно не берёт переменные: инвертированный
   QR — светлые модули на тёмном — читают не все камеры. */
.qr {
  display: inline-block;
  margin-top: 18px;
  padding: 12px;
  background: #ffffff;
  border: 1px solid var(--rule);
}

/* Размер приходит из svg и здесь не переопределяется: модули нарисованы штрихом
   по полупиксельной сетке, дробное растяжение размывает края. */
.qr svg {
  display: block;
  shape-rendering: crispEdges;
}

/* Запасные приложения нужны меньшинству, поэтому свёрнуты нативным details —
   без единой строчки скрипта. */
.more {
  margin-top: 22px;
  padding-top: 14px;
  border-top: 1px solid var(--rule);
  max-width: var(--measure);
}

.more summary {
  cursor: pointer;
  font-size: 14px;
  color: var(--signal);
}

.more summary:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 2px;
}

/* Одно приложение: имя и три шага. Шаги — те же `.steps`, что на витрине,
   поэтому установка читается так же, как «Как попасть». */
.app {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--rule);
}

.app:first-of-type {
  border-top: 0;
}

.app__name {
  font-size: 16px;
  font-weight: 500;
  margin: 0 0 10px;
}

.app .steps li {
  padding-bottom: 12px;
  margin-bottom: 12px;
}

/* Кнопки внутри шага не должны отрываться от своего текста. */
.app .action-row {
  margin-top: 8px;
}

/* Минимальная версия рядом с приложением: без неё совет поставить приложение
   бесполезен — у части людей стоят сборки старее порога. */
.since {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-soft);
  margin-left: 6px;
  white-space: nowrap;
}

.nowrap {
  white-space: nowrap;
}
