/* ============================================================
   Главная страница.
   Длинная — потому что незнакомец приходит с десятком вопросов,
   и оставить их без ответа это ровно то, что делает короткая.
   ============================================================ */

.op-home { padding-block-start: var(--s-7); }

/* ============================================================
   Ведомость — скелет по мотивам Meridian.

   Страница собрана листами. Лист — не карточка: у него нет тени и
   собственного фона, он отделён от соседа чертой во всю ширину и
   подписан мета-строкой с номером. Так выглядит документ, а не
   витрина, — и это ровно то, чем мы торгуем: проверяемой работой,
   а не красотой.

   Два прошлых захода были перекраской и перестановкой секций
   Shelfready; оба раза владелец говорила «всё равно похоже». Похоже
   делали сетки из карточек — их здесь нет ни одной.
   ============================================================ */

.op-sheet {
  border-block-start: var(--border);
  padding-block: var(--s-8);
}

.op-sheet:first-child { border-block-start: 0; }

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

/*
 * Восстановлено 05.10.2026. Переписывая герой под кадр во всю ширину, я вырезал
 * это правило заодно с ним: оно стояло в том же куске файла. Надзаголовки на
 * всём сайте потеряли моноширинный шрифт, капитель и точку, а `.op-meta`
 * перестал быть flex — отчего хвост справа («Per room · not per picture»)
 * прилипал к названию листа.
 *
 * Глазами это читалось как «мелкая неровность на странице цен». Нашлось
 * замером: `display` оказался `block` там, где правило опиралось на `flex`.
 */
.op-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3);
  margin: 0 0 var(--s-6);
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--c-muted);
}

.op-meta__dot {
  inline-size: 6px;
  block-size: 6px;
  border-radius: var(--r-dot);
  background: var(--c-accent);
  flex: none;
}

.op-meta__rest { margin-inline-start: auto; }

@media (max-width: 700px) {
  .op-meta__rest { margin-inline-start: 0; flex-basis: 100%; }
}

/*
 * Первый лист без кадра: высота по содержимому, а не в экран.
 *
 * `min-block-size: min(86vh, 760px)` остался от времён, когда в герое стоял
 * снимок и высоту задавал он. На About и ценах кадра нет, и правило растягивало
 * три строки текста на весь экран: страница цен открывалась пустой стеной, а
 * таблица начиналась ниже сгиба. Замерено — герой 760 при содержимом в 230.
 *
 * Герою главной это не мешает: `.op-hero--bleed` задаёт свою высоту ниже и
 * перебивает это правило. Правило названо по условию, а не по виду: высоту в
 * экран получает тот лист, у которого есть чем её занять.
 */
.op-sheet--hero {
  display: flex;
  align-items: center;
  padding-block: var(--s-9) var(--s-8);
}

/* Хвост надзаголовка вправо — как на листах главной. Без этого «Pricing» и
   «Per room · not per picture» слипаются в одну строку без паузы. */
.op-sheet--hero .op-meta { flex-wrap: wrap; }
.op-sheet--hero .op-meta__rest { margin-inline-start: auto; }

.op-sheet--hero > .op-shell { inline-size: 100%; }

/* ---------- герой во всю ширину ---------- */

/*
 * Кадр от края до края окна, текст поверх. Решено владельцем 05.10.2026 —
 * отмена прежнего устройства, где кадр стоял вторым столбцом справа.
 *
 * ## Как полоса выходит за колонку
 *
 * Родительская тема держит содержимое в 1200 точках, и герой сидит внутри
 * этой колонки. `margin-inline: calc(50% - 50vw)` раздвигает его до ширины
 * окна: половина своей ширины минус половина окна с каждой стороны.
 *
 * Ловушка приёма в том, что `100vw` считает **вместе с полосой прокрутки**, а
 * `100%` — без неё. На странице с прокруткой это даёт лишние точки справа и
 * горизонтальную прокрутку всей страницы. Отсюда `overflow-x: clip` на
 * `.op-main`: именно `clip`, а не `hidden`. `hidden` сделал бы из main
 * прокручиваемую область, и залипающий кадр на листе 02 перестал бы залипать —
 * он считает от окна. `clip` области прокрутки не заводит и залипание не
 * трогает. Проверено обоими замерами после правки.
 */
/*
 * Герой встык под шапку.
 *
 * Между шапкой и ним стояло 96 точек бумаги — по 48 от двух обёрток:
 * `.site-content` родительской темы и нашего `.op-home`. Замерено; на глаз
 * это читалось как «кадр почему-то не сверху».
 *
 * Снимается только на главной, по классу `home`, который WordPress вешает на
 * `body` сам. Писать это правилом на `.op-sheet--hero` нельзя: тот же класс
 * носят первые листы About и цен, у которых никакого кадра нет, — на этом
 * проект уже обжигался трижды.
 */
body.home .site-content,
body.home .op-home { padding-block-start: 0; }

.op-hero--bleed {
  position: relative;
  margin-inline: calc(50% - 50vw);
  inline-size: 100vw;
  padding-block: var(--s-9);
  min-block-size: min(84vh, 720px);
  overflow: hidden;
  background: var(--c-band);
}

.op-hero__bleed {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  /*
   * Кадр прижат к низу: сверху у снимка пустой потолок, снизу — кровать и
   * ковёр, то есть то, за чем сюда пришли. При обрезке по высоте терять надо
   * потолок.
   */
  object-position: 50% 70%;
  /*
   * Кадр выразительнее: глубже тени, чуть плотнее цвет, чуть темнее в целом.
   *
   * Фильтром, а не пересохранением файла: обратимо, без потери качества и
   * видно в одном месте. `brightness` ниже единицы здесь не только ради вида —
   * контраст растягивает светлое вверх, а текст поверх стоит как раз на
   * светлой стене, и без этого он просел бы.
   *
   * Числа проверены замером на самой странице: canvas рисует кадр с тем же
   * фильтром, что и браузер, иначе замер считал бы по неотфильтрованному
   * снимку и врал бы в нашу пользу.
   */
  filter: contrast(1.26) saturate(1.16) brightness(0.94);
}

/*
 * Подложка. Плотность не выбрана, а вычислена.
 *
 * Замер 05.10.2026 на самом кадре, через canvas: в колонке, где стоит текст,
 * 90-й процент светимости равен 0,859. Белый #F5F2EF на таком фоне даёт
 * **0,90 : 1** — то есть текст темнее фона и не читается вовсе.
 *
 * Чтобы вытянуть 4,5 : 1 по 90-му проценту, нужно 0,83 чернил. Это не выбор
 * вкуса: при 0,6 выходит 2,36, при 0,7 — 3,0. Всё, что мягче, — нечитаемый
 * заголовок, как бы хорошо оно ни смотрелось на снимке.
 *
 * И это свойство не одного кадра. Померены все двенадцать наших снимков:
 * требуемая плотность 0,68…0,84, лучший — room-2 с 0,68. Мы продаём светлые
 * комнаты в дневном свету, и светлыми они быть обязаны.
 *
 * Наклон оставлен, но мелкий: вверху 0,74, под текстом 0,84, у низа 0,88.
 * Он даёт глубину, но не отменяет пола: ни одна точка не опускается туда,
 * где текст перестаёт читаться.
 */
.op-hero__veil {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    color-mix(in srgb, var(--c-band) 38%, transparent) 0%,
    color-mix(in srgb, var(--c-band) 45%, transparent) 55%,
    color-mix(in srgb, var(--c-band) 58%, transparent) 100%
  );
}

.op-hero--bleed > .op-shell { position: relative; }

/*
 * Местное пятно под текстом, вместо того чтобы топить весь кадр.
 *
 * Сплошной подложки, достаточной для заголовка, нужно 0,86 — при ней комната
 * перестаёт быть комнатой, остаётся силуэт. Поэтому слоёв два: общий 0,38…0,58
 * на весь кадр, он даёт настроение и держит мелкий текст, и эллипс под самим
 * блоком текста.
 *
 * Плотность эллипса не подобрана, а решена: два слоя складываются как
 * 1 − (1 − a1)(1 − a2). Чтобы в сумме вышло 0,86 при общем 0,45, местному
 * нужно 0,745. Поднято до 0,75 после смены кадра 05.10.2026: без
 * надзаголовка строка заголовка поднялась в более светлую зону снимка, и при
 * 0,72 выходило 4,42 вместо 4,5. Проверено замером после правки.
 *
 * Края эллипса растянуты до прозрачности: резкая граница подложки читается
 * как прямоугольник поверх фотографии, то есть как ошибка вёрстки.
 */
.op-hero__say { position: relative; }

.op-hero__say::before {
  content: "";
  position: absolute;
  inset: -18% -26%;
  z-index: -1;
  /*
   * Плотность держится ровной до 58% радиуса и только потом тает. Сперва она
   * падала с 75% уже на 42%, и надзаголовок со строкой кнопок оказывались на
   * краю пятна, где его почти нет: заголовок по центру проходил, а они — нет.
   */
  background: radial-gradient(
    ellipse at center,
    color-mix(in srgb, var(--c-band) 75%, transparent) 0%,
    color-mix(in srgb, var(--c-band) 75%, transparent) 58%,
    color-mix(in srgb, var(--c-band) 40%, transparent) 80%,
    transparent 100%
  );
}



/*
 * Текст по центру колонки и по центру строки — как на образце, который
 * принесла владелец. Ширина ограничена: заголовок в 56 точек на всю полосу в
 * 1200 рвётся на куски, которые глаз не собирает в строку.
 */
.op-hero__say {
  max-inline-size: 42rem;
  margin-inline: auto;
  text-align: center;
}

/*
 * На фотографии текст только почти белый.
 *
 * Терракота `--c-accent-on-band` держит 6,36 : 1 на сплошной чернильной
 * плите — замерено сторожем, пара «акцент на полосе». Но плита и снимок не
 * одно и то же: на кадре та же краска дала **1,79 : 1**, потому что под ней
 * не чернила, а светлая стена, просвечивающая сквозь подложку.
 *
 * Поэтому надзаголовок и курсив здесь белые. Акцент остаётся на кнопке, у
 * которой своя сплошная заливка, и в точке надзаголовка — она не текст, её
 * читать не надо.
 */
.op-hero--bleed .op-meta { justify-content: center; color: var(--c-band-in); }
.op-hero--bleed .op-meta__dot { background: var(--c-accent-on-band); }
.op-hero--bleed .op-title { color: var(--c-band-in); }
.op-hero--bleed .op-title em { color: var(--c-band-in); }

.op-hero--bleed .op-lede {
  color: var(--c-band-in);
  margin-inline: auto;
  max-inline-size: 46ch;
}

.op-hero__do {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4);
  justify-content: center;
  margin-block-start: var(--s-6);
}

/*
 * Вторая кнопка — обводкой, а не заливкой: два сплошных пятна рядом спорят за
 * то, какое из них главное. На образце ровно так же.
 */
/*
 * Обводка написана через `.op-hero__do`, а не одним классом.
 *
 * Одним классом она не работала: `.op-button--big` ниже по файлу задаёт
 * `box-shadow` тенью, вес у правил одинаковый, и побеждало то, что записано
 * позже. Проверено замером — у кнопки стояла тень, а обводки не было вовсе.
 * Полагаться на порядок строк в файле нельзя: он меняется при первой же
 * перестановке блоков.
 */
.op-hero__do .op-button--ghost {
  background: none;
  color: var(--c-band-in);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--c-band-in) 60%, transparent);
}

.op-hero__do .op-button--ghost:hover {
  filter: none;
  background: color-mix(in srgb, var(--c-band-in) 12%, transparent);
  box-shadow: inset 0 0 0 1px var(--c-band-in);
}

/* Кнопка-ссылка раскладывается флексом ради стрелки; без выравнивания её
   содержимое жмётся влево, и на телефоне, где кнопка во всю ширину, это
   видно сразу. */
.op-hero__do .op-button { justify-content: center; text-align: center; }

/*
 * Узкий экран: пятна под текстом нет, вместо него наклон.
 *
 * Эллипс рассчитан на блок текста посреди широкого кадра. На 375 блок
 * занимает 75% высоты и всю ширину, и пятно вышло 497×607 при герое 375×598,
 * то есть накрыло 101% — фотография пропала совсем, остался тёмный
 * прямоугольник. Замерено, а не замечено: на снимке экрана это выглядело так,
 * будто кадр не загрузился.
 *
 * Поэтому на телефоне: пятно выключено, герой выше, текст прижат книзу, а
 * подложка — наклон, густой внизу под текстом и редкий вверху, где видно
 * комнату. Телефон здесь не запасной случай, а основной: комнату снимают им.
 */
@media (max-width: 760px) {
  .op-hero--bleed {
    min-block-size: 86vh;
    padding-block: var(--s-8);
    align-items: end;
  }

  .op-hero__say::before { display: none; }

  /*
   * Наклон крутой и ранний. Первая попытка шла полого — 0,22 вверху, 0,46 на
   * 38%, — и замер показал у заголовка 1,99 : 1 при нужных 4,5: текст на
   * телефоне стоит выше, чем казалось, его середина приходится на 32% высоты,
   * а там было всего 0,42 чернил.
   *
   * Теперь плотность набирается к 28% и дальше держится. Верхняя четверть
   * остаётся светлой — в ней видно потолок и окно, то есть комнату.
   */
  .op-hero__veil {
    background: linear-gradient(
      to bottom,
      color-mix(in srgb, var(--c-band) 18%, transparent) 0%,
      color-mix(in srgb, var(--c-band) 35%, transparent) 18%,
      color-mix(in srgb, var(--c-band) 82%, transparent) 28%,
      color-mix(in srgb, var(--c-band) 88%, transparent) 100%
    );
  }

  .op-hero__do { flex-direction: column; align-items: stretch; }
}

/* ---------- лист 02: перечень с кадром ---------- */

.op-spec {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: var(--s-7);
  align-items: start;
}

.op-spec__stage {
  position: relative;
  aspect-ratio: 16 / 10;
  border: var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--c-sunk);
  position: sticky;
  inset-block-start: 6rem;
}

.op-spec__shot {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease);
}

/* По умолчанию виден первый кадр — он же останется, если `:has()` не поддержан. */
.op-spec__shot.is-a { opacity: 1; }

/*
 * Кадр меняется под наведённую строку — без единой строки скрипта.
 *
 * `:has()` умеют все нынешние браузеры; старый просто оставит первый кадр, и
 * раздел от этого ничего не потеряет — он и без смены кадра читается.
 */
.op-spec:has(.op-spec__row.is-b:hover) .op-spec__shot.is-a,
.op-spec:has(.op-spec__row.is-c:hover) .op-spec__shot.is-a,
.op-spec:has(.op-spec__row.is-d:hover) .op-spec__shot.is-a { opacity: 0; }

.op-spec:has(.op-spec__row.is-b:hover) .op-spec__shot.is-b,
.op-spec:has(.op-spec__row.is-c:hover) .op-spec__shot.is-c,
.op-spec:has(.op-spec__row.is-d:hover) .op-spec__shot.is-d { opacity: 1; }

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

/*
 * Строка ведомости: буква, затем три строки текста.
 *
 * Разделены чертой, а не зазором: зазор превратил бы их в карточки, а
 * карточек мы избегаем ровно затем, чтобы страница не выглядела прежней.
 */
.op-spec__row {
  display: grid;
  grid-template-columns: 3rem minmax(0, 1fr);
  gap: var(--s-4);
  padding-block: var(--s-5);
  padding-inline: var(--s-4);
  border-block-start: var(--border);

  /*
   * Черта слева — прозрачная, но место под неё занято всегда.
   *
   * Если появлять её только по наведению, строка дёргается вбок на два
   * пикселя. Прозрачная черта держит место: двигается цвет, а не вёрстка.
   */
  border-inline-start: 2px solid transparent;
  transition: background var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}

.op-spec__row:first-child { border-block-start: 0; }

/*
 * Наведение — черта и лёгкий налёт, а не серая плита.
 *
 * Было `background: var(--c-raised)` во всю строку. На ночном лице плита
 * читалась как «эта строка сейчас показана»: приподнятый тон был чуть светлее
 * фона и работал подсветкой. На белой бумаге тот же приём дал серый
 * прямоугольник поперёк листа — он тяжелее всего остального на странице и
 * спорит с кадром, ради которого строку и наводят.
 *
 * Налёт взят общий, `--c-hover`: он один на вопросы, тарифы и эти строки, и
 * если окажется слишком силён, менять его надо в одном месте. Работает здесь
 * черта, а налёт лишь показывает, докуда строка простирается.
 */
.op-spec__row:hover {
  background: var(--c-hover);
  border-inline-start-color: var(--c-accent);
}

.op-spec__key {
  font-family: var(--f-mono);
  font-size: var(--t-sm);
  color: var(--c-accent-text);
  letter-spacing: var(--ls-label);
}

.op-spec__label {
  margin: 0 0 var(--s-2);
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--c-muted);
}

.op-spec__value {
  margin: 0 0 var(--s-2);
  font-size: var(--t-lg);
  letter-spacing: var(--ls-tight);
}

.op-spec__detail {
  margin: 0;
  color: var(--c-muted);
  font-size: var(--t-sm);
  line-height: 1.6;
}

@media (max-width: 900px) {
  .op-spec { grid-template-columns: 1fr; }

  /*
   * `relative`, а не `static`, и это не придирка к слову.
   *
   * Здесь стояло `static` — чтобы на телефоне кадр не прилипал к верху. Липкость
   * оно и правда снимало, но заодно снимало **систему отсчёта**: кадры внутри
   * лежат `absolute`, и без позиционированного предка они отсчитываются от
   * начала документа. На телефоне все четыре уезжали в самый верх страницы и
   * ложились поверх героя — страница открывалась не заголовком, а пустой
   * комнатой во весь экран, а на месте самого листа 02 оставалась серая дыра.
   *
   * Найдено 01.10.2026 при осмотре героя. Жило с тех пор, как лист завели:
   * проверяли его на широком экране, где `sticky` работал и система отсчёта
   * была.
   *
   * `relative` отменяет липкость и оставляет отсчёт на месте. Но `relative`
   * **не отменяет `inset-block-start`**: шесть ремов, которыми кадр прилипал
   * к верху, превращаются в смещение на те же 96 точек вниз, и кадр наезжает
   * на первую строку, пряча её букву и подпись. Поэтому отступ снимается
   * здесь же — поймано тем же осмотром, через десять минут после первого.
   */
  .op-spec__stage { position: relative; inset-block-start: 0; }
}

/* ---------- лист 04: сказанное против измеренного ---------- */

/*
 * Ведомость чисел: слово слева, цифры справа.
 *
 * Поправлено 01.10.2026. Было две вещи, и обе от того, что блок собирали на
 * тёмном лице, где края теряются сами собой.
 *
 * **Он не закрывался снизу.** Черта была только сверху, и вертикальная линия
 * между столбцами обрывалась в пустоте — блок читался не как ведомость, а как
 * начало чего-то, что не дописали.
 *
 * **Числа жались кверху.** Три строки шли своей высотой, и под ними
 * оставалась пустота в треть колонки, а выделенное число висело посередине
 * полосой непонятной длины. Теперь строки делят высоту поровну: заливка
 * выделенного числа стала ровно третью столбца, и видно, что так и задумано.
 */
.op-bulletin {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  border-block: var(--border);
}

.op-bulletin__say {
  padding: var(--s-7) var(--s-7) var(--s-7) 0;
  border-inline-end: var(--border);
  align-self: start;
}

.op-bulletin__say h2 {
  margin: 0 0 var(--s-5);
  font-size: clamp(1.8rem, 3.4vw, 2.8rem);
  line-height: 1.06;
  letter-spacing: -0.03em;
}

.op-bulletin__say p {
  margin: 0;
  color: var(--c-muted);
  line-height: 1.7;
  max-inline-size: 48ch;
}

.op-bulletin__figures {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-rows: repeat(3, minmax(0, 1fr));
}

.op-bulletin__figures li {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: var(--s-6) var(--s-6) var(--s-6) var(--s-7);
  border-block-end: var(--border);
}

.op-bulletin__figures li:last-child { border-block-end: 0; }

/*
 * Одно число выделено заливкой — приём Meridian.
 *
 * Выделено то, которое человек не может проверить сам и которое решает,
 * годится ли услуга: сколько ждать. Остальные два он и так прочтёт.
 *
 * ## Терракота, а не чёрное
 *
 * Заливка была `--c-band` — почти чёрная плита. На ночном лице она читалась
 * продолжением страницы, а на белой бумаге оказалась самым тёмным пятном на
 * всём листе и ни с чем на нём не рифмовалась: владелец сказала, что блок
 * выбивается из общего вида, и была права.
 *
 * Терракота — тот же цвет, что у кнопки, у букв строк и у нашего столбца в
 * таблице сравнения. Белый текст на ней даёт 5,42 : 1, посчитано
 * `scripts/contrast`.
 *
 * Такой же полосой выделена выбранная строка тарифов, и она того же цвета:
 * два выделенных места на одной странице обязаны быть одним оттенком, иначе
 * читаются как две разные мысли.
 */
.op-bulletin__figures .is-key {
  background: var(--c-band-warm);
  color: var(--c-band-warm-in);
}

.op-bulletin__figures .is-key span { color: color-mix(in srgb, var(--c-band-warm-in) 72%, var(--c-band-warm)); }

.op-bulletin__figures b {
  display: block;
  font-size: clamp(2.4rem, 5vw, 3.6rem);
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}

.op-bulletin__figures i {
  font-style: normal;
  font-size: 0.5em;
  color: var(--c-muted);
  margin-inline-start: 0.1em;
}

.op-bulletin__figures .is-key i { color: color-mix(in srgb, var(--c-band-warm-in) 70%, var(--c-band-warm)); }

.op-bulletin__figures span {
  display: block;
  margin-block-start: var(--s-3);
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--c-muted);
}

@media (max-width: 860px) {
  .op-bulletin { grid-template-columns: 1fr; }
  .op-bulletin__say { padding: var(--s-6) 0; border-inline-end: 0; border-block-end: var(--border); }
  .op-bulletin__figures li { padding-inline: 0; }
}

/* ---------- лист 05: шаги строками ---------- */

.op-steps {
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: step;
}

.op-steps li {
  display: grid;
  grid-template-columns: 4rem minmax(0, 22ch) minmax(0, 1fr);
  gap: var(--s-4) var(--s-6);
  align-items: start;
  padding-block: var(--s-6);
  border-block-start: var(--border);
}

.op-steps li:first-child { border-block-start: 0; }

.op-steps__no {
  font-family: var(--f-mono);
  font-size: var(--t-sm);
  color: var(--c-accent-text);
  letter-spacing: var(--ls-label);
}

.op-steps__where {
  grid-column: 2;
  margin: 0 0 var(--s-2);
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--c-muted);
}

.op-steps h3 {
  grid-column: 2;
  grid-row: 2;
  margin: 0;
  font-size: var(--t-lg);
  letter-spacing: var(--ls-tight);
}

.op-steps li > p:not(.op-steps__where):not(.op-steps__tag) {
  grid-column: 3;
  grid-row: 1 / span 2;
  margin: 0;
  color: var(--c-muted);
  line-height: 1.7;
  font-size: var(--t-sm);
}

.op-steps__tag {
  grid-column: 3;
  margin: var(--s-3) 0 0;
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--c-accent-text);
}

@media (max-width: 860px) {
  .op-steps li { grid-template-columns: 3rem minmax(0, 1fr); }
  .op-steps li > p:not(.op-steps__where):not(.op-steps__tag) { grid-column: 2; grid-row: auto; }
  .op-steps__tag { grid-column: 2; }
}

/* ---------- бегущая строка ---------- */

.op-ticker {
  overflow: hidden;
  border-block: var(--border);
  background: var(--c-sunk);
  margin-block: var(--s-8) 0;
  /* Края растворяются, лента не обрывается о рамку экрана. */
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  /* Полоса никого снаружи не задевает: пересчитывать соседей при её
     движении незачем. */
  contain: paint;
}

.op-ticker__rail {
  display: flex;
  inline-size: max-content;
  animation: op-run 42s linear infinite;
  /* Лента едет без остановки. Свой слой — и её везут, а не перерисовывают
     вместе с растворяющимися краями. */
  will-change: transform;
}

.op-ticker:hover .op-ticker__rail { animation-play-state: paused; }

.op-ticker__run {
  display: flex;
  align-items: center;
  gap: var(--s-6);
  list-style: none;
  margin: 0;
  padding: var(--s-4) 0 var(--s-4) var(--s-6);
}

.op-ticker__run li {
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--c-muted);
  white-space: nowrap;
  display: flex;
  align-items: center;
  gap: var(--s-6);
}

/* Разделитель — квадратик акцентом, а не точка: у нас прямые углы. */
.op-ticker__run li::after {
  content: '';
  inline-size: 5px;
  block-size: 5px;
  background: var(--c-accent);
  flex: none;
}

@keyframes op-run {
  from { transform: translate3d(0, 0, 0); }
  /* Ровно половина: вторая лента встаёт на место первой, шва не видно. */
  to { transform: translate3d(-50%, 0, 0); }
}


/* ---------- вопросы ---------- */

.op-faq {
  border: var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
}

.op-faq__item { border-block-end: var(--border); background: var(--c-surface); }
.op-faq__item:last-child { border-block-end: 0; }

/* Раскрытый вопрос виден фоном, а не только значком: глаз находит, где он
   остановился, не перечитывая. */
.op-faq__item[open] { background: var(--c-raised); }

.op-faq__item summary {
  padding: var(--s-4) var(--s-5);
  cursor: pointer;
  font-weight: var(--fw-semi);
  list-style: none;
  display: flex;
  justify-content: space-between;
  gap: var(--s-4);
}

.op-faq__item summary::-webkit-details-marker { display: none; }

.op-faq__item summary::after {
  content: '+';
  font-family: var(--f-mono);
  color: var(--c-accent-text);
  flex: none;
}

/* Раскрытый — минус. Крутить плюс на 45° красивее, но минус понятнее:
   он прямо говорит «свернуть», а повёрнутый плюс надо разгадывать. */
.op-faq__item[open] summary::after { content: '\2212'; }

.op-faq__item[open] summary::after { content: '−'; }
.op-faq__item summary:hover { background: var(--c-hover); }

.op-faq__answer {
  padding: 0 var(--s-5) var(--s-5);
  color: var(--c-muted);
  max-width: var(--w-text);
}

.op-faq__answer p { margin: 0; }


/* ---------- призыв ---------- */

.op-call { max-width: 54ch; }
.op-call h2 { font-size: var(--t-3xl); margin: 0 0 var(--s-4); }
.op-call p { color: var(--c-muted); font-size: var(--t-lg); margin: 0 0 var(--s-6); }

/* ---------- телефон ---------- */

@media (max-width: 640px) {
  /* Меньше пустоты над первым экраном: на телефоне она съедает половину
     того, что человек видит, не пролистывая. */
  .op-home { padding-block-start: var(--s-5); }

  .op-band { padding-block: var(--s-6); margin-block: var(--s-7); }
  .op-sec { margin-block-end: var(--s-7); }

  /* «Было и стало» столбиком: в две колонки по 160 точек не видно ни того,
     ни другого, а вся суть этой пары именно в разглядывании. */
  .op-proof { grid-template-columns: 1fr; }

  .op-hero { gap: var(--s-6); }
  .op-hero__do { gap: var(--s-3); }
  .op-button--big { inline-size: 100%; text-align: center; }
  .op-plain { margin-inline-start: 0; }
}

/* ---------- ещё примеры ---------- */

.op-more {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: var(--s-6);
}

.op-more__item { display: flex; flex-direction: column; gap: var(--s-3); }

.op-more__pair figcaption.is-out { color: var(--c-accent-text); }

/* ============================================================
   Глубина и движение

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


/*
 * Подпись под ползунком — тем же голосом, что прочие оговорки на странице.
 *
 * Своего правила у неё не было вовсе, и она набиралась основным текстом: тот
 * же кегль и тот же цвет, что у абзацев, во всю ширину листа. Рядом с такими
 * же по смыслу примечаниями под лентой работ и под шестью проходами — мелкими
 * и приглушёнными — она читалась как отдельная мысль, а не как подпись.
 */
.op-sheet--wide figcaption {
  margin-block-start: var(--s-5);
  color: var(--c-muted);
  font-size: var(--t-sm);
  line-height: 1.6;
}

/* ---------- шесть проходов: два ряда по три ---------- */

/*
 * Два ряда с подписями внутри одного листа.
 *
 * Прежде это были два отдельных листа, и оба повторяли лист 02: крупный кадр
 * слева, строки с буквами справа. Владелец сказала верное — секции
 * повторяются. Дело было не в оформлении: лист 02 объясняет, какие решения
 * принимает человек, а эти два доказывали одно и то же утверждение по двум
 * осям — комната та же, меняются назначение и обстановка. Две оси одного
 * утверждения складываются в один лист.
 */
.op-ways {
  display: grid;
  gap: var(--s-7);
  margin-block-start: var(--s-6);
}

.op-ways__band { margin: 0; }

/*
 * Подпись ряда — строкой с чертой во всю ширину, как заголовок графы в
 * ведомости. Номер моноширинным, как номера листов и буквы строк: третьего
 * голоса на странице заводить незачем.
 */
.op-ways__title {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
  margin: 0 0 var(--s-4);
  padding-block-end: var(--s-3);
  border-block-end: var(--border);
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  font-weight: 400;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--c-text);
}

.op-ways__no { color: var(--c-accent-text); }

/*
 * Оговорка снизу нуждается в отдельном зазоре.
 *
 * У `op-note-plain` своего отступа сверху нет — там, где она идёт за текстом,
 * он ей и не нужен. За рядом кадров — нужен: иначе она встаёт впритык к
 * подписи первого кадра и читается как четвёртая строка этой подписи, а не
 * как примечание ко всему листу.
 */
.op-ways + .op-note-plain,
.op-rooms + .op-note-plain { display: block; margin-block-start: var(--s-6); }


/* ---------- ряд кадров ---------- */

/*
 * Ровно три равных кадра в ряд — нарочно другой приём, чем у листа 02.
 *
 * Там кадр один и меняется под наведённую строку: лист ведёт за руку по
 * порядку решений. Здесь надо дать **сравнить**, а сравнивают рядом.
 * Спрятать два кадра из трёх значило бы спрятать сам предмет разговора.
 *
 * Соседняя лента работ (`op-rooms`) нарочно мозаика, а не ряд: там кадры
 * разных комнат, и ряд читался бы каталогом. Здесь наоборот — кадры обязаны
 * быть одного размера, иначе крупный покажется лучшим выбором, а не просто
 * крупным.
 *
 * Карточек нет: ни подложки, ни тени, ни рамки. Кадр и подпись под ним.
 */
.op-styles {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s-4);
  list-style: none;
  margin: var(--s-6) 0 0;
  padding: 0;
}

.op-styles figure {
  margin: 0;
}

.op-styles img {
  display: block;
  inline-size: 100%;
  block-size: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border-radius: var(--r-lg);
  background: var(--c-sunk);
}

.op-styles figcaption {
  margin-block-start: var(--s-3);
  color: var(--c-muted);
  font-size: var(--t-sm);
  line-height: 1.6;
}

/* Название стиля — тем же голосом, что номера листов и буквы строк. */
.op-styles__name {
  display: block;
  margin-block-end: var(--s-1);
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--c-accent-text);
}

/*
 * На узком экране — в столбец, а не в два.
 *
 * Два столбца оставили бы третий стиль в одиночестве под первыми двумя, и
 * ряд перестал бы читаться как сравнение равных. Столбец медленнее, зато
 * каждый кадр остаётся крупным: на трёх кадрах по сто точек не видно ни
 * дерева, ни ткани, то есть не видно ровно того, чем стили и отличаются.
 */
@media (max-width: 860px) {
  .op-styles { grid-template-columns: 1fr; gap: var(--s-5); }
  .op-ways { gap: var(--s-6); }
}


/* ---------- лента работ ---------- */

/*
 * Четыре равных кадра: два ряда по два, и ряд — это комната.
 *
 * Сперва была мозаика под четыре комнаты, потом три равных кадра. Владелец
 * посмотрела на три и сказала верное: странно, что кадра три, а один из них
 * другой комнаты. Так и было — две комнаты на три кадра, и какая к какой,
 * читатель догадывался из подписи.
 *
 * Теперь в каждом ряду одна комната, обставленная двумя способами. Отвечать
 * на вопрос «сколько тут комнат» больше не нужно: это видно.
 *
 * Два столбца, а не четыре: на четыре кадра по 282 точки, и комнату в них не
 * разглядеть — лента перестаёт доказывать то, ради чего стоит.
 */
.op-rooms {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-4);
}

.op-rooms figure {
  margin: 0;
  aspect-ratio: 3 / 2;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--c-sunk);
}

.op-rooms img {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}

/* `op-rooms__big` убран и из разметки, и отсюда: кадры равны, и класс,
   который ничего не меняет, однажды будет прочитан как работающий. */

/*
 * На телефоне мозаика рассыпается в два столбца.
 *
 * Сетка в три столбца на экране в 375 точек даёт кадры по сто точек: на них
 * не видно ни мебели, ни комнаты, то есть лента перестаёт доказывать то,
 * ради чего стоит.
 */
/*
 * На узком экране — в столбец, а не в два.
 *
 * Кадров три: в два столбца третий остаётся один, и ряд читается как
 * недоделанный — ровно то, от чего ушли, убрав мозаику. К тому же на 375
 * точках два столбца дают кадры по 170: на них не видно ни мебели, ни
 * комнаты, то есть лента перестаёт доказывать то, ради чего стоит.
 */
@media (max-width: 720px) {
  .op-rooms { grid-template-columns: 1fr; }
}

/*
 * Тёмная полоса во всю ширину — второй голос страницы.
 *
 * Внутри переопределяются токены, как в подвале: правила, писанные под
 * светлый фон, работают на тёмном без переделки. Приём один и тот же в двух
 * местах — и это хорошо: если завтра полос станет три, третья заработает
 * сама.
 */
.op-band--light {
  background: var(--c-band);
  border-block: 0;
  padding-block: var(--s-8);

  /*
   * Цвет текста задаётся прямо, а не только токеном.
   *
   * Переопределить `--c-text` мало: `color` наследуется от `body` уже
   * вычисленным — тёмным, — и переменная внутри полосы на него не влияет.
   * Заготовка этого не делала, и первый же заголовок на ней оказался
   * невидим: тёмное на тёмном. Нашлось 02.10.2026, когда полосу наконец
   * поставили на страницу — она пролежала написанной и ни разу не применённой.
   *
   * Подвал работает правильно ровно потому, что `color` там стоит явно.
   */
  color: var(--c-band-in);

  --c-bg:      var(--c-band);
  --c-surface: color-mix(in srgb, var(--c-band-in) 6%, var(--c-band));
  --c-text:    var(--c-band-in);
  --c-muted:   color-mix(in srgb, var(--c-band-in) 66%, var(--c-band));
  --c-line:    color-mix(in srgb, var(--c-band-in) 16%, transparent);
  --c-accent-text: var(--c-accent-on-band);
  --c-accent:      var(--c-accent-on-band);

  /*
   * Текст на акценте внутри полосы — тёмный, а не белый.
   *
   * Полоса подменяет `--c-accent` на светлую терракоту, потому что тёмной на
   * тёмном не видно. Но `--c-accent-in` оставался белым, и кнопка внутри
   * полосы выходила белым по светло-терракотовому: **2,81 : 1**, то есть
   * нечитаемо. Найдено 02.10.2026, когда в плиту впервые поставили кнопку —
   * до этого полоса жила без кнопок и изъян негде было увидеть.
   *
   * Чернила те же, что у страницы: 6,36 : 1. Это снова тот случай, о котором
   * предупреждает правило выше, — подменяя цвет, подменяй и его пару.
   */
  --c-accent-in:   var(--c-band);
}

.op-band--light .op-sec__head h2 em {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  font-size: 1.06em;
}

/* ---------- плита посреди страницы ---------- */

/*
 * Один тёмный блок на всю ширину колонки — передышка в середине.
 *
 * Страница светлая от начала до конца, и середина её — четыре светлых листа
 * подряд. Плита делит страницу надвое и даёт глазу остановиться. Чёрточки
 * `op-sec__head` здесь нет нарочно: на тёмном она не нужна, плита сама и есть
 * знак препинания.
 *
 * Скругление как у кадров: плита — предмет на странице, а не раздел страницы,
 * и выглядеть должна предметом.
 */
/*
 * Отступы опущены на шаг: было `--s-9` (6rem, по 96 точек сверху и снизу).
 *
 * Владелец сказала дважды: «слишком много свободного лишнего пространства».
 * Первый раз это починила выключка по центру — ушла пустая правая половина.
 * Осталась высота: у плиты с кнопкой содержимого на четыре строки, а воздуха
 * почти две сотни точек.
 *
 * Выбрано уменьшение, а не наполнение. Второе значило бы сочинить текст на
 * живую витрину — а на этом сайте не ставят перед покупателем слов, которых
 * никто не решал.
 *
 * Шаг взят по своей же шкале, а не подобран числом: `--s-8` это 4rem. Ниже не
 * опущено потому, что плита по замыслу «выглядеть должна предметом» — слишком
 * тесная, она перестаёт читаться отдельной вещью и сливается с листами.
 */
.op-plate {
  border-radius: var(--r-lg);
  padding-block: var(--s-8);
  margin-block: var(--s-7);
  border-block: 0;
}

/*
 * Содержимое плиты стоит по середине, а не у левого края.
 *
 * Строка обрезана по 18ch, пояснение по 52ch, а сама плита идёт во всю ширину
 * страницы — и при широком окне текст занимал левую половину, оставляя правую
 * пустой. Владелец сказала прямо: «слишком много пустого места».
 *
 * Выключка по центру, а не растягивание строк: предел в 18ch поставлен затем,
 * чтобы заголовок ломался там, где задумано, — «Every room in the listing.» и
 * курсив отдельной строкой. Сними предел, и перенос поедет от ширины окна.
 *
 * `align-items: center` сжимает дочерние блоки до их содержимого и ставит по
 * середине; `text-align` выравнивает строки внутри них. Нужно и то и другое:
 * одного выравнивания мало, пока блок шириной во всю колонку.
 */
.op-plate .op-shell {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.op-plate .op-meta { margin-block-end: var(--s-6); }

/*
 * Строка набрана крупнее заголовков листов: это единственное место, где
 * страница повышает голос, и если она не крупнее — повышения не слышно.
 */
.op-plate__line {
  margin: 0;
  font-family: var(--f-display);
  font-weight: var(--fw-display);
  font-size: clamp(2rem, 4.4vw, 3.4rem);
  line-height: 1.08;
  letter-spacing: -0.03em;
  max-inline-size: 18ch;
}

.op-plate__line em {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  font-size: 1.08em;
  letter-spacing: -0.01em;
}

.op-plate__under {
  margin: var(--s-6) 0 0;
  max-inline-size: 52ch;
  color: var(--c-muted);
  line-height: 1.7;
}

/* Кнопка подтянута к тексту: отступ был `--s-7`, и вместе с нижним полем плиты
   он складывался в самое пустое место блока. */
.op-plate__do { margin-block-start: var(--s-6); }

/* Вторая плита закрывает страницу, поэтому нижнего отступа у неё нет: за ней
   сразу подвал, и зазор между двумя тёмными блоками читался бы щелью. */
.op-plate--end { margin-block-end: 0; }

@media (max-width: 720px) {
  /* На узком экране плита и так во всю ширину, воздух там дороже — ещё шаг
     вниз. Правило опущено вместе с настольным, иначе оно сравнялось бы с ним и
     перестало что-либо значить. */
  .op-plate { padding-block: var(--s-7); margin-inline: 0; }
}

/* ---------- появление листов при прокрутке ---------- */

/*
 * Лист поднимается на 14 точек и проявляется, когда входит в экран.
 *
 * Без единой строки скрипта: `animation-timeline: view()` привязывает ход
 * к положению листа в окне. Поэтому и правило устроено наоборот обычного —
 * **по умолчанию ничего нет**, движение включается только там, где браузер
 * его умеет. Браузер постарше просто покажет страницу, и никто не заметит
 * разницы; вариант «спрятать, а потом показать скриптом» так не умеет —
 * при любой осечке страница остаётся пустой.
 *
 * Герой исключён: он виден сразу при открытии, и проявляться ему неоткуда.
 * Исключена и плита — её дело останавливать глаз, а не въезжать в него.
 */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .op-sheet:not(.op-sheet--hero):not(.op-plate) {
      animation: op-rise both;
      animation-timeline: view();
      animation-range: entry 8% cover 26%;
    }

    @keyframes op-rise {
      from { opacity: 0; transform: translateY(14px); }
    }
  }
}

/* ---------- числа под героем ---------- */

/*
 * Узкая строка, а не полоса во всю ширину.
 *
 * Полосой числа спорили с кадром прямо над ними: два крупных предмета подряд,
 * и глаз не знает, куда идти. Строкой они дочитывают герой, а не начинают
 * новый раздел.
 */
.op-figures {
  margin-block-end: var(--s-9);
  padding-block-start: var(--s-5);
  border-block-start: var(--border);
}

/* ---------- сравнение отдельной секцией ---------- */

/* Секция сравнения зовётся `op-sheet--wide` с тех пор, как страница
   пересобрана листами; прежнее имя `op-compare` осталось в стилях и молча
   ничего не красило. Найдено замером: ограничение ширины не применялось. */

/*
 * Ползунок во всю ширину полотна.
 *
 * В герое он был картинкой при тексте — 45 % ширины, и ручку на нём было
 * видно только тому, кто её искал. Здесь он крупный настолько, что за ручку
 * хочется взяться, а это и есть весь смысл: товар доказывается не словами.
 */
/*
 * Ширина сравнения больше не ограничена.
 *
 * Ограничение стояло, пока кадры были по 1248 точек и на плотном экране
 * растягивались вдвое. Теперь кадр 2048: на полотне в 1200 логических точек
 * при двойной плотности нужно 2400, то есть растяжение 1,17 — этого не видно.
 *
 * Размер взялся не сам: снимки заменены на свои, с названным источником и
 * лицензией, и прогнаны у поставщика с поднятым `image_size`. Прежние были
 * превью чужих стоков по 626 точек, один — прямо с водяными знаками.
 */
.op-sheet--wide .op-slider__shot { max-block-size: 66vh; object-fit: cover; }


/* ---------- против чего нас выбирают ---------- */

/* ---------- против чего нас выбирают ---------- */

/*
 * Таблица, а не три плитки.
 *
 * Плитки заставляли сличать: читатель держал в голове первый абзац, читая
 * третий. Строка таблицы задаёт вопрос один раз, и три клетки отвечают на
 * него рядом — разницу видно, не перечитывая.
 *
 * Карточек по-прежнему нет: ни теней, ни подложек у чужих столбцов. Залит
 * только наш, и это единственное место на странице, где мы говорим о себе
 * рядом с чужими способами.
 */
.op-vs {
  margin-block-start: var(--s-6);

  /* На узком экране таблица едет вбок целиком, а не ломает слова по буквам.
     Пять столбцов текста в 375 точек не встают никак, и любая попытка их
     сложить превращает таблицу в те же плитки, от которых уходили. */
  overflow-x: auto;
}

.op-vs table {
  inline-size: 100%;
  min-inline-size: 46rem;
  border-collapse: collapse;
  text-align: start;
}

/*
 * Свои рамки, а не доставшиеся от родительской темы.
 *
 * GeneratePress рисует таблицам сетку по всем клеткам, и ведомость от этого
 * превращается в бухгалтерский бланк: вертикальные линии режут строку на
 * клетки, хотя читается она целиком, слева направо. Снимаем всё и возвращаем
 * одну горизонтальную черту между строками — ту же, что делит строки на
 * листах 02 и 08.
 */
.op-vs th,
.op-vs td { border: 0; }

.op-vs__cap {
  caption-side: top;
  text-align: start;
  color: var(--c-muted);
  font-size: var(--t-sm);
  line-height: 1.6;
  /* Оговорка — подпись к таблице, а не абзац страницы: во всю ширину листа
     она читалась вторым вступлением после мета-строки. */
  max-inline-size: 78ch;
  padding-block-end: var(--s-6);
}

/* Угловая клетка: подпись к столбцу вопросов, а не пустота. */
.op-vs__stub { color: var(--c-muted); font-weight: 400; }

/* Подсказка про боковую прокрутку — только там, где прокрутка есть. */
.op-vs__hint { display: none; }

@media (max-width: 860px) {
  .op-vs__hint {
    display: block;
    margin: var(--s-4) 0 0;
    font-family: var(--f-mono);
    font-size: var(--t-xs);
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--c-muted);
  }
}

/* Шапка — моноширинным, как номера листов и буквы строк. */
.op-vs th { text-align: start; }

.op-vs thead th,
.op-vs thead td { border-block-end: var(--border); }

.op-vs thead th {
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  font-weight: 400;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--c-muted);
  padding: 0 var(--s-5) var(--s-4);
  vertical-align: bottom;
}

/* Названия строк — тоже моноширинным, но тёмным: это вопросы, а не подписи. */
/*
 * Название строки — с полями слева и справа, а не впритык.
 *
 * Левого поля не было вовсе: столбец считался первым, а у первого слева
 * ничего нет. Но у таблицы есть собственная рамка, и слова упирались в неё.
 * Поля одинаковые со всех сторон — у клетки нет причины быть особенной
 * только потому, что она первая.
 */
.op-vs tbody th {
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  font-weight: 400;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--c-text);
  padding: var(--s-5);
  vertical-align: top;
  inline-size: 12rem;
  line-height: 1.5;
}

.op-vs tbody td {
  padding: var(--s-5);
  vertical-align: top;
  color: var(--c-muted);
  font-size: var(--t-sm);
  line-height: 1.6;
}

/* Одна черта на всю строку — не сетка по клеткам. */
.op-vs tbody tr + tr th,
.op-vs tbody tr + tr td { border-block-start: var(--border); }

/*
 * Наш столбец залит во всю высоту — приём Apex, и у него единственный смысл:
 * читателю не нужно объяснять, какой из трёх столбцов наш.
 *
 * Залит светлым налётом, а не тёмной плитой. Тёмная была бы четвёртым
 * тяжёлым пятном на листе после кадров, а налёт показывает столбец, не
 * перекрикивая его содержимое.
 */
.op-vs .is-ours {
  background: color-mix(in srgb, var(--c-accent) 7%, transparent);
  color: var(--c-text);
}

/*
 * Шапка нашего столбца — залита целиком, а не подкрашена.
 *
 * Прежде весь столбец был одним светлым налётом, и читатель видел пятно, а не
 * колонку: где она начинается, глаз определял по цвету заливки, который на
 * семи процентах едва отличим от бумаги.
 *
 * Теперь столбец выглядит панелью с подписанной крышкой: тёмная терракота
 * сверху, светлая под ней. Цвет крышки — тот же `--c-band-warm`, что у
 * выделенного числа и у выбранной строки тарифа; три выделенных места на
 * сайте обязаны быть одним цветом, иначе читаются как три разные мысли.
 */
.op-vs thead .is-ours {
  background: var(--c-band-warm);
  color: var(--c-band-warm-in);
  border-start-start-radius: var(--r-md);
  border-start-end-radius: var(--r-md);
  padding-block: var(--s-5);
  border-block-end-color: transparent;
}

/* Цифры в нашем столбце — табличными: 10, 20, 43–71 стоят друг под другом. */
.op-vs tbody .is-ours { font-variant-numeric: tabular-nums; }

.op-vs tbody tr:last-child .is-ours {
  border-end-start-radius: var(--r-md);
  border-end-end-radius: var(--r-md);
}

@media (max-width: 640px) {
  .op-sheet--wide .op-slider__shot { max-block-size: 48vh; }
}

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

.op-button {
  position: relative;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  transition:
    transform var(--dur-fast) var(--ease),
    box-shadow var(--dur-base) var(--ease),
    filter var(--dur-fast) var(--ease);
}

.op-button__arrow {
  font-style: normal;
  display: inline-block;
  transition: transform var(--dur-base) var(--ease);
}

.op-button:hover { transform: translateY(-2px); }
.op-button:hover .op-button__arrow { transform: translateX(4px); }
.op-button:active { transform: translateY(0); }

/*
 * Здесь был блик — белая полоса, проходящая по кнопке при наведении.
 *
 * Приём тёмного лица: на чёрном он читался как отблеск на металле. На
 * кремовой бумаге кнопка не металлическая, и пробегающий по ней белый луч
 * выглядит как сбой отрисовки. Удалено 29.09.2026.
 */

/*
 * Тень под главной кнопкой — мягкая и тёмная, а не лаймовое свечение.
 *
 * Свечение работало на чёрном: кнопка казалась источником света. На бумаге
 * источников света не бывает, зато бывает тень — и она говорит то же самое
 * («этот предмет ближе к вам»), не притворяясь неоном.
 */
.op-button--big {
  box-shadow: 0 6px 20px color-mix(in srgb, var(--c-text) 14%, transparent);
}

.op-button--big:hover {
  box-shadow: 0 10px 28px color-mix(in srgb, var(--c-text) 20%, transparent);
}


/* ---------- карточки оживают под курсором ---------- */

.op-more__pair,
.op-tier,
.op-flow__card,
.op-flow__dot,
.op-faq__item {
  transition:
    border-color var(--dur-base) var(--ease),
    background var(--dur-base) var(--ease),
    transform var(--dur-base) var(--ease);
}

.op-more__item:hover .op-more__pair {
  border-color: color-mix(in srgb, var(--c-accent) 55%, var(--c-line));
  transform: translateY(-3px);
}

.op-tier:hover { background: var(--c-hover); }

.op-flow__step:hover .op-flow__card {
  background: var(--c-hover);
  border-color: color-mix(in srgb, var(--c-accent) 45%, var(--c-line));
  transform: translateX(4px);
}

/* ---------- появление при прокрутке ---------- */

/*
 * Устроено так, что сломаться нечему.
 *
 * Раздел **виден всегда**. Когда он въезжает в окно, скрипт вешает метку, и
 * проигрывается короткое появление — анимация, а не переключение видимости.
 *
 * Сперва было наоборот: скрипт прятал разделы и показывал по мере прокрутки.
 * Проверить это в здешнем браузере не удалось — он не прокручивается
 * программно и наблюдатель в нём не срабатывает ни разу. Ставить видимость
 * всей страницы в зависимость от того, чего нельзя проверить, нельзя: не
 * загрузился файл, устарел кэш, выключен JavaScript — и ниже первого экрана
 * пустота.
 *
 * Теперь худшее, что бывает: разделы просто появляются без анимации.
 */
@keyframes op-rise {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: none; }
}

[data-reveal='in'] {
  animation: op-rise 620ms var(--ease) both;
}

/* ---------- меньше движения ---------- */

@media (prefers-reduced-motion: reduce) {
  .op-ticker__rail { animation: none; transform: none; }
  .op-button:hover,
  .op-more__item:hover .op-more__pair,
  .op-flow__step:hover .op-flow__card { transform: none; }
  .op-flow::after { transition: none; }
  .op-button:hover .op-button__arrow { transform: none; }
  [data-reveal] { animation: none !important; opacity: 1 !important; transform: none !important; }
}

/* ============================================================
   Отделка
   ============================================================ */

/* ---------- фактура ---------- */


/* ---------- заголовок раздела ---------- */

/* Короткая терракотовая черта над каждым заголовком: ряд разделов получает
   ритм, а акцент — работу помимо кнопок. Слово «малиновая» стояло здесь от
   лица Shelfready и называло цвет, которого в проекте нет с 30.09.2026. */
.op-sec__head h2,
.op-call h2 { position: relative; padding-block-start: var(--s-4); }

.op-sec__head h2::before,
.op-call h2::before {
  content: '';
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  inline-size: 34px;
  block-size: 3px;
  background: var(--c-accent);
  /*
   * Свечения вокруг черты больше нет. Оно писалось под тёмное лицо, где
   * акцент был источником света на странице; на белой бумаге размытый ореол
   * вокруг трёхпиксельной черты читается грязью, а не светом.
   */
}

/* ---------- главное число ---------- */

.op-numbers .is-key b { color: var(--c-accent-text); }

.op-numbers .is-key span { color: var(--c-text); }

/* ---------- меню ---------- */

.op-nav__list a {
  position: relative;
  padding-block-end: 2px;
}

.op-nav__list a::after {
  content: '';
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  block-size: 1px;
  background: var(--c-accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-base) var(--ease);
}

.op-nav__list a:hover::after { transform: scaleX(1); }

/* ---------- вопросы ---------- */

.op-faq__item summary::after {
  transition: transform var(--dur-base) var(--ease);
}

.op-faq__item[open] summary { color: var(--c-text); }

/* ---------- ссылки в примерах ---------- */

.op-tile__link,
.op-history__files a {
  transition: color var(--dur-fast) var(--ease);
}

@media (prefers-reduced-motion: reduce) {
  .op-nav__list a::after { transition: none; }
}

/* ---------- скругление ---------- */

/*
 * Панели, склеенные из ячеек.
 *
 * «Что умеет / что не проверено», ступени цен и панель «до/после» устроены
 * одинаково: решётка с зазором в один пиксель, зазор просвечивает цветом
 * рамки. Своих углов у ячеек нет — скруглять надо оболочку и резать по ней.
 * Скруглив сами ячейки, получаешь вырезы в середине ряда, где две круглые
 * ячейки стоят впритык.
 */
.op-proof,
.op-halves,
.op-tiers,
.op-more__pair {
  border-radius: var(--r-lg);
  overflow: hidden;
}

/* Крупные блоки первой страницы. */
.op-call,
.op-faq {
  border-radius: var(--r-xl);
}

/* Одиночные карточки, кадры, врезки. */
.op-why,
.op-flow__card,
.op-numbers {
  border-radius: var(--r-lg);
}

/* Плашки и подписи. */
.op-flow__tag,
.op-tier__rate,
.op-proof__tag {
  border-radius: var(--r-sm);
}

/* Снимок внутри ячейки скругляется сам: у ячейки углов нет, а прямой угол
   картинки посреди мягкой панели видно сразу. */
.op-proof__shot,
.op-more__pair img {
  border-radius: var(--r-md);
}

/*
 * Первый и последний вопрос повторяют скругление своего списка: иначе прямой
 * угол строки выглядывает из-под круглого угла рамки.
 */
.op-faq__item:first-child {
  border-start-start-radius: var(--r-xl);
  border-start-end-radius: var(--r-xl);
}

.op-faq__item:last-child {
  border-end-start-radius: var(--r-xl);
  border-end-end-radius: var(--r-xl);
}

/* Врезка «зачем» держит розовую грань слева — скругляем только справа,
   иначе грань превращается в дугу и перестаёт читаться линией. */
.op-why {
  border-start-start-radius: 0;
  border-end-start-radius: 0;
}

/*
 * Тонкая светлая грань по верхнему ребру.
 *
 * На тёмном фоне тень не видна вовсе, а свет по ребру делает ту же работу:
 * карточка читается лежащей на странице, а не вырезанной в ней.
 */
.op-flow__card,
.op-why,
.op-numbers,
.op-half,
.op-tier {
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--c-text) 6%, transparent);
}

/* Та же тёплая грань, что и у карточек в components.css. */
.op-flow__card,
.op-why,
.op-numbers,
.op-half,
.op-tier {
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--c-edge) 22%, transparent);
}


/* ---------- вернулось после пересборки ---------- */

/*
 * Тарифы строками ведомости, а не карточками.
 *
 * Карточки со скруглением и заливкой были последним, что роднило страницу с
 * соседями: ровно так набраны цены у Shelfready и у Paperrow. Владелец
 * прислала снимок именно этого места и сказала: всё ещё похоже.
 *
 * Строка честнее и по смыслу: у тарифа четыре числа — сумма, комнаты, цена
 * комнаты, скидка. Это таблица, и притворяться карточкой ей незачем.
 */
.op-tiers {
  list-style: none;
  margin: var(--s-5) 0;
  padding: 0;
}

/*
 * Поля по бокам есть у всех строк, а не только у выделенной.
 *
 * Их не было вовсе: суммы начинались ровно от края колонки и упирались в
 * черту, а «€1.00 each» — в правую. Выделенная строка выглядела приличнее
 * случайно, у неё поля появлялись вместе с заливкой.
 *
 * Теперь поле одно на все строки, и выделенная больше не вылезает за колонку:
 * заливка идёт ровно по ней, а текст внутри стоит там же, где у соседей.
 * Прежний вылет на 16 точек был нужен, чтобы заливка казалась шире текста, —
 * но платой за это было то, что тексты всех строк жались к краю.
 */
.op-tier {
  display: grid;
  grid-template-columns: 7rem minmax(0, 1fr) auto auto;
  gap: var(--s-4) var(--s-5);
  align-items: baseline;
  padding-block: var(--s-4);
  padding-inline: var(--s-5);
  border-block-start: var(--border);
}

.op-tier:last-child { border-block-end: var(--border); }

/*
 * Выбранный — светлой полосой во всю строку.
 *
 * Не рамкой и не другим цветом текста: строка в таблице выделяется тем, что
 * её подложили, как в бумажной ведомости карандашом.
 */
.op-tier.is-pick {
  background: var(--c-band-warm);
  color: var(--c-band-warm-in);
  border-radius: var(--r-md);
  border-block-start-color: transparent;

  /*
   * Инвертируется весь набор, а не только приглушённый.
   *
   * Сперва я переопределил здесь `--c-muted` и забыл `--c-text` — и число
   * комнат в выбранной строке покрасилось в цвет самой полосы, то есть
   * пропало. Нашлось глазами на снимке от владельца.
   *
   * Урок тот же, что с подвалом: полоса — это инверсия, и объявлять надо
   * весь набор сразу, иначе забытое всплывёт ровно там, где его не ждёшь.
   *
   * ## И всплыло: цвет «готово»
   *
   * Скидка была набрана классом `op-off`, а он красился `--c-ok` — зелёным. На
   * терракотовой полосе это 1,57 : 1, на прежней чернильной было 3,58 — тоже
   * ниже нормы. То есть «9,1 % off» в выбранной строке не читался и на прежнем
   * лице; просто на чёрном не бросалось в глаза, что он зелёный.
   *
   * 05.10.2026 скидка переведена на `--c-accent-text`, и подмена `--c-ok`
   * здесь стала не нужна — оставлена на случай, если в строку когда-нибудь
   * попадёт что-то ещё, красящееся цветом состояния.
   */
  --c-text:  var(--c-band-warm-in);
  --c-muted: color-mix(in srgb, var(--c-band-warm-in) 72%, var(--c-band-warm));
  --c-accent-text: var(--c-accent-on-warm);
  --c-ok: var(--c-accent-on-warm);
  --c-line: color-mix(in srgb, var(--c-band-warm-in) 20%, transparent);
}

.op-tier__price {
  margin: 0;
  font-family: var(--f-display);
  font-weight: var(--fw-semi);
  font-size: var(--t-xl);
  line-height: 1;
  letter-spacing: var(--ls-tight);
}

.op-tier__what { margin: 0; font-size: var(--t-sm); color: var(--c-muted); }
.op-tier__what b { color: inherit; }
.op-tier__what b { color: var(--c-text); }

.op-tier__rate {
  margin: 0;
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  color: var(--c-muted);
  font-variant-numeric: tabular-nums;
}


.op-halves {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1px;
  background: var(--c-line);
  border: var(--border);
}

.op-half { background: var(--c-surface); padding: var(--s-6); }
.op-half h3 { font-size: var(--t-xl); margin: 0 0 var(--s-4); }
/*
 * Заголовки половинок — обычным цветом текста, а не зелёным и красным.
 *
 * На ночном лице мятный и лососевый читались как состояния. На терракотовой
 * бумаге красный «Look elsewhere» стал неотличим от фирменного цвета — то
 * есть отрицательная половина оказалась набрана цветом марки, — а зелёный
 * рядом с терракотой завёл на странице второй акцент из ниоткуда.
 *
 * Слова «Send us» и «Look elsewhere» сами говорят, что к чему. Зелёный и
 * красный остаются там, где они и значат состояние: подтверждения и ошибки
 * в полях.
 */
.op-half h3 { color: var(--c-text); }

.op-half ul {
  margin: 0;
  padding-inline-start: var(--s-5);
  color: var(--c-muted);
  font-size: var(--t-sm);
}

.op-half li { margin-block-end: var(--s-3); }

.op-half__note {
  margin: var(--s-5) 0 0;
  font-size: var(--t-sm);
  color: var(--c-muted);
}

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


/* На узком экране строка складывается в две: сумма и комнаты, под ними цена. */
@media (max-width: 640px) {
  .op-tier {
    grid-template-columns: 6rem minmax(0, 1fr);
    gap: var(--s-2) var(--s-4);
  }
  .op-tier__rate { grid-column: 2; }
}
