/* Оформление сайта. Без фреймворков; скрипта ровно столько, сколько нужно на
   переключатель темы и появление блоков при прокрутке (см. app.js). Всё
   остальное движение — на CSS: анимации в потоке композитора не трогают
   основной поток и не зависят от того, доехал ли скрипт.

   Тёмная тема по умолчанию идёт за системной настройкой, а кнопка в шапке
   перебивает её вручную.

   Три правила, на которых держится вид, — нарушать их поштучно нельзя, иначе
   блок сразу выпадает из общего ряда:
     1. Теней нет. Совсем. Границу поверхности даёт волосяная линия в 1px.
     2. Радиусы крупные: 20px у карточек, 32px у больших панелей, кнопки —
        пилюли. Мелкий радиус читается как «бутстрап» и ломает ритм.
     3. Поверхности полупрозрачные и с размытием: под ними виден фоновый
        градиент, за счёт этого страница не выглядит плоской заливкой. */

/* ============ Токены ============ */
/* Тема задаётся парами значений в light-dark(), а не вторым списком токенов в
   медиазапросе. Раньше тёмная тема была копией всего блока целиком, и каждый
   новый токен приходилось заводить дважды — расхождения брались ровно оттуда.

   В каждой паре первая строка запасная: браузер, который не знает
   light-dark(), её и оставит — то есть покажет светлую тему, а не сломанную.
   Вторая строка перебивает первую там, где функция понимается. */
:root {
  /* Отсюда light-dark() и узнаёт, какое из двух значений брать. Заодно это
     свойство красит то, что нам не принадлежит, — полосу прокрутки и
     системную часть полей ввода. */
  color-scheme: light dark;

  --bg:        #f5f7fb;
  --bg:        light-dark(#f5f7fb, #080b18);
  --surface:   #ffffff;
  --surface:   light-dark(#ffffff, #121629);
  /* Стекло: сквозь него просвечивает фоновый свет из body::before. */
  --glass:     rgba(255, 255, 255, .70);
  --glass:     light-dark(rgba(255, 255, 255, .70), rgba(18, 22, 41, .70));
  --ink:       #0a0d1e;
  --ink:       light-dark(#0a0d1e, #f8fafc);
  --muted:     #64748b;
  --muted:     light-dark(#64748b, #94a3b8);
  --faint:     #94a3b8;
  --faint:     light-dark(#94a3b8, #64748b);
  --line:      rgba(10, 13, 30, .08);
  --line:      light-dark(rgba(10, 13, 30, .08), rgba(255, 255, 255, .07));
  --line-hard: rgba(10, 13, 30, .16);
  --line-hard: light-dark(rgba(10, 13, 30, .16), rgba(255, 255, 255, .16));
  --accent:    #4f46e5;
  --accent:    light-dark(#4f46e5, #818cf8);
  --accent-2:  #8b5cf6;
  --accent-2:  light-dark(#8b5cf6, #a78bfa);
  --accent-ink:#ffffff;
  --accent-ink:light-dark(#ffffff, #0a0d1e);
  --accent-soft:#eef0ff;
  --accent-soft:light-dark(#eef0ff, #1a1f3a);
  --ok:        #16a34a;
  --ok:        light-dark(#16a34a, #4ade80);
  --danger:    #dc2626;
  --danger:    light-dark(#dc2626, #f87171);

  /* Краски фонового света. В токенах, потому что сам градиент один на обе
     темы и различаются только цвета пятен. */
  --wash-1:    rgba(116, 140, 255, .20);
  --wash-1:    light-dark(rgba(116, 140, 255, .20), rgba(79, 70, 229, .24));
  --wash-2:    rgba(150, 128, 255, .16);
  --wash-2:    light-dark(rgba(150, 128, 255, .16), rgba(139, 92, 246, .18));

  --radius-sm: 12px;
  --radius:    20px;
  --radius-lg: 32px;
  --pill:      999px;
  --wrap:      1200px;
  --narrow:    760px;

  /* Inter подключён в base.html; дальше — системные, чтобы страница читалась
     и до того, как шрифт доедет, и если он не доедет вовсе. */
  --font: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
          "Helvetica Neue", Arial, "Noto Sans", sans-serif;
}

/* Кнопка в шапке выставляет атрибут принудительно; без атрибута страница
   по-прежнему идёт за системной настройкой. Выбор лежит в localStorage и
   применяется скриптом в <head> до первой отрисовки — иначе тёмная страница
   при каждой перезагрузке моргала бы белым. */
: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%; scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: 17px;
  line-height: 1.65;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

/* Фоновый свет. Два мягких пятна по краям вместо плоской заливки: они не
   читаются как «картинка», но убирают ощущение листа бумаги. Слой fixed и
   лежит под содержимым, поэтому при прокрутке не двигается и ничего не ловит
   мышью.

   Пятна медленно дышат. Период в полминуты выбран так, чтобы движение нельзя
   было заметить, глядя в упор: оно работает боковым зрением, а осознанно
   замеченная анимация фона раздражает. Анимируется только transform, поэтому
   всё считает композитор и перерисовки страницы не происходит. */
body::before {
  content: ""; position: fixed; inset: -20%; z-index: -1; pointer-events: none;
  background:
    radial-gradient(55% 100% at 0% 38%, var(--wash-1), transparent 100%),
    radial-gradient(55% 100% at 100% 62%, var(--wash-2), transparent 100%);
  animation: wash-drift 34s ease-in-out infinite;
  will-change: transform;
}
@keyframes wash-drift {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  50%      { transform: translate3d(3%, -2%, 0) scale(1.12); }
}

img { max-width: 100%; height: auto; }

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

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

   text-wrap: balance — про перенос: браузер сам выравнивает строки по длине,
   вместо «длинная строка плюс огрызок». Свойство знают не все браузеры,
   незнающие его просто игнорируют, и заголовок переносится как раньше. */
h1, h2, h3 { margin: 0 0 .5em; }
h1, h2 { text-wrap: balance; }
h1 {
  font-size: clamp(2.4rem, 5.4vw, 4.2rem);
  font-weight: 700; line-height: 1.04; letter-spacing: -0.035em;
}
h2 {
  font-size: clamp(1.75rem, 3.2vw, 2.3rem);
  font-weight: 700; line-height: 1.12; letter-spacing: -0.028em; margin-top: 0;
}
h3 { font-size: 1.15rem; font-weight: 600; line-height: 1.3; letter-spacing: -0.012em; }
.h3 { font-size: 1.4rem; margin-top: 2.4rem; }

p { margin: 0 0 1rem; }
ul, ol { margin: 0 0 1rem; padding-left: 1.2rem; }
li { margin-bottom: .4rem; }

.muted { color: var(--muted); }
.small { font-size: .9rem; }
.centered { text-align: center; }
/* Надпись над заголовком: мелко, вразрядку, заглавными. Служебная строка —
   её замечают, но не читают как текст. */
.eyebrow {
  font-size: .72rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .11em; color: var(--muted); margin-bottom: .9rem;
}
/* pretty — тоже про перенос, но у абзаца: браузер не оставляет одно слово на
   последней строке, а подтягивает к нему предыдущее. */
.lede { font-size: 1.18rem; line-height: 1.7; color: var(--muted); max-width: 46ch; }
.lede, .section-lede { text-wrap: pretty; }

.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 24px; }
.section { padding: 96px 24px; }
.narrow { max-width: var(--narrow); }
.centered-block { text-align: center; }
.centered-block .lede { margin-left: auto; margin-right: auto; }

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

/* ============ Шапка ============ */
.site-head {
  position: sticky; top: 0; z-index: 10;
  background: color-mix(in srgb, var(--bg) 78%, transparent);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line);
}
.head-inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 20px; min-height: 74px;
}
.brand {
  display: inline-flex; align-items: center; gap: 11px;
  font-weight: 700; color: var(--ink); letter-spacing: -0.03em;
}
.brand:hover { text-decoration: none; }
.brand-mark {
  width: 26px; height: 26px; border-radius: 9px;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
}
.nav { display: flex; align-items: center; gap: 26px; flex-wrap: wrap; }
.nav a { position: relative; color: var(--muted); font-size: .95rem; font-weight: 500; }
.nav a:hover { color: var(--ink); text-decoration: none; }
/* Подчёркивание выезжает от левого края. Анимируем transform, а не width:
   ширину браузер пересчитывает раскладкой, и на слабой машине это заметно
   дёргается. */
.nav a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -6px; height: 2px;
  border-radius: 2px; background: var(--accent);
  transform: scaleX(0); transform-origin: left;
  transition: transform .28s cubic-bezier(.4, 0, .2, 1);
}
.nav a:hover::after { transform: scaleX(1); }

/* ============ Переключатель темы ============ */
/* Кнопка одна на обе темы: внутри два значка, наружу торчит тот, который
   соответствует теме, в которую кнопка переключит. */
.theme-toggle {
  /* Сетка, а не флексбокс: оба значка кладутся в одну ячейку и лежат друг на
     друге, поэтому переключение — это поворот с растворением, а не подмена. */
  display: inline-grid; place-items: center;
  width: 38px; height: 38px; padding: 0; flex: none;
  border: 1px solid var(--line-hard); border-radius: 50%;
  background: var(--surface); color: var(--muted);
  cursor: pointer; overflow: hidden;
  transition: color .2s, border-color .2s, transform .2s;
}
.theme-toggle:hover { color: var(--ink); border-color: var(--ink); transform: rotate(18deg); }
.theme-toggle:active { transform: scale(.9) rotate(18deg); }
.theme-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.theme-toggle svg {
  width: 18px; height: 18px; grid-area: 1 / 1;
  transition: opacity .25s, transform .35s cubic-bezier(.4, 0, .2, 1);
}
.icon-moon { opacity: 0; transform: rotate(-90deg) scale(.4); }
:root[data-theme="dark"] .icon-sun  { opacity: 0; transform: rotate(90deg) scale(.4); }
:root[data-theme="dark"] .icon-moon { opacity: 1; transform: none; }

/* ============ Кнопки ============ */
/* Пилюли, а не прямоугольники со скруглением: это самая заметная деталь
   оформления, по ней страница узнаётся раньше, чем по цвету. */
.btn {
  display: inline-block; padding: 14px 28px; border-radius: var(--pill);
  font-size: .95rem; font-weight: 700; border: 1px solid transparent;
  /* Фон гасим в базовом классе, а не в каждом варианте: на <button> браузер
     иначе рисует свой серый, и это видно ровно у тех вариантов, которые фон
     не задают, — btn-link. На <a> тот же класс выглядел нормально. */
  background: none; font-family: inherit; color: var(--ink);
  cursor: pointer; transition: background .15s, border-color .15s, color .15s,
                              transform .15s, opacity .15s;
}
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.btn:hover { text-decoration: none; }
/* Нажатие возвращает кнопку на место и чуть сминает. Без этого подъём при
   наведении выглядит как поломка: кнопка уехала и не реагирует на клик. */
.btn:active { transform: translateY(0) scale(.97); transition-duration: .06s; }

.btn-primary {
  position: relative; overflow: hidden;
  background: var(--accent); color: var(--accent-ink);
}
.btn-primary:hover {
  background: color-mix(in srgb, var(--accent) 88%, black);
  transform: translateY(-2px);
  /* Единственная тень на сайте, и та цветная и только при наведении: не
     изображает высоту, а подсвечивает то, на что человек уже указал. */
  box-shadow: 0 14px 30px -12px color-mix(in srgb, var(--accent) 75%, transparent);
}
/* Блик пробегает слева направо один раз за наведение. Лежит поверх фона, но
   под текстом, поэтому надпись не мутнеет. */
.btn-primary::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(105deg, transparent 35%,
              rgba(255, 255, 255, .28) 50%, transparent 65%);
  transform: translateX(-120%);
  transition: transform .7s cubic-bezier(.4, 0, .2, 1);
}
.btn-primary:hover::after { transform: translateX(120%); }

/* Второстепенная кнопка — белая плашка с волосяной рамкой, не «пустая». Так
   пара кнопок в первом экране читается как одна конструкция. */
.btn-ghost {
  border-color: var(--line-hard); color: var(--ink); background: var(--surface);
}
.btn-ghost:hover { border-color: var(--ink); transform: translateY(-2px); }
.btn-link {
  color: var(--accent); padding-inline: 0; padding-block: 8px;
  font-weight: 600; border-radius: 0;
}
.btn-link:hover { opacity: .7; }
.btn.block { display: block; width: 100%; text-align: center; margin-top: 14px; }
.cta-row { display: flex; gap: 12px; flex-wrap: wrap; margin: 32px 0 16px; }

/* ============ Первый экран ============ */
/* Экран держит высоту сам: содержимого здесь мало, и без min-height слоган
   висел бы полосой посреди пустоты. Вычитаем высоту шапки, чтобы под первым
   экраном оставался край следующей секции — иначе не видно, что страница
   продолжается. Флексом центрируем по вертикали. */
.hero {
  padding: 96px 0 80px;
  min-height: min(72vh, 720px);
  display: flex; align-items: center;
}
.hero-grid {
  display: grid; grid-template-columns: 1.1fr .9fr; gap: 56px; align-items: center;
}
/* Одна колонка по центру и ничего рядом: слоган должен остаться единственным,
   что видно при открытии. Ширина по тексту, а не по странице, — иначе строка
   уезжает на весь монитор и перестаёт читаться. */
/* width сказан явно: внутри флекса ширину иначе считали бы по содержимому, и
   на промежуточных ширинах блок дышал бы вместе с длиной строк. */
.hero-lead { width: 100%; max-width: 940px; margin-inline: auto; text-align: center; }
/* Крупнее обычного h1: на первом экране заголовок и есть содержимое, и в общем
   кегле он тонул в пустом поле вокруг.

   Нижняя граница 2.25rem, а не 2.5rem: замерено — на телефоне в 375 пикселей
   вторая строка на 40 px не укладывается и разваливается на две, а на 36 px
   встаёт целиком. Четыре пикселя кегля против лишней строки. */
.hero-lead h1 { font-size: clamp(2.25rem, 6.4vw, 5.2rem); }
/* Строки заголовка заданы разметкой (см. index.html), поэтому span'ы блочные.
   Вторая — градиентом, тем же, что в квадратике логотипа и на кнопке: тире
   делит фразу на тему и обещание, и переход цвета показывает это делением, а не
   украшением.

   Ширина по содержимому и по центру — не косметика: фон красит рамку элемента,
   а строка короче рамки, и на всю ширину блока градиент показал бы тексту
   только свою середину, потеряв оба конца. */
.hero-title span { display: block; }
.hero-accent {
  width: fit-content; margin-inline: auto;
  /* Запасной цвет для браузера без обрезки фона по тексту — см. @supports ниже. */
  color: var(--accent);
}

/* Градиент по буквам делается фоном, обрезанным по тексту, а сам текст при этом
   прозрачный. Отсюда две страховки. Первая: @supports — браузер, не знающий
   обрезки по тексту, увидел бы прозрачные буквы, то есть пустое место вместо
   заголовка, поэтому прозрачность включается только вместе с обрезкой, а иначе
   строка остаётся акцентного цвета. */
@supports (background-clip: text) or (-webkit-background-clip: text) {
  .hero-accent {
    background-image: linear-gradient(105deg, var(--accent), var(--accent-2));
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
  }
}

/* Вторая страховка: режим повышенной контрастности сам заменяет цвета
   системными, но фон под обрезкой ему не заменить — буквы остались бы
   невидимыми. Возвращаем обычный цвет текста. */
@media (forced-colors: active) {
  .hero-accent {
    background-image: none;
    -webkit-text-fill-color: currentColor;
    color: CanvasText;
  }
}
/* 43ch — по замеру: строке нужно 549 пикселей, а 40ch давали 533, и она рвалась
   на две ради одного слова. Под двухстрочным заголовком лид должен быть одной
   строкой, иначе первый экран превращается в четыре обрывка. */
.hero-lead .lede {
  font-size: 1.32rem; max-width: 43ch; margin-inline: auto;
}
.hero-lead .cta-row { justify-content: center; }

/* Пример уведомления. Слегка приподнят над фоном — чтобы читался как
   сообщение в мессенджере, а не как ещё один блок текста. */
.demo {
  background: var(--glass); backdrop-filter: blur(12px);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg); overflow: hidden;
  /* Карточка едва заметно покачивается — ровно настолько, чтобы читаться как
     всплывшее уведомление, а не как ещё один блок вёрстки. Ход в шесть
     пикселей: больше начинает мешать читать. */
  animation: demo-float 7s ease-in-out infinite;
}
@keyframes demo-float {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-6px); }
}
.demo-head {
  display: flex; align-items: center; gap: 8px;
  padding: 15px 24px; border-bottom: 1px solid var(--line);
  font-size: .72rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .09em; color: var(--muted);
}
/* Точка «на связи» пускает круги, как индикатор входящего сообщения. Два
   кольца со сдвигом в половину периода — так волна идёт непрерывно, а не
   рывками. Кольца нарисованы псевдоэлементами, лишней разметки не нужно. */
.dot {
  position: relative; flex: none;
  width: 8px; height: 8px; border-radius: 50%; background: var(--ok);
}
.dot::before, .dot::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%;
  border: 1px solid var(--ok);
  animation: dot-ring 2.8s cubic-bezier(.2, .6, .3, 1) infinite;
}
.dot::after { animation-delay: 1.4s; }
@keyframes dot-ring {
  0%   { transform: scale(1);   opacity: .8; }
  100% { transform: scale(3.6); opacity: 0; }
}
.demo-body { padding: 24px 26px 28px; }
.demo-title { font-weight: 600; margin-bottom: .2rem; }
.demo-price { font-size: 1.5rem; font-weight: 700; letter-spacing: -.03em; margin-bottom: .6rem; }
.demo-line { margin-bottom: .2rem; font-size: .95rem; }
.demo hr { border: 0; border-top: 1px solid var(--line); margin: 16px 0; }
.verdict { color: var(--ok); font-weight: 600; margin-bottom: .8rem; }
.demo-facts li {
  display: flex; justify-content: space-between; gap: 16px;
  padding: 7px 0; border-bottom: 1px dashed var(--line);
  font-size: .93rem; margin: 0;
}
.demo-facts li:last-child { border-bottom: 0; }
.demo-facts span:first-child { color: var(--muted); white-space: nowrap; }
.demo-facts b { text-align: right; font-weight: 600; }

/* ============ Полосы ============ */
/* Полосы чередуются со страницей не рамкой, а плотностью белого: под стеклом
   фоновый свет глушится, и граница секции видна сама собой. Линий сверху и
   снизу нет намеренно — они дробили страницу на отсеки. */
.band {
  background: var(--glass); backdrop-filter: blur(20px); padding: 96px 0;
}
.band-accent {
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--accent) 7%, transparent),
    color-mix(in srgb, var(--accent-2) 7%, transparent));
  backdrop-filter: none;
}
.section-lede { max-width: 52ch; margin-top: -.2rem; font-size: 1.05rem; }

/* ============ Цифры ============ */
/* Узкая полоса сразу под первым экраном: три числа и подписи. Отдельный отступ,
   потому что это не секция с заголовком, а строка доказательства. */
.proof-band { padding: 40px 0; }
.proof { display: grid; grid-template-columns: repeat(3, 1fr); gap: 32px; }
.proof-item p { margin: 0; }
.proof-num {
  font-size: 2.8rem; font-weight: 700; letter-spacing: -0.04em; line-height: 1.05;
  margin-bottom: .3rem;
}
.proof-item .muted {
  font-size: .78rem; font-weight: 600; text-transform: uppercase; letter-spacing: .08em;
}

/* ============ Объём услуги ============ */
/* Слово крупно, пояснение мелко и приглушённо: пробегая глазами, человек
   читает шесть слов, а подробности берёт только там, где ему интересно. */
.takeover { display: grid; grid-template-columns: repeat(3, 1fr); gap: 30px 40px; margin-top: 36px; }
.takeover li { display: flex; flex-direction: column; gap: 4px; margin: 0; }
.takeover b { font-size: 1.15rem; font-weight: 600; letter-spacing: -.012em; }

/* Перечень мелким шрифтом внутри абзацного текста: конкретика есть, но она
   заведомо тише основной мысли. */
.dashes { list-style: none; padding-left: 2px; }
.dashes li { position: relative; padding-left: 18px; margin-bottom: .3rem; }
.dashes li::before { content: "—"; position: absolute; left: 0; }

/* ============ Кейсы ============ */
.cases { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; margin-top: 36px; }
.case {
  margin: 0; background: var(--glass); backdrop-filter: blur(12px);
  border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden;
}
.case-photo { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block; }
.case-body { padding: 20px 24px 22px; }
.case-body h3 { margin-bottom: .25rem; }
.case-body p { margin: 0; }

/* ============ Шаги ============ */
.steps { list-style: none; padding: 0; display: grid; gap: 32px; margin-top: 40px; }
/* Раскладку задаёт отдельный класс, а не предок вида `.band .steps`: такой
   селектор весит больше и медиазапросов ниже (колонки не схлопывались на
   телефоне), и класса `.steps-inline` — а он теперь встречается внутри полосы. */
.steps-four { grid-template-columns: repeat(4, 1fr); gap: 36px; }
/* Номер и заголовок в одну строку. Раньше номер стоял блоком над текстом, и
   между цифрой и словом зияла пустая строка — на широком экране это выглядело
   как оборванная вёрстка. */
.step-head { display: flex; align-items: center; gap: 12px; margin-bottom: .5rem; }
.step-head h3 { margin: 0; font-size: 1.22rem; }
.step-head .step-num { margin-bottom: 0; flex: none; }
.steps-four p { font-size: 1.02rem; }
.step-num {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 50%;
  background: var(--accent-soft); color: var(--accent);
  font-size: .88rem; font-weight: 700; margin-bottom: 12px;
  transition: background .25s, color .25s, transform .25s;
}
/* Наведение на шаг заливает его номер. Шаг — не ссылка, поэтому отклик
   намеренно слабый: он показывает, что строка живая, но никуда не зовёт. */
.steps li:hover .step-num {
  background: var(--accent); color: var(--accent-ink); transform: scale(1.08);
}
.steps p { margin: 0; }
.steps-inline { grid-template-columns: 1fr; gap: 14px; }
.steps-inline li { display: flex; gap: 14px; align-items: flex-start; }
.steps-inline .step-num { flex: none; margin-bottom: 0; }

/* Этапы услуги. От обычных шагов отличаются тем, что каждый — отдельный товар
   со своей ценой, поэтому у них рамка: взгляд должен видеть границу того, что
   покупается одной суммой. Цену прижимаем вправо через margin-left: auto —
   .step-head и так flex. */
.stages { gap: 24px; margin-top: 20px; }
.stage {
  border: 1px solid var(--line); border-radius: var(--radius-lg);
  padding: 22px 24px;
}
.stage .step-head { flex-wrap: wrap; margin-bottom: .2rem; }
.stage-price { margin-left: auto; font-weight: 700; white-space: nowrap; }
.stage .ticks { margin-top: 12px; }

/* ============ Две колонки ============ */
.split { display: grid; grid-template-columns: 1.15fr .85fr; gap: 64px; align-items: start; }
.split-wide { grid-template-columns: 1.4fr .6fr; }
.side { position: sticky; top: 98px; }

.price-card {
  background: var(--glass); backdrop-filter: blur(12px);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg); padding: 32px;
}
.price { font-size: 2.4rem; font-weight: 700; letter-spacing: -0.04em; line-height: 1.05; margin-bottom: .4rem; }

.ticks { list-style: none; padding: 0; margin: 18px 0 0; }
.ticks li { position: relative; padding-left: 26px; margin-bottom: .55rem; }
.ticks li::before {
  content: ""; position: absolute; left: 4px; top: .62em;
  width: 9px; height: 5px; border-left: 2px solid var(--accent);
  border-bottom: 2px solid var(--accent); transform: rotate(-45deg);
}

/* ============ Карточки услуг ============ */
.cards {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; margin-top: 40px;
}
.card {
  display: block; position: relative; color: inherit;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 30px;
  transition: border-color .15s, transform .15s;
}
.card:hover { text-decoration: none; border-color: var(--accent); transform: translateY(-3px); }
/* Подчёркивание растёт под заголовком слева направо. Сделано фоновой
   картинкой, а не рамкой: анимировать background-size можно, а border-width
   на каждом кадре пересчитывает раскладку. inline-block нужен, чтобы линия
   шла по ширине текста, а не по всей карточке. */
.card h3 {
  display: inline-block; margin-bottom: .5rem;
  background-image: linear-gradient(var(--accent), var(--accent));
  background-repeat: no-repeat; background-position: 0 100%;
  background-size: 0% 2px;
  transition: background-size .38s cubic-bezier(.4, 0, .2, 1);
}
.card:hover h3 { background-size: 100% 2px; }
.card p { margin-bottom: 1rem; font-size: .95rem; }
/* Цена уезжает вправо вместе со стрелкой — карточка отвечает на курсор не
   только рамкой. */
.card-price {
  font-weight: 700; letter-spacing: -.02em; color: var(--ink); margin: 0;
  transition: transform .25s cubic-bezier(.4, 0, .2, 1);
}
.card-price::after {
  content: "→"; display: inline-block; margin-left: .5em;
  color: var(--accent); opacity: 0; transform: translateX(-6px);
  transition: opacity .25s, transform .25s;
}
.card:hover .card-price::after { opacity: 1; transform: none; }
.card-featured { border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.badge {
  position: absolute; top: -11px; left: 28px;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #fff;
  font-size: .66rem; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; padding: 5px 13px; border-radius: var(--pill);
}

/* ============ Вопросы ============ */
.faq { margin-top: 36px; border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  cursor: pointer; padding: 22px 0; font-weight: 600; font-size: 1.05rem;
  letter-spacing: -.012em; list-style: none;
  display: flex; justify-content: space-between; gap: 16px; align-items: center;
}
.faq summary:hover { color: var(--accent); }
.faq summary::-webkit-details-marker { display: none; }
/* Плюс поворачивается на 135° и становится крестом. Подменять символ на «−»
   было нечем анимировать: content не интерполируется. */
.faq summary::after {
  content: "+"; color: var(--muted); font-size: 1.4rem; font-weight: 400;
  line-height: 1; flex: none;
  transition: transform .3s cubic-bezier(.4, 0, .2, 1), color .2s;
}
.faq details[open] summary::after { transform: rotate(135deg); color: var(--accent); }
/* Ответ выплывает. Высоту <details> не анимируем — она неизвестна до
   раскрытия, а трюки с grid-template-rows требуют лишней обёртки в разметке. */
.faq details[open] p { animation: answer-in .35s cubic-bezier(.2, .6, .3, 1) both; }
@keyframes answer-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}
.faq details p { padding-bottom: 22px; margin: 0; max-width: 72ch; }

/* ============ Форма ============ */
.form-section { display: grid; grid-template-columns: 1fr 1fr; gap: 64px; align-items: start; }
.lead-form {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-lg); padding: 32px;
}
.field { margin-bottom: 18px; }
.field label { display: block; font-size: .9rem; margin-bottom: 7px; font-weight: 600; }
.field input, .field textarea, .field select {
  width: 100%; padding: 13px 16px; font: inherit; font-size: .98rem;
  color: var(--ink); background: var(--bg);
  border: 1px solid var(--line-hard); border-radius: 14px;
}
.field textarea { resize: vertical; }
.field input:focus, .field textarea:focus, .field select:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 16%, transparent);
}
/* Подпись группы переключателей. У неё нет своего поля, поэтому это не <label>:
   label без for указывал бы в пустоту, а с for — на один из переключателей. */
.field-label {
  display: block; font-size: .9rem; margin-bottom: 7px; font-weight: 600;
}
/* Внутри группы каждая строка — сама себе label, отступ у него уже свой. */
.field .check { margin-bottom: 8px; }
.field .check + .form-error { margin-top: 0; }
.form-error { display: block; color: var(--danger); font-size: .88rem; margin-top: 6px; }
.form-error-top {
  margin: 0 0 16px; padding: 13px 16px; border-radius: 14px;
  background: color-mix(in srgb, var(--danger) 10%, transparent);
}
.consent { margin: 12px 0 0; }

.form-extra {
  position: absolute; left: -9999px; width: 1px; height: 1px;
  overflow: hidden; opacity: 0;
}

/* ============ Страницы услуг и документов ============ */
.crumbs { margin-bottom: 18px; }
.note {
  border-left: 3px solid var(--line); padding: 4px 0 4px 16px; margin-top: 28px;
}
.doc h2 { margin-top: 2rem; }
.doc p, .doc li { max-width: 74ch; }
/* Реквизиты: две колонки, подпись слева, значение справа. Не таблица, потому
   что это пары «название — значение», а не сетка данных, и на телефоне пары
   должны схлопнуться в строки, чего от таблицы не добьёшься без вранья про
   display. */
.req { display: grid; grid-template-columns: 15rem 1fr; gap: .55rem 24px; margin: 16px 0 32px; }
.req dt { color: var(--muted); }
.req dd { margin: 0; }
/* Клик выделяет номер целиком: счета длинные, промахнуться на знаке легко. */
.req-num { font-variant-numeric: tabular-nums; user-select: all; letter-spacing: .01em; }
@media (max-width: 640px) {
  .req { grid-template-columns: 1fr; gap: 0; }
  .req dt { margin-top: .9rem; font-size: .9rem; }
}

.big-check { font-size: 3rem; margin: 0 0 .4rem; }

/* ============ Кабинет ============ */
.nav-cabinet { color: var(--ink); font-weight: 550; }

.cab-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 24px; flex-wrap: wrap; margin-bottom: 32px;
}
.cab-head h1 { margin-bottom: .2rem; }
.cab-head-actions { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }

.cab-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; margin-bottom: 44px;
}
.panel {
  background: var(--glass); backdrop-filter: blur(12px);
  border: 1px solid var(--line);
  border-radius: var(--radius); padding: 26px 28px;
}
.panel-big {
  font-size: 2rem; font-weight: 700; letter-spacing: -0.04em; margin: .2rem 0 .3rem;
}
.panel-big.ok { color: var(--ok); }
.panel-big.warn { color: var(--danger); }
.panel p:last-child { margin-bottom: 0; }

/* Пары «поле — значение»: в фильтре их шесть, и таблица тут читается лучше строки. */
.kv li {
  display: flex; justify-content: space-between; gap: 20px; margin: 0;
  padding: 9px 0; border-bottom: 1px dashed var(--line); font-size: .95rem;
}
.kv li:last-child { border-bottom: 0; }
.kv span { color: var(--muted); white-space: nowrap; }
.kv b { text-align: right; font-weight: 550; }

.filter-card { margin-bottom: 18px; }
.filter-head { display: flex; align-items: center; gap: 12px; margin-bottom: 6px; }
.filter-head h3 { margin: 0; }
/* Кнопка «Изменить» прижимается к правому краю заголовка фильтра. */
.filter-head .btn-small { margin-left: auto; }
.btn-small { padding: 8px 18px; font-size: .86rem; }

/* Сообщение после сохранения или о протухшей форме. */
.notice {
  padding: 13px 20px; border-radius: var(--pill); margin-bottom: 24px; font-size: .95rem;
}
.ok-notice {
  background: color-mix(in srgb, var(--ok) 12%, transparent); color: var(--ok);
}
/* Не ошибка, но и не «всё хорошо»: тестовый режим кассы, платёж ещё не прошёл,
   статус не выяснен. Отдельный цвет нужен именно потому, что зелёное здесь
   соврало бы, а красное напугало бы там, где деньги не потеряны. */
.warn-notice {
  background: color-mix(in srgb, var(--danger) 9%, transparent); color: var(--ink);
}
.panel form { margin-top: 6px; }

/* Сетка цен «тариф × города». Узкий экран её не вмещает, поэтому таблица едет
   внутри своей обёртки, а не растягивает страницу: горизонтальная прокрутка
   всего body — это когда уезжает и шапка, и текст. */
.table-scroll { overflow-x: auto; margin: 4px 0 14px; }
.price-grid { border-collapse: collapse; width: 100%; font-size: .93rem; }
.price-grid th, .price-grid td {
  padding: 9px 14px; text-align: right; white-space: nowrap;
  border-bottom: 1px solid var(--line);
}
.price-grid thead th { color: var(--muted); font-weight: 600; }
.price-grid tbody th { text-align: left; font-weight: 600; }
.price-grid td { font-variant-numeric: tabular-nums; }
.price-grid tbody tr:last-child th, .price-grid tbody tr:last-child td {
  border-bottom: none;
}

/* Два поля границы диапазона в одну строку. */
.pair { display: flex; align-items: center; gap: 10px; }
.pair input { flex: 1 1 0; min-width: 0; }
.dash { color: var(--muted); flex: none; }

.hint { display: block; margin-top: 6px; }
.check { display: flex; align-items: center; gap: 10px; font-weight: 500; }
.check input { width: auto; accent-color: var(--accent); }
.tag {
  font-size: .78rem; padding: 2px 9px; border-radius: 20px;
  background: var(--accent-soft); color: var(--muted);
}
.tag.warn { background: color-mix(in srgb, var(--danger) 12%, transparent); color: var(--danger); }

/* ============ Лента находок ============ */
.finds { display: grid; gap: 18px; margin: 32px 0; }
.find {
  display: grid; grid-template-columns: 190px 1fr; gap: 0;
  background: var(--glass); backdrop-filter: blur(12px);
  border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden;
}
.find-photo {
  width: 100%; height: 100%; min-height: 150px; object-fit: cover; display: block;
  background: var(--accent-soft);
}
.find-photo-empty { min-height: 150px; }
.find-body { padding: 20px 24px; min-width: 0; }
.find-body h3 { margin-bottom: .35rem; }
.find-numbers { margin-bottom: .6rem; font-size: 1.05rem; }
.find-facts { display: flex; flex-wrap: wrap; gap: 6px 10px; margin-bottom: .6rem; }
.find-facts li {
  margin: 0; font-size: .88rem; padding: 3px 10px; border-radius: 20px;
  background: var(--accent-soft); color: var(--ink);
}
.find-facts li.bad {
  background: color-mix(in srgb, var(--danger) 12%, transparent); color: var(--danger);
}
.find-facts li.muted { background: transparent; padding-left: 0; }
.find-support { font-size: .92rem; margin-bottom: .5rem; }
.find-foot { margin: 0; }

.pager { display: flex; align-items: center; gap: 16px; justify-content: center; }

/* ============ Админка ============ */
.adm-nav { display: flex; flex-wrap: wrap; gap: 20px; margin-bottom: 26px; font-size: .95rem; }
.adm-nav a { color: var(--muted); }
.adm-nav a.is-here { color: var(--ink); font-weight: 600; }
.adm-nav b { color: var(--accent); }
.adm-nav-out { margin-left: auto; }

.adm-tabs { display: flex; flex-wrap: wrap; gap: 8px; margin: 24px 0 26px; }
.adm-tabs .tab {
  border: 1px solid var(--line-hard); border-radius: var(--pill); padding: 6px 17px;
  font-size: .9rem; color: var(--muted); background: var(--surface);
}
.adm-tabs .tab:hover { text-decoration: none; border-color: var(--ink); }
.adm-tabs .tab.is-here { border-color: var(--accent); color: var(--ink); font-weight: 550; }

.adm-lead { margin-bottom: 16px; }
.adm-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 6px; }
.adm-head h3 { margin: 0; }
/* Дата уезжает вправо: слева читается имя, справа — когда это было. */
.adm-head .muted { margin-left: auto; }

/* Комментарий клиента: переносы строк он ставил осмысленно. */
.adm-msg { white-space: pre-line; margin: 14px 0 6px; }
.adm-src { margin: 0; overflow-wrap: anywhere; }

.adm-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 12px; }
.adm-inline { display: flex; gap: 6px; align-items: center; }

.adm-note, .adm-inline input {
  border: 1px solid var(--line-hard); border-radius: 14px; padding: 10px 14px;
  background: var(--bg); color: var(--ink); font: inherit; font-size: .95rem;
}
.adm-note { width: 100%; margin-top: 14px; resize: vertical; }
.adm-inline input { width: 80px; padding: 7px 10px; font-size: .9rem; }
.adm-note:focus, .adm-inline input:focus { outline: none; border-color: var(--accent); }

.tag.ok { background: color-mix(in srgb, var(--ok) 12%, transparent); color: var(--ok); }

/* ============ Подвал ============ */
.site-foot { border-top: 1px solid var(--line); padding: 72px 0 32px; margin-top: 0; }
.foot-grid { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: 32px; }
.foot-brand { font-weight: 700; letter-spacing: -.02em; margin-bottom: .3rem; }
.foot-title {
  font-size: .72rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .11em; color: var(--muted); margin-bottom: .9rem;
}
.site-foot .plain li { margin-bottom: .4rem; font-size: .95rem; }
.site-foot a { color: var(--muted); }
.site-foot a:hover { color: var(--ink); }
.foot-bottom { margin-top: 40px; padding-top: 20px; border-top: 1px solid var(--line); }

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

   Ход маленький и вверх: движение должно подсказывать, что блок только что
   появился, а не устраивать въезд. */
.reveal {
  opacity: 0; transform: translateY(16px);
  transition: opacity .55s ease-out, transform .55s cubic-bezier(.2, .6, .3, 1);
}
.reveal.is-in { opacity: 1; transform: none; }

/* Соседние карточки всплывают не одновременно, а лесенкой: задержку ставит
   скрипт через эту переменную, по порядку внутри группы. */
.reveal { transition-delay: var(--reveal-delay, 0s); }

/* Цифры досчитываются скриптом; пока он не начал, показываем конечное
   значение — иначе при отключённом JS в полосе висели бы нули. */
.proof-num { font-variant-numeric: tabular-nums; }

/* ============ Узкие экраны ============ */
@media (max-width: 900px) {
  .hero { padding: 88px 0 72px; }
  .section, .band { padding-top: 72px; padding-bottom: 72px; }
  .hero-grid, .split, .split-wide, .form-section { grid-template-columns: 1fr; gap: 40px; }
  .steps-four { grid-template-columns: repeat(2, 1fr); }
  .cards, .cases, .takeover { grid-template-columns: repeat(2, 1fr); }
  .foot-grid { grid-template-columns: 1fr 1fr; }
  .cab-grid { grid-template-columns: 1fr 1fr; }
  .side { position: static; }
}

@media (max-width: 600px) {
  body { font-size: 16px; }
  .section, .band { padding-top: 56px; padding-bottom: 56px; }
  .hero { padding: 64px 0 48px; }
  .price-card, .lead-form { padding: 24px; border-radius: var(--radius); }
  .card { padding: 24px; }
  .steps-four, .cards, .cases, .takeover, .foot-grid, .cab-grid { grid-template-columns: 1fr; }
  .proof { grid-template-columns: 1fr; gap: 20px; }
  /* Фото над текстом: в 190 пикселей колонки на телефоне не остаётся места
     ни под адрес, ни под цену. */
  .find { grid-template-columns: 1fr; }
  .find-photo { max-height: 200px; }
  .head-inner { flex-direction: column; align-items: flex-start; gap: 8px; padding-block: 12px; }
  .nav { gap: 16px; }
  .btn { width: 100%; text-align: center; }
  .cta-row .btn { width: auto; flex: 1 1 auto; }
  /* В админке кнопки идут рядами по три-четыре: растянутые на всю ширину они
     превратили бы карточку заявки в вертикальный столбик. */
  .adm-actions .btn { width: auto; }
  .adm-head .muted { margin-left: 0; }
}

/* Кому движение мешает — тому его нет. Скрипт читает ту же настройку и не
   вешает ни появление при прокрутке, ни досчёт цифр, так что содержимое
   остаётся на месте, а не замирает невидимым. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    transition: none !important;
    animation: none !important;
  }
  .reveal { opacity: 1; transform: none; }
}
