/* ==========================================================================
   OTPBox, направление A: бумага и чернила.
   Тёплая бумага, чернильный текст, один акцент из логотипа.
   Порядок файла: токены, база, утилиты, шапка, герой, шкала срока, секции,
   подвал, адаптив, доступность.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Токены
   -------------------------------------------------------------------------- */

:root {
  /* Направление A открывается светлым независимо от системной настройки:
     тема выбирается атрибутом data-theme на <html>, а не медиазапросом.
     Атрибут ставит короткий скрипт в <head> до первой отрисовки, поэтому
     чужая тема не успевает мигнуть. Порядок такой: сохранённый выбор
     человека, если он есть, иначе светлая тема направления. */
  color-scheme: light;

  /* Палитра светлой темы. Второго акцента на странице нет и не будет. */
  --bg: #F3F0E9;
  --surface: #FBFAF7;
  --surface-sunk: #EEEAE0;
  --text: #15171C;
  --muted: #6A6558;
  --line: #E3DED2;
  --line-strong: #CFC7B6;
  --accent: #2749D6;
  --accent-ink: #1E3AAE;
  --on-accent: #FBFAF7;
  /* Тонировка обязана читаться на экране, а не только в коде: ячейки бенто
     отличаются ею от соседей, поэтому она заметно плотнее обычной подсветки. */
  --tint: rgba(39, 73, 214, 0.07);
  --tint-strong: rgba(39, 73, 214, 0.10);

  /* Тени тонированы тёплым коричневым, а не чёрным: на бумажном фоне
     нейтральная чёрная тень выглядит грязным пятном. */
  --shadow-flat: 0 1px 0 rgba(84, 70, 44, 0.05);
  --shadow-lift: 0 1px 2px rgba(84, 70, 44, 0.06), 0 10px 28px rgba(84, 70, 44, 0.08);
  --shadow-deep: 0 2px 4px rgba(84, 70, 44, 0.08), 0 22px 60px rgba(84, 70, 44, 0.14);

  /* Шрифты свои, файлы и правила @font-face - в assets/fonts/fonts.css. Запасные
     через запятую названы не для красоты: до того, как доедет woff2, текст рисуется
     именно ими, поэтому в списке стоят гарнитуры соседней ширины, а не «sans-serif»
     наугад - иначе первый экран переверстался бы на глазах при подмене.
     Начертания ограничены тем, что лежит в fonts.css: Unbounded 700, Onest 400-600,
     JetBrains Mono 500. Вес вне этого диапазона браузер не нарисует - он возьмёт
     ближайший, и разницы на экране не будет. */
  --font-display: "Unbounded", "Segoe UI", system-ui, sans-serif;
  --font-text: "Onest", "Segoe UI", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;

  /* Шкала кегля. Числами по месту размеры не задаются нигде. */
  /* Кегль первого экрана подобран под реальную ширину Unbounded: каждая из двух
     строк заголовка обязана уместиться в колонку целиком. На телефоне колонка
     равна ширине экрана, на компьютере она вдвое уже, отсюда две разные формулы.
     Запас к измеренной ширине строки держится около 5%: строки не запрещено
     переносить, так что худший случай теперь перенос, а не молчаливый обрез. */
  --t-hero: clamp(1.4rem, 6.2vw, 2.6rem);
  --t-h2: clamp(1.75rem, 3.4vw, 2.75rem);
  --t-h3: clamp(1.15rem, 1.6vw, 1.375rem);
  --t-lead: clamp(1.0625rem, 1.35vw, 1.25rem);
  --t-body: 1rem;
  --t-sm: 0.9375rem;
  --t-xs: 0.8125rem;
  /* Кегль слогана в финале. Потолок подобран под ширину колонки, в которой
     слоган стоит рядом с призывом: самое длинное слово обязано в неё влезать. */
  --t-mega: clamp(1.9rem, 5.8vw, 3.5rem);

  --lh-tight: 1.06;
  --lh-snug: 1.25;
  --lh-body: 1.6;

  /* Шкала отступов */
  --s1: 0.25rem;
  --s2: 0.5rem;
  --s3: 0.75rem;
  --s4: 1rem;
  --s5: 1.5rem;
  --s6: 2rem;
  --s7: 3rem;
  --s8: 4rem;
  --s9: 6rem;

  --wrap: 1180px;
  --pad: clamp(1.125rem, 4vw, 2.5rem);
  --section-y: clamp(3.5rem, 8vw, 7.5rem);
  --header-h: 72px;

  /* Радиус один на весь проект */
  --r-surface: 14px;
  --r-field: 10px;

  --ease: cubic-bezier(0.22, 0.72, 0.2, 1);
}

/* Тёмная тема включается только переключателем в шапке. Значения те же самые,
   что были в направлении раньше: сменился способ включения, а не палитра. */
:root[data-theme="dark"] {
  color-scheme: dark;

  --bg: #14161B;
  --surface: #1B1E25;
  --surface-sunk: #171A20;
  --text: #ECEAE4;
  --muted: #9A968C;
  --line: #2A2E37;
  --line-strong: #3A404C;
  --accent: #7C9BFF;
  --accent-ink: #9DB4FF;
  --on-accent: #12141A;
  /* В тёмной теме та же доля даёт почти невидимый след, поэтому здесь она
     вдвое больше светлой: иначе тонированная ячейка не отличается от белой. */
  --tint: rgba(124, 155, 255, 0.15);
  --tint-strong: rgba(124, 155, 255, 0.22);

  --shadow-flat: 0 1px 0 rgba(0, 0, 0, 0.3);
  --shadow-lift: 0 1px 2px rgba(0, 0, 0, 0.4), 0 10px 28px rgba(0, 0, 0, 0.35);
  --shadow-deep: 0 2px 4px rgba(0, 0, 0, 0.45), 0 22px 60px rgba(0, 0, 0, 0.5);
}

@media (min-width: 720px) {
  :root { --header-h: 76px; }
}

/* --------------------------------------------------------------------------
   2. База
   -------------------------------------------------------------------------- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 1rem);
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-text);
  font-size: var(--t-body);
  line-height: var(--lh-body);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  /* Страховка от случайного горизонтального выезда на узких экранах.
     clip, а не hidden: не ломает position: sticky у шапки. */
  overflow-x: clip;
}

img, svg { display: block; max-width: 100%; }
img { height: auto; }

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.02em;
  margin: 0;
  text-wrap: balance;
}

h1 { font-size: var(--t-hero); line-height: var(--lh-tight); }
h2 { font-size: var(--t-h2); line-height: 1.12; }
h3 { font-size: var(--t-h3); line-height: var(--lh-snug); letter-spacing: -0.01em; }

p { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }

a { color: inherit; text-decoration: none; }

:where(a, button, input, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

::selection { background: var(--tint-strong); }

/* --------------------------------------------------------------------------
   3. Утилиты
   -------------------------------------------------------------------------- */

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--pad);
}

.num {
  font-family: var(--font-mono);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

.icon {
  width: 1em;
  height: 1em;
  flex: none;
  fill: currentColor;
}

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

/* Ссылка «перейти к содержанию» обязана показаться, когда до неё дошли
   табуляцией: невидимая всегда, она бесполезна. */
.visually-hidden:focus-visible {
  position: fixed;
  top: 0.75rem;
  left: 0.75rem;
  width: auto; height: auto;
  margin: 0;
  padding: 0.75rem 1rem;
  clip-path: none;
  overflow: visible;
  z-index: 100;
  background: var(--accent);
  color: var(--on-accent);
  font-size: var(--t-sm);
  font-weight: 600;
  border-radius: var(--r-field);
}

.eyebrow {
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: var(--s3);
}

.lede {
  font-size: var(--t-lead);
  color: var(--muted);
  line-height: 1.55;
  max-width: 58ch;
}

.section { padding-block: var(--section-y); }

.section__head { max-width: 62ch; margin-bottom: clamp(2rem, 4vw, 3.25rem); }
.section__head .lede { margin-top: var(--s4); }

/* Не все секции открываются столбиком «заголовок, под ним лид». Там, где под
   заголовком идёт материал во всю ширину, лид уходит в правую колонку и встаёт
   на одну линию с заголовком. Раскладка включается ниже, в адаптиве. */
.section__head--split { max-width: none; }

/* Появление секций. Прячем только когда работает JS, иначе при отключённом
   скрипте страница осталась бы пустой. */
.js .reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
}
.js .reveal.is-in { opacity: 1; transform: none; }

/* --------------------------------------------------------------------------
   4. Кнопки
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  /* Кнопка не переносится на вторую строку ни в одном языке. */
  white-space: nowrap;
  font-family: var(--font-text);
  font-size: var(--t-sm);
  font-weight: 600;
  line-height: 1;
  padding: 0.875rem 1.25rem;
  border-radius: var(--r-field);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background-color 0.2s var(--ease), border-color 0.2s var(--ease),
              color 0.2s var(--ease), transform 0.2s var(--ease);
}
.btn .icon { font-size: 1.15em; }

.btn--primary { background: var(--accent); color: var(--on-accent); }
.btn--primary:hover { background: var(--accent-ink); }

.btn--ghost {
  background: transparent;
  color: var(--text);
  border-color: var(--line-strong);
}
.btn--ghost:hover { border-color: var(--text); background: var(--tint); }

.btn--small { padding: 0.625rem 0.9375rem; font-size: var(--t-xs); }

.btn:active { transform: translateY(1px); }

/* --------------------------------------------------------------------------
   5. Шапка
   -------------------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}

/* Три колонки, а не поток: знак слева, разделы РОВНО по центру страницы, действия
   справа. В потоке разделы прижимались к действиям своим margin-left, и слева от них
   оставалась дыра во весь остаток строки - шапка читалась как «всё справа». Боковые
   колонки равны (1fr), поэтому центр разделов не зависит ни от ширины логотипа, ни от
   длины кнопок: подменят надпись - середина останется серединой. */
.site-header__inner {
  height: var(--header-h);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--s5);
}

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

   Разделы уходят в подвал, где они повторены целиком, а логотип уменьшается: он
   пропорционален высоте и при 24 px занимает 158 px ширины, то есть почти половину
   строки на узком экране. Вход и регистрация не прячутся ни при каких условиях -
   регистрация здесь главное действие страницы. */
@media (max-width: 480px) {
  .site-header__inner { gap: var(--s2); }
  .site-header__inner .btn--small { padding-inline: var(--s3); }
  .site-header .brand__logo { height: 19px; }
  /* Разделы уходят целиком: их место в подвале, где они повторены. Вместе с ними
     обязана уйти и их колонка: display: none выкидывает элемент из сетки, и действия
     сползали в СРЕДНЮЮ колонку - вход с регистрацией вставали посреди строки, оставляя
     справа сотню пикселей пустоты. Двух колонок на этой ширине и достаточно. */
  .site-header .site-nav { display: none; }
  .site-header__inner { grid-template-columns: 1fr auto; }
}

/* Самые узкие экраны, какие ещё встречаются. Здесь шапка упирается в край даже без
   разделов: с полем в 18 px кнопка регистрации оставляла справа один пиксель вместо
   восемнадцати, и строка выглядела съехавшей. Ужимаем внутренние зазоры и поля кнопки,
   но не саму пару «вход - регистрация»: это то, ради чего шапка существует. */
@media (max-width: 340px) {
  .site-header .header__actions { gap: var(--s1); }
  .site-header .header__actions .theme-toggle { margin-right: var(--s1); }
  .site-header .btn--small { padding-inline: 0.625rem; }
}

/* justify-self обязателен: в сетке шапки ячейка растягивается на всю колонку, и
   ссылка вместе с ней - кликабельной становилась пустота в треть строки, уводившая
   на главную. В подвале и вне сетки правило просто ни на что не влияет. */
.brand {
  display: inline-flex;
  align-items: center;
  color: var(--text);
  flex: none;
  justify-self: start;
}

/* Логотип целиком, той же конструкции, что в кабинете: знак и есть буква O,
   за ней идут «TP» и «Box». Второй буквы O в слове нет и быть не должно.
   Цвета сняты с жёстких значений кабинета и привязаны к токенам темы,
   поэтому логотип живёт и в светлой, и в тёмной. Ширину буквенной части
   держит textLength, так что подстановка чужого шрифта пропорций не ломает. */
.brand__logo { display: block; height: 24px; width: auto; }
.brand__logo .logo-otp { fill: var(--accent); }
.brand__logo .logo-box { fill: var(--muted); }
.site-footer .brand__logo { height: 30px; }

.site-nav { display: flex; align-items: center; gap: var(--s5); justify-self: center; }
.site-nav__link {
  font-size: var(--t-sm);
  font-weight: 500;
  color: var(--muted);
  transition: color 0.2s var(--ease);
}
.site-nav__link:hover { color: var(--text); }

/* Разделы и действия - две разные группы, и зазор между ними обязан быть больше
   внутреннего, иначе «Поддержка» и кнопка темы читаются как соседи одного списка.
   Раньше это делало поле у навигации; теперь их разводит сама сетка - между колонками
   остаётся весь свободный остаток строки. Внутри действий логика та же: тема - это
   настройка вида, вход и регистрация - про аккаунт, поэтому у переключателя свой отступ. */
.header__actions { display: flex; align-items: center; gap: var(--s3); justify-self: end; }
.header__actions .theme-toggle { margin-right: var(--s2); }
.header__login { font-size: var(--t-sm); font-weight: 600; color: var(--text); }
.header__login:hover { color: var(--accent-ink); }

/* --------------------------------------------------------------------------
   6. Первый экран
   -------------------------------------------------------------------------- */

.hero {
  /* Потолок в 660 px нужен, чтобы на большом мониторе экран не растягивался
     в пустоту, а на ноутбуке всё умещалось без прокрутки. */
  min-height: min(calc(100svh - var(--header-h)), 660px);
  display: flex;
  align-items: center;
  padding-block: clamp(2rem, 5vh, 4rem);
  border-bottom: 1px solid var(--line);
}

.hero__inner {
  display: grid;
  gap: clamp(2.5rem, 5vw, 4rem);
  align-items: center;
  width: 100%;
}

/* Каждая строка заголовка живёт в своём блоке: так их ровно две в любом языке.
   Переносы не запрещены нарочно: при подмене гарнитуры строка перенесётся,
   а не обрежется молча по букве (у body стоит overflow-x: clip). */
.hero__title span { display: block; }
.hero__title .hero__title-accent { color: var(--accent-ink); }

.hero__lede {
  margin-top: var(--s5);
  font-size: var(--t-lead);
  color: var(--muted);
  max-width: 46ch;
}

.hero__actions {
  margin-top: clamp(1.5rem, 3vw, 2.25rem);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
}

/* Композиция справа: три слоя разной глубины (их помечает data-depth),
   двигаются за курсором. will-change тут намеренно нет: на отдельные слои
   композитора их выносит скрипт и только когда параллакс включён, поэтому
   на телефоне и при выключенном движении видеопамять не тратится вовсе. */
/* Высота коробки не задана числом: её задаёт сам снимок, который лежит в потоке.
   Заданной высоте пришлось бы угадывать, на сколько ценник перекроет снимок,
   а снимок широкий и его высота меняется вместе с шириной колонки: на одной
   ширине ценник лёг бы внахлёст, на другой встал бы под снимком с пустым полем
   между ними. Ниже 900 пикселей ценник просто идёт следом за снимком, а в
   двухколоночном герое он всплывает поверх, и отступ снизу там равен той его
   части, которая свешивается ниже кадра. */
.stage {
  position: relative;
  isolation: isolate;
  perspective: 1200px;
}

/* На узком экране слои не выходят за колонку: иначе появляется горизонтальная
   прокрутка. Свесы за край включаются только в двухколоночном герое. */
.stage__grid {
  position: absolute;
  inset: -4% 0 14% 8%;
  z-index: 0;
  border-radius: var(--r-surface);
  background-image:
    linear-gradient(to right, var(--line-strong) 1px, transparent 1px),
    linear-gradient(to bottom, var(--line-strong) 1px, transparent 1px);
  background-size: 34px 34px;
  opacity: 0.55;
  /* Сетка гаснет к краям, чтобы не спорить с рамкой снимка. */
  -webkit-mask-image: radial-gradient(120% 100% at 70% 30%, #000 30%, transparent 78%);
  mask-image: radial-gradient(120% 100% at 70% 30%, #000 30%, transparent 78%);
}

/* ТЕЛЕФОН. Пропорции взяты у настоящего аппарата: 402 x 874 CSS-пикселя — ровно та
   ширина, в которой снят кадр (tools/render_cabinet.py), поэтому внутри рамки лежит
   не подогнанная картинка, а страница кабинета такой, какой её видит человек с
   телефона. Ширина считается тремя ограничителями сразу, и последний важнее всех:
   высота телефона в два с лишним раза больше ширины, и без потолка по высоте экрана
   первый экран на ноутбуке уезжал бы под сгиб. 0.46 = 402/874, то есть перевод
   доступной высоты в ширину.
   В одну колонку рамка НАМЕРЕННО мельче: человек и так смотрит с телефона, и телефон во всю
   ширину телефона выглядит нелепо — снимок должен показывать «вот как это будет», а не
   притворяться самим устройством. */
.phone {
  position: relative;
  z-index: 1;
  margin-inline: auto;
  width: max(9rem, min(13rem, 58%, calc((100svh - var(--header-h) - 11rem) * 0.46)));
}

.phone__body {
  position: relative;
  display: block;
  padding: 2.8%;
  border-radius: 2.4rem;
  /* Графит ТЁПЛЫЙ, а не чёрный. Так рамка держит температуру страницы (у неё
     кремовый тон), а экран внутри остаётся холодным — каким кабинет и есть.
     Смешивать два серых на одном поле нельзя, но граница между ними законна:
     у настоящего телефона она в этом же месте, и глаз на ней не спотыкается.
     Свет сверху слева, как у всех прочих теней страницы. */
  background: linear-gradient(153deg, #3B3730 0%, #221F1B 42%, #302C26 100%);
  box-shadow:
    0 2px 4px rgba(84, 70, 44, 0.10),
    0 26px 64px rgba(84, 70, 44, 0.20),
    inset 0 1px 0 rgba(255, 255, 255, 0.14);
}

/* Кнопки на рёбрах. Мелочь на четыре строки, но без них рамка читается планшетом. */
.phone__body::before,
.phone__body::after {
  content: "";
  position: absolute;
  width: 2px;
  border-radius: 2px;
  background: linear-gradient(180deg, #4A453D, #2B2823);
}
.phone__body::before { left: -2px; top: 27%; height: 7%; }
.phone__body::after { right: -2px; top: 24%; height: 12%; }

.phone__screen {
  position: relative;
  display: block;
  overflow: hidden;
  border-radius: 2rem;
  /* Тот же цвет, что у кадра по краю: полоса состояния и страница под ней должны
     быть одним полем, иначе виден стык. */
  background: #ECEFF6;
  aspect-ratio: 402 / 874;
}
/* Кадр начинается ниже полосы состояния — так страница и лежит на телефоне. */
.phone__screen picture { position: absolute; inset: 6.2% 0 auto 0; }
.phone__screen img { display: block; width: 100%; height: auto; }

.phone__island {
  position: absolute;
  z-index: 1;
  top: 1.5%;
  left: 50%;
  transform: translateX(-50%);
  width: 30%;
  height: 3.4%;
  border-radius: 99px;
  background: #16140F;
}

/* Верхний слой держит ценник: снимок под ним показывает пришедший код, ценник
   говорит, сколько это стоит. Ничего похожего на интерфейс в нём нет, это
   набранная строка прайса: знак сервиса, имя, сумма из снимка каталога.
   На узком экране ценник встаёт под снимок и занимает всю ширину: класть его
   поверх кадра высотой в полторы сотни пикселей значило бы закрыть кадр. */
.stage__tag {
  position: static;
  margin-top: var(--s4);
  z-index: 2;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-surface);
  padding: var(--s4);
  box-shadow: var(--shadow-deep);
  display: grid;
  gap: var(--s3);
}
.stage__tag-head {
  font-size: var(--t-xs);
  color: var(--muted);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 600;
}
.stage__tag-list {
  display: grid;
  gap: var(--s3);
  padding-top: var(--s3);
  border-top: 1px solid var(--line);
}
.stage__tag-row {
  display: grid;
  grid-template-columns: 1.125rem minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--s3);
}
.stage__tag-row .icon { font-size: 1.125rem; color: var(--muted); }
.stage__tag-name { font-size: var(--t-sm); font-weight: 500; }
.stage__tag-price { font-size: 1.0625rem; color: var(--accent-ink); }

/* --------------------------------------------------------------------------
   7. Сигнатура: шкала срока
   -------------------------------------------------------------------------- */

.scale-section { background: var(--surface); border-bottom: 1px solid var(--line); }

.scale {
  margin-top: clamp(2rem, 4vw, 3rem);
}

.scale__track { position: relative; }

.scale__stops { position: relative; }

.stop__price { color: var(--text); }
.stop__term { color: var(--muted); }

.scale__note {
  margin-top: var(--s6);
  color: var(--muted);
  font-size: var(--t-sm);
  max-width: 68ch;
}
.scale__note strong { color: var(--text); font-weight: 600; }

/* Телефон: шкала разворачивается вертикально, длина полосы честно
   пропорциональна сроку. */
.scale__stops { display: grid; gap: var(--s5); }

/* Телефонная раскладка: срок и цена в строке, полоса под ними во всю ширину.
   Так доля срока читается, а не сжимается в узкую колонку. */
.stop {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "term price" "mark mark";
  align-items: baseline;
  gap: var(--s2) var(--s3);
  font-size: var(--t-sm);
}
.stop__term { grid-area: term; }
.stop__price { grid-area: price; }
.stop__mark { grid-area: mark; }

.stop__mark {
  position: relative;
  height: 8px;
  border-radius: 999px;
  background: var(--surface-sunk);
  overflow: hidden;
}
.stop__mark::after {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  /* Ширина полосы равна доле срока от тридцати дней, поэтому двадцать минут
     превращаются в еле заметную засечку. Минимум в 3 px оставлен, чтобы
     засечка вообще была видна. */
  width: max(var(--pos), 3px);
  background: var(--accent);
  border-radius: 999px;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.9s var(--ease);
  transition-delay: calc(var(--i, 0) * 90ms);
}
.is-in .stop__mark::after { transform: scaleX(1); }

.stop--other .stop__mark::after { background: var(--line-strong); }
.stop--other .stop__price { color: var(--muted); font-family: var(--font-text); font-weight: 500; }

/* Под засечкой стоит самая низкая цена срока, поэтому перед суммой идёт «от».
   Слово набирается текстовой гарнитурой: моноширинным оно спорило бы с числом,
   ради которого моноширинный шрифт здесь и стоит. */
.stop__from {
  font-family: var(--font-text);
  font-weight: 500;
  font-size: 0.82em;
  color: var(--muted);
  letter-spacing: 0;
  margin-right: 0.3em;
}

.scale__axis { display: none; }

/* --------------------------------------------------------------------------
   8. Не пришёл код, не платите.
   Главный блок страницы, поэтому он единственный набран панелью во всю ширину
   и кеглем крупнее обычного заголовка секции. Три строки идут по убыванию:
   что делать, что будет если забыть, и честная граница возврата.
   -------------------------------------------------------------------------- */

.promise {
  border: 1px solid var(--line-strong);
  border-radius: var(--r-surface);
  background: var(--surface);
  box-shadow: var(--shadow-lift);
  padding: clamp(1.5rem, 4vw, 3.5rem);
  display: grid;
  gap: clamp(1.5rem, 3vw, 3rem);
  align-items: start;
}
.promise__title {
  font-size: clamp(1.75rem, 3.9vw, 2.75rem);
  line-height: 1.04;
  max-width: 15ch;
}
.promise__body { display: grid; gap: var(--s5); }
.promise__text {
  font-size: var(--t-lead);
  line-height: 1.5;
  max-width: 46ch;
}
.promise__soft {
  color: var(--muted);
  font-size: var(--t-sm);
  max-width: 52ch;
}
/* Граница возврата стоит отдельной строкой под линией: она нужна до оплаты,
   но это одна строка, а не витрина ограничений. */
.promise__edge {
  padding-top: var(--s4);
  border-top: 1px dashed var(--line-strong);
  color: var(--muted);
  font-size: var(--t-xs);
  max-width: 52ch;
}

/* --------------------------------------------------------------------------
   9. Как проходит покупка
   -------------------------------------------------------------------------- */

.flow-section { background: var(--surface); border-block: 1px solid var(--line); }

.flow { display: grid; gap: 0; counter-reset: step; }

.flow__step {
  display: grid;
  grid-template-columns: 3.25rem minmax(0, 1fr);
  gap: var(--s4);
  padding-block: var(--s5);
  border-top: 1px solid var(--line);
  align-items: start;
}
.flow__step:last-child { border-bottom: 1px solid var(--line); }

.flow__num {
  font-family: var(--font-mono);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  font-size: 1.5rem;
  color: var(--accent-ink);
  line-height: 1.2;
}
.flow__body h3 { margin-bottom: var(--s2); }
.flow__body p { color: var(--muted); max-width: 62ch; }

/* --------------------------------------------------------------------------
   10. Цены
   -------------------------------------------------------------------------- */

.prices__caption {
  font-size: var(--t-xs);
  color: var(--muted);
  margin-bottom: var(--s3);
}

/* Прайс не тянет страницу вбок ни на одном экране: ниже 720 px он складывается
   в карточки тем же правилом .tbl-cards, что каталог и таблица сравнения,
   поэтому ни прокручиваемой области, ни минимальной ширины ему не нужно. */
.price-table {
  width: 100%;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}
.price-table th, .price-table td {
  text-align: right;
  padding: 0.75rem 0.25rem;
  border-bottom: 1px solid var(--line);
}
.price-table thead th {
  font-size: var(--t-xs);
  font-weight: 600;
  color: var(--muted);
  letter-spacing: 0.02em;
  border-bottom-color: var(--line-strong);
  padding-bottom: var(--s2);
  white-space: nowrap;
}
.price-table th[scope="row"],
.price-table thead th:first-child {
  text-align: left;
  font-weight: 500;
  font-size: var(--t-sm);
}
.price-table thead th:first-child { font-weight: 600; font-size: var(--t-xs); }
.price-table td {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--t-sm);
  letter-spacing: -0.02em;
  white-space: nowrap;
}
.price-table tbody tr:hover td,
.price-table tbody tr:hover th { background: var(--tint); }

.price-service { display: flex; align-items: center; gap: 0.625rem; }
.price-service .icon { font-size: 1.125rem; color: var(--muted); }
.price-table tbody tr:hover .price-service .icon { color: var(--accent-ink); }

.prices__after {
  margin-top: clamp(1.75rem, 3vw, 2.5rem);
  display: grid;
  gap: var(--s5);
  align-items: center;
}
.prices__facts { display: grid; gap: var(--s3); }
.prices__fact {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--s3);
  font-size: var(--t-sm);
  color: var(--muted);
  align-items: start;
}
.prices__fact .icon { font-size: 1.125rem; color: var(--accent-ink); margin-top: 0.2rem; }

.prices__cta {
  display: inline-flex;
  align-items: center;
  gap: var(--s3);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.25rem, 2.4vw, 1.75rem);
  letter-spacing: -0.02em;
  color: var(--text);
  border-bottom: 2px solid var(--accent);
  padding-bottom: 0.35rem;
  transition: color 0.2s var(--ease);
}
.prices__cta:hover { color: var(--accent-ink); }
.prices__cta .icon { font-size: 0.85em; color: var(--accent); transition: transform 0.2s var(--ease); }
.prices__cta:hover .icon { transform: translate(3px, -3px); }
.prices__cta-block { display: grid; gap: var(--s3); justify-items: start; }
.prices__cta-note { font-size: var(--t-sm); color: var(--muted); }

/* --------------------------------------------------------------------------
   11. Оплата
   -------------------------------------------------------------------------- */

/* Оплата занимает одну полосу: весь разговор о ней укладывается в заголовок и
   абзац рядом, и раздувать его таблицей значений незачем. Полоса поэтому уже
   остальных секций по вертикали. */
.pay-section {
  background: var(--surface);
  border-block: 1px solid var(--line);
  padding-block: clamp(2.5rem, 5vw, 4.5rem);
}

/* Заголовок, под которым ничего нет: нижний отступ ему не нужен. */
.section__head--flat { margin-bottom: 0; }

.spec {
  border: 1px solid var(--line);
  border-radius: var(--r-surface);
  background: var(--bg);
  overflow: hidden;
}
.spec__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3);
  padding: var(--s4) var(--s5);
  border-bottom: 1px solid var(--line);
}
.spec__row:last-child { border-bottom: 0; }
/* В узкой колонке переносится подпись, а не значение: дата со временем,
   разорванная после запятой, читается как две разные строки. */
.spec__key { font-size: var(--t-sm); color: var(--muted); min-width: 0; }
.spec__val {
  font-family: var(--font-mono);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  font-size: var(--t-sm);
  text-align: right;
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   12. Кабинет, бенто
   -------------------------------------------------------------------------- */

/* Секция кабинета намеренно повторяет фон соседней секции оплаты: чередование
   через одну на восьми секциях подряд читается как шаблон. */
.cabinet-section { background: var(--surface); border-block: 1px solid var(--line); }

.bento { display: grid; gap: var(--s4); }

.bento__cell {
  border: 1px solid var(--line);
  border-radius: var(--r-surface);
  padding: clamp(1.25rem, 2.4vw, 1.75rem);
  /* Ячейки лежат на секции цвета поверхности, поэтому сами они утоплены
     в цвет фона: иначе карточки слились бы с секцией. */
  background: var(--bg);
  display: flex;
  flex-direction: column;
  gap: var(--s3);
}
.bento__cell--tint { background: var(--tint); border-color: color-mix(in srgb, var(--accent) 22%, var(--line)); }
.bento__cell h3 { font-size: var(--t-body); font-family: var(--font-text); font-weight: 600; letter-spacing: 0; }
.bento__cell p { color: var(--muted); font-size: var(--t-sm); }

/* Заголовки ячеек бывают в две строки, поэтому знак выравнивается по верху,
   а не по середине: у длинного заголовка середина уезжает вниз. */
.bento__cell-head { display: flex; align-items: flex-start; gap: var(--s3); }
.bento__cell-head .icon { font-size: 1.25rem; color: var(--muted); margin-top: 0.1rem; }

/* Полоса со снимком кабинета во всю ширину бенто. Кадр меняется вместе с
   шириной, потому что один и тот же кадр не может быть читаемым и в 1100, и в
   310 пикселей: широкий снимок целиком там, где есть ширина, и крупная
   карточка номера там, где её нет. Оба файла сняты с одного экрана кабинета. */
.bento__shot {
  display: block;
  margin-top: var(--s2);
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--r-field);
  background: var(--surface-sunk);
  /* Узкий экран: то же окно 1120x395 крупного кадра, что и в герое. */
  aspect-ratio: 1120 / 395;
}
/* picture по умолчанию строчный, и внутри окна с обрезкой он добавил бы
   лишнюю строку под картинкой. */
.bento__shot picture { display: block; }
.bento__shot img {
  display: block;
  width: 175%;
  max-width: none;
  margin-left: -8.036%;
  margin-top: -22.768%;
}

/* Оговорка о стенде стоит рядом со снимком, а не под каждой картинкой:
   на снимке настоящий интерфейс, но номер и сообщение демонстрационные,
   и об этом честнее сказать прямо. */
.bento__shot-note {
  margin-top: var(--s3);
  color: var(--muted);
  font-size: var(--t-xs);
  line-height: 1.5;
}

/* Ячейка со снимком не несёт заголовка: строчка про коды стоит в соседней
   ячейке над ней, а снимок ровно её и показывает. */
.bento__cell--shot { gap: var(--s3); }
.bento__cell--shot .bento__shot { margin-top: 0; }

/* --------------------------------------------------------------------------
   13. Финальный призыв
   -------------------------------------------------------------------------- */

.final { border-top: 1px solid var(--line); }

.final__inner { display: grid; gap: clamp(2rem, 4vw, 3.5rem); align-items: end; }
.final__text { margin-top: var(--s4); max-width: 44ch; color: var(--muted); font-size: var(--t-lead); }
.final__actions { margin-top: clamp(1.75rem, 3vw, 2.5rem); display: flex; flex-wrap: wrap; gap: var(--s3); }

/* --------------------------------------------------------------------------
   14. Подвал
   -------------------------------------------------------------------------- */

.site-footer {
  border-top: 1px solid var(--line);
  background: var(--surface);
  padding-block: clamp(2.5rem, 5vw, 4rem) var(--s6);
}

.footer__top { display: grid; gap: clamp(2rem, 4vw, 3rem); }
.footer__about { max-width: 34ch; }
.footer__about p { margin-top: var(--s4); color: var(--muted); font-size: var(--t-sm); }

.footer__cols { display: grid; gap: var(--s6); }
.footer__col h3 {
  font-family: var(--font-text);
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: var(--s3);
}
/* Явная колонка нужна, чтобы длинная ссылка переносилась, а не растягивала
   ячейку подвала за край страницы. */
.footer__col ul { display: grid; gap: var(--s2); grid-template-columns: minmax(0, 1fr); }
/* Перенос по буквам: длинное слово в узкой колонке подвала иначе растянет её за край. */
.footer__col a { font-size: var(--t-sm); color: var(--text); overflow-wrap: break-word; transition: color 0.2s var(--ease); }
.footer__col a:hover { color: var(--accent-ink); }


/* Переключатель темы. Набран теми же линиями и тем же радиусом, что кнопки
   языка рядом, и держит их высоту: в шапке это одна пара органов управления,
   а не два разных элемента. В отличие от языка показан на любой ширине,
   иначе с телефона тему не сменить. */
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.125rem;
  height: 2.125rem;
  padding: 0;
  flex: none;
  font-size: 1.125rem;
  color: var(--muted);
  background: var(--bg);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-field);
  cursor: pointer;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease), background-color 0.2s var(--ease);
}
.theme-toggle:hover { color: var(--text); border-color: var(--text); }
.theme-toggle .icon { width: 1em; height: 1em; }

/* --------------------------------------------------------------------------
   15. Адаптив
   -------------------------------------------------------------------------- */

/* На телефоне в строке шапки остаются знак, «Цены», тема, вход и регистрация.
   Кнопка регистрации теперь главное действие страницы, поэтому она не прячется:
   вместо неё ужимаются поля и зазоры, а разделы уходят в подвал. */
@media (max-width: 719px) {
  .site-nav__link--desktop { display: none; }
  .site-nav { gap: var(--s4); }
  .site-header__inner { gap: var(--s4); }
  .header__actions { gap: var(--s2); }
  .header__cta { padding: 0.5rem 0.6875rem; }
}

@media (min-width: 720px) {
  .brand__logo { height: 26px; }
}

@media (min-width: 560px) {
  /* Четыре текстовых ячейки ложатся в два ряда по две, снимок и ячейка про
     передачу номера идут во всю ширину: пустых мест в сетке не остаётся. */
  .bento { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .bento__cell--band, .bento__cell--d { grid-column: span 2; }
}

@media (min-width: 720px) {
  .flow__step { grid-template-columns: 4.5rem minmax(0, 1fr); gap: var(--s5); }
  .flow__num { font-size: 1.875rem; }
  .prices__after { grid-template-columns: minmax(0, 1fr) auto; gap: var(--s7); }
  .price-table th, .price-table td { padding: 0.875rem 0.5rem; }
  .footer__top { grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); }
  .footer__cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 900px) {
  .hero__inner { grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr); gap: clamp(2rem, 4vw, 4rem); }
  :root { --t-hero: clamp(2.05rem, 3.7vw, 2.75rem); }

  /* В двухколоночном герое телефон отжат к правому краю, а ценник всплывает
     поверх его левого ребра. Нахлёст здесь по делу: два слоя на разной глубине
     читаются как объём, а рядом стоящие плитки — как список. Ценник ложится на
     нижнюю часть экрана, где у кабинета кнопки, а не номер и не текст SMS. */
  .stage { padding-bottom: 3.5rem; }
  .stage__grid { inset: -10% -4% 12% 10%; }
  .phone {
    margin-inline: auto 0;
    width: max(10.5rem, min(15.5rem, 84%, calc((100svh - var(--header-h) - 10rem) * 0.46)));
  }
  .stage__tag {
    position: absolute;
    left: -8%;
    bottom: 0;
    margin-top: 0;
    width: min(13.5rem, 78%);
  }

  /* Две колонки остались от слогана, который стоял слева. Слоган убран, ребёнок в сетке
     теперь один, и правая колонка была пустой на всех широких экранах. */

  /* Заголовок обещания слева, три строки объяснения справа: панель во всю
     ширину с текстом в один столбец оставляла бы половину поля пустой. */
  .promise { grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); }

  /* Заголовок этой секции длиннее всех прочих на странице, и на общем кегле
     он рассыпался бы на четыре строки. */
  .scale-section .section__head h2 { font-size: clamp(1.6rem, 3.1vw, 2.35rem); }

  /* Заголовок и лид рядом, а не столбиком. */
  .section__head--split {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
    gap: clamp(2rem, 5vw, 4rem);
    align-items: end;
  }
  .section__head--split .lede { margin-top: 0; max-width: 52ch; }

  /* Ширины соседей в ряду разные: 7+5, затем 5+7, а снимок и последняя ячейка
     идут во всю ширину. Одинаковых карточек в ряд не стоит. Последняя ячейка
     широкая не от нехватки соседа: заголовок в ней стоит слева, объяснение
     справа, как в заголовках секций рядом. */
  .bento { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .bento__cell--wide { grid-column: span 7; }
  .bento__cell--a { grid-column: span 5; }
  .bento__cell--band { grid-column: span 12; }
  .bento__cell--b { grid-column: span 5; }
  .bento__cell--c { grid-column: span 7; }
  .bento__cell--d {
    grid-column: span 12;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr);
    gap: clamp(1.5rem, 4vw, 3.5rem);
    align-items: start;
  }
  .bento__cell--d p { max-width: 62ch; }

  /* Здесь под снимок есть тысяча с лишним пикселей, поэтому в кадр входит
     весь экран кабинета: боковое меню, заголовок, карточка активного номера
     с кодом и кнопкой копирования и завершённая аренда под ней. Окно
     1482x512 отсекает у файла правые 86 пикселей с обрезанной плашкой
     баланса, 1568/1482 = 105.803%. */
  .bento__shot { aspect-ratio: 1482 / 512; }
  .bento__shot img { width: 105.803%; margin-left: 0; margin-top: 0; }
}

/* Горизонтальная шкала включается там, где для неё есть ширина. */
@media (min-width: 800px) {
  .scale__track { padding-block: 0; }

  .scale__axis {
    display: block;
    position: relative;
    height: 5px;
    margin-inline: 3.25rem;
    background: var(--surface-sunk);
    border-radius: 999px;
    overflow: hidden;
  }
  /* Акцентом залита только та часть шкалы, которую мы действительно продаём:
     от трёх дней и правее. Слева от засечки полоса остаётся серой. */
  .scale__axis::after {
    content: "";
    position: absolute;
    inset: 0 0 0 10%;
    background: var(--accent);
    border-radius: 999px;
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 1.1s var(--ease);
  }
  .is-in .scale__axis::after { transform: scaleX(1); }

  .scale__stops {
    display: block;
    position: relative;
    height: 5.5rem;
    margin-inline: 3.25rem;
  }

  .stop { display: contents; }

  /* На десктопе каждая засечка стоит на своей честной доле от тридцати дней:
     --pos задан в разметке как процент, поэтому шкала линейная, а не рисованная. */
  .stop__mark {
    position: absolute;
    left: var(--pos);
    top: 0;
    width: 1px;
    height: 1.625rem;
    background: var(--line-strong);
    border-radius: 0;
    overflow: visible;
    opacity: 0;
    transition: opacity 0.5s var(--ease);
    transition-delay: calc(var(--i, 0) * 90ms + 250ms);
  }
  .stop__mark::after { content: none; }
  .is-in .stop__mark { opacity: 1; }

  .stop__term, .stop__price {
    position: absolute;
    left: var(--pos);
    transform: translateX(-50%);
    white-space: nowrap;
    opacity: 0;
    transition: opacity 0.5s var(--ease);
    transition-delay: calc(var(--i, 0) * 90ms + 250ms);
  }
  .is-in .stop__term, .is-in .stop__price { opacity: 1; }

  .stop__term { top: 2rem; font-size: var(--t-sm); font-weight: 500; }
  .stop__price { top: 3.5rem; font-size: 1.0625rem; }

  /* Двадцать минут стоят почти в нуле, поэтому их подпись поднимается над
     осью и прижимается влево: центрированная вылезла бы за край. */
  .stop--other .stop__mark { top: -1.5rem; height: 1.25rem; background: var(--line-strong); }
  .stop--other .stop__term { top: -3.75rem; transform: none; }
  .stop--other .stop__price { top: -2.25rem; transform: none; font-size: var(--t-xs); }

  .scale__stops { margin-top: 0; }
  .scale__track { padding-top: 4.5rem; }
}

@media (min-width: 1000px) {
  .footer__cols { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (min-width: 1040px) {
  .scale__axis, .scale__stops { margin-inline: 4rem; }
}

/* --------------------------------------------------------------------------
   16. Доступность и предпочтения движения
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    transition-delay: 0ms !important;
  }
  .js .reveal { opacity: 1; transform: none; }
  .stop__mark::after { transform: scaleX(1); }
  .scale__axis::after { transform: scaleX(1); }
  .stop__mark, .stop__term, .stop__price { opacity: 1; }
}

/* При запросе повышенного контраста поднимаем только вторичный текст и линии:
   акцент и фон уже проходят AA, менять их незачем. */
@media (prefers-contrast: more) {
  :root { --muted: #4A4638; --line: #C9C2B2; --line-strong: #9E967F; }
}

@media (prefers-contrast: more) {
  :root[data-theme="dark"] { --muted: #C3BFB5; --line: #3C424E; --line-strong: #59606F; }
}

/* ==========================================================================
   17. Внутренние страницы: прайс и вопросы.
   Всё, что ниже, добавлено для pricing.html и faq.html. Токены, шапка,
   подвал и кнопки взяты те же, что на главной, ничего выше не переписано.
   ========================================================================== */

/* Текущая страница в шапке. Подчёркивание, а не точка перед пунктом. */
.site-nav__link[aria-current="page"] {
  color: var(--text);
  font-weight: 600;
  box-shadow: 0 1px 0 var(--accent);
}

/* --------------------------------------------------------------------------
   17.1 Шапка внутренней страницы
   -------------------------------------------------------------------------- */

.page-head {
  padding-block: clamp(2.25rem, 5vw, 3.75rem) clamp(2rem, 4vw, 3rem);
  border-bottom: 1px solid var(--line);
}

.page-head__inner {
  display: grid;
  gap: clamp(1.75rem, 4vw, 3rem);
  align-items: start;
}

.page-head__lede { margin-top: var(--s5); }

.page-head__note {
  margin-top: var(--s5);
  color: var(--muted);
  font-size: var(--t-sm);
  max-width: 60ch;
}

.page-head__spec { background: var(--surface); }

/* Правая колонка страницы вопросов набрана не таблицей «ключ - значение», как
   на странице цен, а тремя числами: другой разговор, другой ритм. */
.keynums {
  display: grid;
  border: 1px solid var(--line);
  border-radius: var(--r-surface);
  background: var(--surface);
  overflow: hidden;
}
.keynum { padding: var(--s5); border-bottom: 1px solid var(--line); }
.keynum:last-child { border-bottom: 0; }
.keynum__line { display: flex; align-items: baseline; gap: 0.5rem; }
.keynum__val {
  font-size: clamp(1.75rem, 4vw, 2.25rem);
  line-height: 1;
  color: var(--accent-ink);
}
.keynum__unit { font-size: var(--t-body); font-weight: 600; }
.keynum__text { margin-top: var(--s2); color: var(--muted); font-size: var(--t-sm); }

/* --------------------------------------------------------------------------
   17.2 Панель каталога: поиск и порядок
   -------------------------------------------------------------------------- */

.catalog__toolbar { display: grid; gap: var(--s4); }

/* После удаления фильтра стран в ряду управления осталась одна кнопка сортировки, и она
   занимала собственную строку во всю ширину каталога. Ставим её рядом с полем поиска:
   на телефоне поле и кнопка по-прежнему идут друг под другом. */
@media (min-width: 720px) {
  .catalog__toolbar {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
  }
  .catalog__toolbar > .catalog__quick { grid-column: 1 / -1; }
}

.field { position: relative; display: flex; align-items: center; }

.field__icon {
  position: absolute;
  left: 0.9375rem;
  font-size: 1.125rem;
  color: var(--muted);
  pointer-events: none;
}

.field__input {
  width: 100%;
  font-family: var(--font-text);
  font-size: var(--t-body);
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-field);
  padding: 0.875rem 2.75rem;
  -webkit-appearance: none;
  appearance: none;
  transition: border-color 0.2s var(--ease);
}
.field__input::placeholder { color: var(--muted); opacity: 1; }
.field__input:hover { border-color: var(--text); }
/* Свой крестик уже есть, системный дублировал бы его. */
.field__input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }

.field__clear {
  position: absolute;
  right: 0.5rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  font-size: 1rem;
  color: var(--muted);
  background: transparent;
  border: 0;
  border-radius: var(--r-field);
  cursor: pointer;
}
.field__clear:hover { color: var(--text); background: var(--tint); }

.catalog__controls {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
  align-items: center;
}

/* Свой выпадающий список вместо нативного select. У системного и панель,
   и обводка фокуса приходят из операционной системы: синяя рамка спорит
   с единственным акцентом направления, а панель не знает ни про бумажный фон,
   ни про тёмную тему. Здесь всё рисуется страницей. */
.pick { position: relative; }

.pick__btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  font-family: var(--font-text);
  font-size: var(--t-xs);
  font-weight: 600;
  white-space: nowrap;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-field);
  padding: 0.625rem 0.75rem 0.625rem 0.875rem;
  cursor: pointer;
  transition: border-color 0.2s var(--ease);
}
.pick__btn:hover { border-color: var(--text); }
.pick__btn[aria-expanded="true"] { border-color: var(--text); }
.pick__caret { font-size: 0.875rem; color: var(--muted); transition: transform 0.2s var(--ease); }
.pick__btn[aria-expanded="true"] .pick__caret { transform: rotate(180deg); }

.pick__list {
  position: absolute;
  z-index: 30;
  top: calc(100% + 0.375rem);
  left: 0;
  min-width: 100%;
  max-width: calc(100vw - 2 * var(--pad));
  display: grid;
  gap: 2px;
  padding: 0.3125rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-field);
  background: var(--surface);
  box-shadow: var(--shadow-lift);
}
/* Панель получает фокус, чтобы принимать стрелки, но обводки на ней нет:
   видимый фокус несёт активный вариант внутри, а не рамка вокруг всего списка. */
.pick__list:focus { outline: none; }
.pick__list:focus-visible { outline: none; }

.pick__option {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  white-space: nowrap;
  font-size: var(--t-xs);
  font-weight: 500;
  color: var(--muted);
  padding: 0.4375rem 0.75rem 0.4375rem 0.5rem;
  border-radius: 8px;
  cursor: pointer;
}
.pick__option:hover { color: var(--text); background: var(--tint); }
.pick__option[aria-selected="true"] { color: var(--text); font-weight: 600; }
/* Вариант под стрелками. Обводки нет намеренно: рамка вокруг строки выглядела
   системной и спорила с оформлением панели. Место в списке показывает заливка -
   та же, что при наведении мышью, поэтому клавиатура и курсор ведут себя одинаково. */
.pick__option.is-active {
  color: var(--text);
  background: var(--tint);
}
.pick__tick { font-size: 0.875rem; color: var(--accent-ink); visibility: hidden; }
.pick__option[aria-selected="true"] .pick__tick { visibility: visible; }

.catalog__quick {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s2);
}
.catalog__quick-label {
  font-size: var(--t-xs);
  color: var(--muted);
  margin-right: var(--s1);
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-family: var(--font-text);
  font-size: var(--t-xs);
  font-weight: 500;
  white-space: nowrap;
  color: var(--muted);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--r-field);
  padding: 0.3rem 0.625rem;
  cursor: pointer;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease), background-color 0.2s var(--ease);
}
.chip .icon { font-size: 0.9375rem; }
.chip:hover { color: var(--text); border-color: var(--line-strong); background: var(--tint); }

/* --------------------------------------------------------------------------
   17.3 Таблица каталога
   -------------------------------------------------------------------------- */

.catalog__status {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3);
  margin-top: clamp(1.75rem, 3vw, 2.5rem);
  margin-bottom: var(--s3);
}
.catalog__count { font-size: var(--t-sm); font-weight: 600; }
.catalog__count .num { color: var(--accent-ink); }
.catalog__caption { font-size: var(--t-xs); color: var(--muted); max-width: 56ch; }

.catalog__table {
  width: 100%;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}
.catalog__table thead th {
  text-align: right;
  font-size: var(--t-xs);
  font-weight: 600;
  color: var(--muted);
  white-space: nowrap;
  padding: 0.5rem 0.5rem;
  background: var(--bg);
  box-shadow: inset 0 -1px 0 var(--line-strong);
}
.catalog__table thead th:first-child,
.catalog__table thead th:nth-child(2) { text-align: left; }
.catalog__table td,
.catalog__table tbody th { border-bottom: 1px solid var(--line); padding: 0.6875rem 0.5rem; }
.catalog__table tbody tr:hover td,
.catalog__table tbody tr:hover th { background: var(--tint); }

.cat__name { text-align: left; font-weight: 500; font-size: var(--t-sm); }
.cat__row { display: flex; align-items: center; gap: 0.5rem; }

/* Слот знака одинаковый у всех строк: и у тех, где стоит фирменный знак,
   и у тех, где его не существует и рисуется монограмма. Названия от этого
   стоят по одной вертикали на всю тысячу с лишним строк. */
.cat__brand {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 1.5rem;
  height: 1.5rem;
  color: var(--muted);
}
.cat__brand .icon { font-size: 1.125rem; }
.catalog__table tbody tr:hover .cat__brand { color: var(--accent-ink); }

/* Монограмма для сервисов, у которых нет фирменного знака.

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

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

   Кегль крупнее иконочного и вес выше: у буквы штрихов меньше, чем у глифа,
   и при равном размере она выглядела бы легче соседей. */
.cat__brand--mono {
  font-family: var(--font-text);
  font-size: 0.9375rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0;
  padding-top: 0.04em;
}

.cat__label { overflow-wrap: anywhere; }

.cat__geo { text-align: left; font-size: var(--t-xs); color: var(--muted); }

.cat__price {
  text-align: right;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--t-sm);
  letter-spacing: -0.02em;
  white-space: nowrap;
}
/* Сумма и знак валюты идут одним куском: на телефоне строка складывается
   в карточку, и без обёртки флексбокс развёл бы число и знак по краям. */
.cat__sum { display: inline-block; }
/* Знак приглушён, чтобы четыре колонки цен не рябили долларами, но набран
   тем же моноширинным, что и цифры: колонки от него не съезжают. */
.cat__cur { color: var(--muted); }
.cat__cur--pre { margin-inline-end: 0.1ch; }
.cat__cur--post { margin-inline-start: 0.35ch; }

.catalog__empty {
  border: 1px solid var(--line-strong);
  border-radius: var(--r-surface);
  background: var(--surface-sunk);
  padding: clamp(1.5rem, 4vw, 2.5rem);
}
.catalog__empty-title { font-size: var(--t-h3); }
.catalog__empty-q { color: var(--accent-ink); overflow-wrap: anywhere; }
.catalog__empty-text {
  margin-top: var(--s4);
  margin-bottom: var(--s5);
  color: var(--muted);
  font-size: var(--t-sm);
  max-width: 64ch;
}

.catalog__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
  margin-top: var(--s5);
}
.catalog__shown { font-size: var(--t-sm); color: var(--muted); }
.catalog__shown .num { color: var(--text); }
.catalog__more .icon { font-size: 1rem; }
.catalog__sentinel { height: 1px; }

/* Пояснение под таблицей: его читают после цен, а не до них. */
.catalog__note {
  margin-top: var(--s5);
  padding-top: var(--s4);
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: var(--t-sm);
  max-width: 68ch;
}

/* --------------------------------------------------------------------------
   17.4 Что входит в аренду
   -------------------------------------------------------------------------- */

.explain-section { background: var(--surface); border-block: 1px solid var(--line); }
.explain { display: grid; gap: clamp(2rem, 4vw, 3rem); align-items: start; }
.explain__facts { margin-top: var(--s5); gap: var(--s4); }

.incl { display: grid; gap: var(--s3); margin-top: var(--s5); }
.incl__item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--s3);
  align-items: start;
  font-size: var(--t-sm);
  color: var(--muted);
}
.incl__item .icon { font-size: 1rem; margin-top: 0.28rem; }
.incl__yes { color: var(--accent-ink); }

/* --------------------------------------------------------------------------
   17.5 Призыв в конце внутренней страницы
   -------------------------------------------------------------------------- */

.page-cta { border-top: 1px solid var(--line); }
.page-cta__inner { display: grid; gap: clamp(1.5rem, 3vw, 2.5rem); align-items: center; }
.page-cta__text { margin-top: var(--s4); color: var(--muted); max-width: 54ch; }
.page-cta__actions { display: flex; flex-wrap: wrap; gap: var(--s3); }

/* --------------------------------------------------------------------------
   17.6 Страница вопросов
   -------------------------------------------------------------------------- */

.faq__layout { display: grid; gap: clamp(2rem, 4vw, 3rem); align-items: start; }

.faq__nav-title {
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: var(--s3);
}
.faq__nav-list { display: flex; flex-wrap: wrap; gap: var(--s2); }
.faq__nav-link {
  display: inline-block;
  font-size: var(--t-sm);
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: var(--r-field);
  padding: 0.3rem 0.625rem;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.faq__nav-link:hover { color: var(--text); border-color: var(--line-strong); }

.faq__toggle {
  margin-top: var(--s4);
  font-family: var(--font-text);
  font-size: var(--t-xs);
  font-weight: 600;
  color: var(--accent-ink);
  background: transparent;
  border: 0;
  padding: 0 0 2px;
  cursor: pointer;
  text-align: left;
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
}
.faq__toggle:hover { border-bottom-color: var(--accent); }

.faq__group {
  margin-bottom: clamp(2.5rem, 5vw, 3.75rem);
  scroll-margin-top: calc(var(--header-h) + 1.5rem);
}
.faq__group-title {
  display: flex;
  align-items: center;
  gap: var(--s3);
  font-size: clamp(1.375rem, 2.4vw, 1.75rem);
  margin-bottom: var(--s5);
}
.faq__group-icon { font-size: 1.375rem; color: var(--muted); }
.faq__group-lede { margin-top: calc(var(--s2) - var(--s5)); margin-bottom: var(--s5); color: var(--muted); max-width: 62ch; }
.faq__after { margin-top: var(--s5); color: var(--muted); font-size: var(--t-sm); max-width: 68ch; }

.qa { border-top: 1px solid var(--line); }
.qa:last-of-type { border-bottom: 1px solid var(--line); }
.qa__q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
  padding: var(--s4) 0;
  font-family: var(--font-text);
  font-size: var(--t-body);
  font-weight: 600;
  cursor: pointer;
  list-style: none;
  transition: color 0.2s var(--ease);
}
.qa__q::-webkit-details-marker { display: none; }
.qa__q:hover { color: var(--accent-ink); }
/* summary тоже не попал в общее правило фокуса выше по файлу. */
.qa__q:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.qa__mark { font-size: 1rem; color: var(--muted); flex: none; transition: transform 0.25s var(--ease); }
.qa[open] .qa__mark { transform: rotate(180deg); }
.qa__a { padding-bottom: var(--s5); }
.qa__a p { color: var(--muted); font-size: var(--t-sm); max-width: 74ch; }
.qa__note {
  margin-top: var(--s3);
  padding-top: var(--s3);
  border-top: 1px dashed var(--line-strong);
}

.versus { width: 100%; border-collapse: collapse; margin-top: var(--s5); }
.versus th, .versus td {
  text-align: left;
  vertical-align: top;
  font-size: var(--t-sm);
  padding: 0.75rem 0.875rem;
  border-bottom: 1px solid var(--line);
}
.versus thead th {
  font-family: var(--font-text);
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0;
  color: var(--muted);
  border-bottom-color: var(--line-strong);
}
.versus tbody th { font-weight: 500; color: var(--muted); width: 24%; }
.versus td { color: var(--muted); }
.versus .versus__ours { color: var(--text); background: var(--tint); }
.versus thead .versus__ours { color: var(--accent-ink); }

.help-block {
  margin-top: clamp(2rem, 4vw, 3rem);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-surface);
  background: var(--surface-sunk);
  padding: clamp(1.25rem, 3vw, 2rem);
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--s4);
  align-items: start;
}
.help-block__icon { font-size: 1.5rem; color: var(--accent-ink); margin-top: 0.2rem; }
.help-block__title { font-size: var(--t-h3); }
.help-block__text { margin-top: var(--s3); color: var(--muted); font-size: var(--t-sm); max-width: 62ch; }
.help-block__actions { margin-top: var(--s5); display: flex; flex-wrap: wrap; gap: var(--s3); }

/* На узком экране «Написать в поддержку» с полями кнопки шире своей колонки и вылезала
   за сетку, давая странице горизонтальную прокрутку. Кнопки в этом блоке занимают всю
   ширину: длина надписи перестаёт что-либо решать, и попасть по ним пальцем проще. */
@media (max-width: 380px) {
  .help-block__actions { flex-direction: column; align-items: stretch; }
  .help-block__actions .btn { width: 100%; justify-content: center; }
}

/* --------------------------------------------------------------------------
   17.7 Таблицы, которые на телефоне превращаются в карточки.
   Ни одна из них не уезжает за край: горизонтальной прокрутки нет вовсе.
   -------------------------------------------------------------------------- */

@media (max-width: 719px) {
  .tbl-cards,
  .tbl-cards tbody,
  .tbl-cards tr,
  .tbl-cards td,
  .tbl-cards th { display: block; }

  .tbl-cards thead { display: none; }

  .tbl-cards tr {
    border: 1px solid var(--line);
    border-radius: var(--r-surface);
    background: var(--surface);
    padding: var(--s4);
    margin-bottom: var(--s3);
  }
  .tbl-cards tr:hover td,
  .tbl-cards tr:hover th { background: transparent; }

  .tbl-cards td,
  .tbl-cards tbody th { border: 0; padding: 0; }

  .tbl-cards tbody th {
    text-align: left;
    font-size: var(--t-body);
    font-weight: 600;
    color: var(--text);
    width: auto;
    margin-bottom: var(--s3);
  }

  .tbl-cards td[data-label] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--s4);
    padding: 0.375rem 0;
    border-top: 1px solid var(--line);
  }
  .tbl-cards td[data-label]::before {
    content: attr(data-label);
    flex: none;
    font-family: var(--font-text);
    font-size: var(--t-sm);
    font-weight: 400;
    letter-spacing: 0;
    color: var(--muted);
  }

  .catalog__table .cat__geo { text-align: right; }
  .versus td.versus__ours { background: transparent; color: var(--text); font-weight: 600; }
}

/* --------------------------------------------------------------------------
   17.8 Раскладка внутренних страниц пошире
   -------------------------------------------------------------------------- */

@media (min-width: 720px) {
  /* Заголовок таблицы держится под шапкой, пока идёт длинный список.
     Обёртка таблицы намеренно без overflow: он отключил бы прилипание. */
  .catalog__table thead th { position: sticky; top: var(--header-h); z-index: 2; }
  .catalog__table td,
  .catalog__table tbody th { padding: 0.75rem 0.625rem; }
}

@media (min-width: 820px) {
  .page-cta__inner { grid-template-columns: minmax(0, 1fr) auto; }
}

@media (min-width: 880px) {
  .page-head__inner { grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr); gap: clamp(2rem, 5vw, 4rem); }
}

@media (min-width: 900px) {
  .explain { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(2.5rem, 5vw, 4rem); }

  .faq__layout { grid-template-columns: minmax(0, 220px) minmax(0, 1fr); gap: clamp(2.5rem, 5vw, 4.5rem); }
  .faq__nav { position: sticky; top: calc(var(--header-h) + 1.5rem); }
  .faq__nav-list { display: grid; gap: 0; }
  .faq__nav-link {
    display: block;
    border: 0;
    border-left: 2px solid var(--line);
    border-radius: 0;
    padding: 0.4375rem 0 0.4375rem 0.875rem;
  }
  .faq__nav-link.is-current { color: var(--text); font-weight: 600; border-left-color: var(--accent); }
}

/* Скрытые скриптом узлы (пустой результат, кнопка «показать ещё», колонки
   лишних сроков) обязаны исчезать, даже если их класс выше задаёт display. */
[hidden] { display: none !important; }

/* --------------------------------------------------------------------------
   17.9 Доводка после проверки в браузере
   -------------------------------------------------------------------------- */

/* Инструмент поиска стоит сразу под шапкой страницы: полный отступ секции
   отодвигал его на экран вниз, а за ним человек сюда и приходит. */
.catalog-section,
.faq-section { padding-block: clamp(1.75rem, 3vw, 2.5rem) var(--section-y); }

@media (min-width: 720px) {
  /* Слово «Сервис» встаёт над названиями, а не над слотом знака:
     0.625rem поля ячейки плюс 2rem на знак и зазор. */
  .catalog__table thead th:first-child { padding-left: 2.625rem; }
}

/* Ячейка сравнения бывает собрана из нескольких кусков (число и слово рядом).
   Обёртка держит их одним куском: без неё карточка на телефоне растаскивает
   куски по всей строке, потому что каждый становится отдельным флекс-элементом. */
.versus__val { display: inline-block; }

@media (max-width: 719px) {
  .versus td[data-label] .versus__val { text-align: right; }
}
