/* ===== ВИТРИНА ГЛАВНОЙ (index.html). Перенесено из mockups/home-showcase-v2.html 18.08.
   Все классы под префиксом .mk- — прод-классы не переопределяются. ===== */


/* Цвета и тайминги мокапа. Держатся ЗДЕСЬ и только здесь: значение, попавшее прямо в
   правило ниже, через три правки превращается в десятую вариацию того же серого. */
:root {
  /* Проза на светлой бумаге. Темнее --muted: --muted оставлен вспомогательному тексту. */
  --mk-ink-strong: #4f463d;
  /* Финальный CTA. Фон виден, пока грузится кадр; вуаль гасит ткань под текстом.
     Оба тона теплее --bg и в палитре проекта пары не имеют. */
  --mk-final-bg: #f4e6dc;
  --mk-final-veil: #faf3ec;
  --mk-ease-out: cubic-bezier(.16, 1, .3, 1);
  --mk-dur-fast: .18s;
  --mk-dur-mid: .6s;
  --mk-dur-slow: .9s;
}

/* Обрезка по краю страницы — clip, а не hidden: hidden на предке убивает position:sticky
   у потомков, clip сохраняет. Нужен на ОБОИХ элементах, на body одного мало. */
html, body { overflow-x: clip; }

/* Длинные слова в крупных заголовках переносятся внутри слова: у «фотомастерская» и
   «восстановления» другой точки разрыва нет, и на узком экране они уезжают за поле. */
h1, h2 { overflow-wrap: anywhere; min-width: 0; }

/* Один размер на ВСЕ заголовки секций. До этого их было три: четыре секции мокап задавал сам
   (31px), финальный CTA шёл на другом коэффициенте (33.6px), а «Что вы хотите сделать»
   единственный оставался на базовом правиле style.css и вырастал до 48px — почти вровень
   с h1 в hero, отчего страница читалась как два конкурирующих первых экрана.
   Правило стоит ЗДЕСЬ, одно на всех: разъехаться снова можно только сознательно. */
.mk-services .nv-h2,
.mk-books h2,
.mk-how h2,
.mk-pricing h2,
.mk-head h2,
.mk-final h2 { font-size: clamp(24px, 2.6vw, 34px); }

/* Ширина контейнера витрины. Прод сейчас 1220px: на 13-дюймовом ноутбуке (1440 CSS) это
   110px полей с каждой стороны, витрина с сеткой карточек выглядит зажатой. Канон: текстовые
   лендинги 1200-1280 (длина строки), витрины и каталоги 1320-1440. Строки текста при этом
   держим отдельным max-width, поэтому расширение контейнера читаемость не портит. */
/* ⚠️ Новая секция ОБЯЗАНА попасть в этот список. Забытый селектор не ломается заметно:
   контейнер молча падает на проектные 1220px, и секция стоит уже соседних — на широком
   экране это читается как съехавшая вёрстка (так уехали тарифы, правка 18.08). */
.mk-services .container, .mk-books-wrap .container,
.mk-how .container, .mk-pricing .container, .mk-memory .container,
.mk-facts-strip .container,
/* .faq — прод-секция, но стоит между витринными: со своей 1220px она была бы уже соседей. */
.faq .container,
main > .container { max-width:1360px; margin-inline:auto; }
/* Внутренняя раскладка hero держит ту же ширину, что остальные секции, — но САМА СЕКЦИЯ
   и её фоновая картинка идут во всю ширину экрана (правило .mk-hero ниже). */
.mk-hero-inner { max-width:1360px; margin-inline:auto; }
.header .container { max-width:1360px; }

/* --- HERO витрины ---
   Картинка hero-showcase-wide.webp (2.36:1) растянута ФОНОМ НА ВСЮ ШИРИНУ экрана, а слева, под
   текстом, притушена подложкой-переливом. Схема принята оператором по скриншоту 17.08;
   вариант «картинка отдельной колонкой» отвергнут — возвращать нельзя.
   Compact/Medium: та же картинка блоком под текстом. */
.mk-hero { position:relative; overflow:hidden; }
.mk-hero-media { position:absolute; inset:0; z-index:0; }
/* Кадр 2.36:1 (замена оператора 18.08, прежний был 1.79:1). Секция шире кадра на широких
   экранах и УЖЕ него на ноутбучных, поэтому обрезка меняет сторону: при ширине от ~1560px
   режется по высоте, ниже — по бокам.
   Якорь 25% по горизонтали, а не 88%, как было у прежнего кадра: у нового вся правая половина
   занята книгой и вазой, и при правом якоре книга на ноутбуке съезжала под текстовую колонку.
   Левая часть кадра пустая, её потеря безболезненна.
   85% по вертикали держат низ: там лежат карточки снимков, ради которых кадр и выбран.
   Сдвиг вправо на 50px (правка оператора 18.08) сделан не через object-position: кадр
   вписан по ширине целиком, двигать внутри окна нечего. Поэтому сама картинка шире секции
   на 50px и смещена на столько же вправо — слева щели не остаётся, справа уходит край. */
.mk-hero-media img { width:calc(100% + 50px); height:100%; object-fit:cover;
  object-position:50% 85%; display:block; position:relative; left:50px; }
/* Подложка. У левого края НЕПРОЗРАЧНАЯ (1): картинка должна раствориться в фоне страницы
   без видимой границы — на скриншоте оператора переход бесшовный. Дальше плавно сходит на
   нет к правому краю, где стоит книга. Цвет = --bg страницы, иначе стык читается полосой.
   Альфа снимается с самого токена через color-mix: тон фона правится в одном месте. */
.mk-hero-media::after { content:""; position:absolute; inset:0;
  background:linear-gradient(90deg,
    var(--bg) 0%,
    color-mix(in srgb, var(--bg) 94%, transparent) 18%,
    color-mix(in srgb, var(--bg) 62%, transparent) 34%,
    color-mix(in srgb, var(--bg) 24%, transparent) 50%,
    transparent 64%); }
/* Высота долей ширины, а не vh: кадр широкий, при высокой секции cover режет его по бокам и
   книга уезжает за правый край. */
/* Одна колонка: текст занимает левую половину, правая пустая — там из-под него видна книга.
   Картинка лежит СНАРУЖИ этого блока (прямой потомок секции), поэтому его ширина 1360px
   больше её не обрезает. */
/* Низ тяжелее верха: при равных полях секция «висит» отдельной плашкой, а не втекает
   в ритм следующей. */
.mk-hero-inner { position:relative; z-index:1; display:grid; grid-template-columns:minmax(0,46%) 1fr;
  align-items:center; min-height:min(760px, 42.4vw); padding:56px var(--gutter) 76px; }
.mk-hero-text { display:flex; flex-direction:column; justify-content:center; }
/* min-width:0 обязателен: ряд чипов неразрывный, и грид-итем со стандартным min-width:auto
   растягивается под его min-content, унося кнопки и подписи за правое поле экрана. */
.mk-hero-text { min-width:0; position:relative; z-index:1; }
.mk-hero h1 { font-size: clamp(34px, 4.4vw, 56px); line-height:1.05; margin:0 0 18px; letter-spacing:-0.02em; }
.mk-hero h1 em { color: var(--accent); }
.mk-hero-desc { font-size:18px; line-height:1.55; color:var(--mk-ink-strong); margin:0 0 22px; max-width:46ch; }
/* ПОЛОСА ФАКТОВ под hero. Тезисы стоят БЕЗ плашек (правка оператора 18.08): рамка с заливкой
   на светлом фоне читалась как три пустые карточки и спорила с сеткой услуг ниже. Держит ряд
   только сетка из трёх колонок.
   Иконки растровые (нарезаны с листа оператора), поэтому цвет задан в самом файле, а не
   currentColor — менять его правкой CSS нельзя, только перенарезкой. Нормированы по ВЫСОТЕ:
   у широкой «снимок → книга» пропорция 2.1:1, и при квадратном боксе она вдвое мельче соседей. */
.mk-facts-strip { padding: 32px 0 0; }
.mk-facts { display:grid; grid-template-columns:repeat(3, 1fr); gap:28px; margin:0; padding:0;
  list-style:none; }
.mk-fact { display:flex; align-items:center; gap:16px; font-size:16px; line-height:1.4;
  min-width:0; }
.mk-fact img { height:56px; width:auto; flex:0 0 auto; }
/* b — акцент ВНУТРИ фразы, а не заголовок над подписью (правка оператора 18.08): при
   display:block строка разрывалась на «заголовок» и «описание», хотя это одно предложение,
   и читалась порванной. Кегль общий, отличие только в насыщенности. */
.mk-fact b { display:inline; font-size:inherit; font-weight:600; }
.mk-hero-btns { display:flex; flex-wrap:wrap; gap:12px; }

/* ДВИЖЕНИЕ: проявление блоков при прокрутке — четвёртый эффект канона «Движение главной»
   (style.css § 12256), перенесённый на разметку витрины. Скрытие действует ТОЛЬКО под классом
   .mk-motion, который ставит скрипт: не доехал файл — страница видима целиком.
   Задержка идёт от --i (порядковый номер внутри ряда), её проставляет тот же скрипт. */
body.mk-motion [data-reveal] {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 620ms var(--mk-ease-out), transform 620ms var(--mk-ease-out);
  transition-delay: calc(var(--i, 0) * 70ms);
}
body.mk-motion [data-reveal].is-revealed { opacity: 1; transform: none; }

/* --- СЕТКА УСЛУГ ---
   Карточки взяты с главной вместе со своими классами (.vr-quad/.vr-card/.ex-ba), их стили
   лежат в style.css. Здесь меняется ТОЛЬКО раскладка сетки — сами карточки не трогаем.

   Раскладка по эскизу оператора: слева крупная «Восстановить» и рядом вертикальная «Оживить»,
   справа блок 2×2 из четырёх мелких. Держится сценарием
   `node scripts/scenario.mjs home-showcase-services-grid` (два ряда + доля картинки). */
/* Вертикальный ритм всех секций витрины — канон проекта --section-y (72px десктоп / 48px
   мобильный, tokens.css). Раньше здесь стоял самодельный разнобой 8/56/0/56. */
.mk-services { padding: var(--section-y) 0; }
/* Один общий ряд из двух зон: СЛЕВА две крупные карточки («Восстановить» и «Улучшить
   качество») одинаковой ширины, СПРАВА блок 2×2 из четырёх мелких. Переносить мелкие под
   крупные нельзя — правка оператора 17.08.
   Колонок 6: каждая крупная занимает 2 (итого 4 слева, обе одной ширины), каждая мелкая 1 →
   справа ровно 2 колонки в каждом из двух рядов. Ряды равны, иначе мелкие карточки с текстом
   разной длины не бьются по высоте против крупных. */
.mk-services .vr-quad { grid-template-columns: repeat(6, 1fr); grid-template-rows: repeat(2, 290px); }
.mk-services .vr-quad > .vr-card:nth-child(1),
.mk-services .vr-quad > .vr-card:nth-child(2) { grid-column: span 2; grid-row: span 2; }
/* Шторку не растягиваем флексом: прод-скрипт кладёт внутрь картинки с height:100%, и без
   собственной высоты у контейнера они схлопываются в ноль. Высоту даёт сама карточка,
   media забирает остаток над текстом через min-height:0 + overflow. */
.mk-services .vr-quad > .vr-card { overflow: hidden; }
.mk-services .vr-quad > .vr-card .vr-media { aspect-ratio: auto; height: 100%; min-height: 0; }
.mk-services .vr-quad > .vr-card .vr-body { flex: 0 0 auto; }
.mk-services .vr-quad > .vr-card:nth-child(1) h3,
.mk-services .vr-quad > .vr-card:nth-child(2) h3 { font-size: 22px; }
/* Мелкие карточки нижнего ряда: заголовок и описание мельче, мета времени убрана —
   в узкой колонке текстовый низ съедал картинку (у «Улучшить качество» оставалось 35px из 290). */
.mk-services .vr-quad > .vr-card:nth-child(n+3) h3 { font-size: 17px; }
.mk-services .vr-quad > .vr-card:nth-child(n+3) .vr-desc { font-size: 13.5px; line-height: 1.35; }
.mk-services .vr-quad > .vr-card:nth-child(n+3) .restore-meta { display: none; }
.mk-services .vr-quad > .vr-card:nth-child(n+3) .vr-body { padding: 12px 14px 14px; gap: 6px; }
/* 44px — нижняя граница тач-цели (CONVENTIONS.md § Мобильный канон). Прод держит 48px;
   ужимая кнопку под узкую колонку, ниже 44 опускаться нельзя. */
.mk-services .vr-quad > .vr-card:nth-child(n+3) .nv-svc-cta { min-height: 44px; font-size: 14px; padding: 9px 12px; }
/* Описания мелких карточек разной длины — без общей высоты кнопки уезжают на разные уровни
   и ряд выглядит расшатанным. Одна строка: столько занимает самое длинное из четырёх. */
.mk-services .vr-quad > .vr-card:nth-child(n+3) .vr-desc { min-height: calc(13.5px * 1.35 * 2); display: block; }
.mk-head { display:flex; align-items:baseline; justify-content:space-between; gap:16px; margin-bottom:20px; }
.mk-head h2 { margin:0; }
.mk-head a { font-size:15px; color: var(--accent); text-decoration:none; white-space:nowrap; }

/* --- ФОТОКНИГИ --- */
/* Отступ секции живёт на обёртке (.mk-books-wrap), а не на карточке: так ритм у всех
   секций один и задан одним токеном. */
.mk-books-wrap { padding: var(--section-y) 0; }
.mk-books { background: var(--bg-alt); border-radius:24px; padding:32px; display:grid;
  grid-template-columns: minmax(0,0.85fr) minmax(0,1.15fr); gap:32px; align-items:center; margin:0; }
.mk-books h2 { margin:0 0 10px; }
.mk-books p { margin:0 0 20px; font-size:16px; line-height:1.5; color:var(--mk-ink-strong); }
/* Правая колонка секции — слайдер кадров (привод перенесён с лендинга fotokniga.html,
   [data-slides], без изменений в логике). Кадры ведёт движение мыши: ширина поделена на равные
   зоны по числу кадров, показывается кадр той зоны, где курсор. Полоски сверху отмечают
   текущий кадр и кликабельны. */
.mk-books-media { position:relative; height:100%; min-height:clamp(280px,42vh,440px);
  overflow:hidden; border-radius:16px; }
.mk-books-media img { position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
  border-radius:16px; display:block; opacity:0;
  transition:opacity var(--mk-dur-slow) var(--mk-ease-out), transform var(--mk-dur-mid) var(--mk-ease-out); }
.mk-books-media img.on { opacity:1; }
.mk-books-media:hover img.on { transform:scale(1.035); }
/* Под курсором кадры сменяются быстро и без наезда: медленное затухание превратило бы
   проводку мышью в кашу из полупрозрачных наложений. */
.mk-books-media.scrub img { transition:opacity var(--mk-dur-fast) var(--mk-ease-out); }
.mk-books-media.scrub img.on { transform:none; }
.mk-books-media .segs { position:absolute; top:12px; left:12px; right:12px; display:flex; gap:6px; z-index:2; }
.mk-books-media .segs button { position:relative; flex:1; height:4px; padding:0; border:0; appearance:none;
  border-radius:2px; background:color-mix(in srgb, var(--paper-0) 55%, transparent); cursor:pointer;
  transition:background .2s var(--mk-ease-out); }
/* Полоска высотой 4px — не тач-цель. Псевдоэлемент растит область нажатия до 44px по канону,
   не трогая саму отрисовку. */
.mk-books-media .segs button::after { content:''; position:absolute; left:0; right:0; top:-20px; bottom:-20px; }
.mk-books-media .segs button:hover { background:var(--paper-0); }
/* Обводка фокуса не участвует в transition выше: она обязана появляться мгновенно,
   иначе первые кадры перехода клавиатурный пользователь стоит без индикатора. */
.mk-books-media .segs button:focus-visible { outline:2px solid var(--paper-0); outline-offset:4px; }
.mk-books-media .segs button:active { background:var(--paper-0); transform:scaleY(1.5); }
.mk-books-media .segs button.on { background:var(--fg); box-shadow:0 0 0 1px color-mix(in srgb, var(--paper-0) 35%, transparent); }
/* Строка цены: на --bg-alt прежний тон давал 4.04:1 при кегле 14px, ниже нормы 4.5. */
.mk-books-note { display:block; margin-top:10px; font-size:14px; color:var(--muted); }

/* Финальная секция во всю ширину экрана. Кадр final-cta-book.webp (2.35:1) снят под неё:
   восстановленные снимки слева, книга «Семья» справа, середина пустая. Текст стоит по центру,
   в пустой части кадра — по краям он налез бы на снимки или на книгу. */
.mk-final { position:relative; overflow:hidden; margin:0; padding:clamp(56px,7vw,96px) var(--gutter);
  min-height:clamp(320px,30vw,460px); display:flex; align-items:center; justify-content:center;
  text-align:center; background:var(--mk-final-bg); }
.mk-final img { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; object-position:50% 50%; }
/* Заливка мягкая и по центру: гасит ткань под текстом, оставляя снимки слева и книгу справа. */
.mk-final::after { content:""; position:absolute; inset:0;
  background:radial-gradient(ellipse 46% 78% at 50% 50%,
    color-mix(in srgb, var(--mk-final-veil) 90%, transparent) 0%,
    color-mix(in srgb, var(--mk-final-veil) 72%, transparent) 55%,
    transparent 100%); }
.mk-final-inner { position:relative; z-index:1; max-width:min(560px, 52%); margin:0 auto; }

/* --- ПУТЬ ОДНОЙ ФОТОГРАФИИ (в v1 это была секция «как это работает») ---
   Шаг ведёт кадр, а не карточка. Причина замены: четыре одинаковые плашки с номерами
   в пастельных кружках — самый узнаваемый шаблон сгенерированного лендинга, и на странице,
   где всё остальное держится на снимках, он читался вставкой из другого макета.
   Шагов три, а не четыре: «выберите, что сделать» показывает сетка услуг прямо над этой
   секцией, каждой карточкой со своей кнопкой. Повторять её словами нечем. */
.mk-how { padding: var(--section-y) 0; }
.mk-how h2 { margin:0 0 8px; }
.mk-how-lede { margin:0 0 var(--section-head-gap); font-size:16px; line-height:1.5;
  color:var(--muted); max-width:52ch; }
.mk-flow { display:grid; grid-template-columns:repeat(3, minmax(0,1fr)); gap:20px;
  margin:0; padding:0; list-style:none; }
/* Карточка: кадр на всю площадь, текст и номер лежат ПОВЕРХ него.
   Высота задана min-height, а не aspect-ratio: при жёстких пропорциях длинная подпись
   на планшете вылезала бы за нижний край, а так карточка просто подрастает. */
.mk-flow-step { position:relative; min-width:0; overflow:hidden; border-radius:var(--radius);
  min-height:clamp(240px, 25vw, 330px); display:flex; }
/* ⚠️ У figure НЕ ДОЛЖНО быть ни position, ни z-index. Разбор 18.08: кадр лежит ВНУТРИ figure,
   и любой из этих двух признаков превращает figure в отдельный слой. Внутри слоя абсолютный
   кадр (z-index:0) оказывается выше статичной подписи, и картинка закрывает собой текст, а
   заодно уезжает выше затемнения, которое живёт на карточке. Снаружи всё выглядит так, будто
   ни текста, ни затемнения вообще не написали. Геометрия при этом верная, и замеры размеров
   такой дефект не ловят — ловит только проверка «кто лежит сверху в точке заголовка».
   flex:1 обязателен отдельно: одиночный флекс-итем без него сжимается по содержимому. */
/* РИТМ РЯДА (правка оператора 18.08): первый и третий шаги — текст сверху, номер срезан
   снизу; ВТОРОЙ перевёрнут. Одинаковая раскладка у всех трёх читалась плоско, а перевёрнутый
   средний даёт ряду ход. Всё, что относится к второму шагу, собрано в одном блоке ниже —
   иначе перестановка разъезжается по трём разным правилам. */
.mk-flow figure { margin:0; flex:1; display:flex; flex-direction:column;
  padding:clamp(20px, 2vw, 28px); }
.mk-flow-step:nth-child(2) figure { justify-content:flex-end; }
.mk-flow img { position:absolute; inset:0; z-index:0; width:100%; height:100%;
  object-fit:cover; display:block; }
/* Кадр второго шага вертикальный (375×562) и в широкой карточке обрезается сильнее прочих:
   при центровке лицо уходит под верхний край. Окно поднято к голове. */
.mk-flow-step:nth-child(2) img { object-position:50% 28%; }
/* Затемнение. Тон снят с --dark, а не с чистого чёрного: на тёплых архивных снимках чёрная
   вуаль уходит в синеву. Плотность верхнего стопа посчитана от ХУДШЕГО случая, а не подобрана
   на глаз: если под подписью окажется выбеленный участок снимка, при 85% белый текст держит
   5.07:1, при 74% падал до 3.3:1 — ниже нормы 4.5. */
.mk-flow-step::before { content:""; position:absolute; inset:0; z-index:1;
  background:linear-gradient(180deg,
    color-mix(in srgb, var(--dark) 85%, transparent) 0%,
    color-mix(in srgb, var(--dark) 62%, transparent) 55%,
    color-mix(in srgb, var(--dark) 52%, transparent) 100%); }
/* У перевёрнутого шага плотная часть обязана переехать вниз, под подпись: иначе белый текст
   ложится на самый светлый край кадра. Стопы те же, читаются снизу вверх. */
.mk-flow-step:nth-child(2)::before {
  background:linear-gradient(0deg,
    color-mix(in srgb, var(--dark) 85%, transparent) 0%,
    color-mix(in srgb, var(--dark) 62%, transparent) 55%,
    color-mix(in srgb, var(--dark) 52%, transparent) 100%); }
/* Номер уходит за ЛЕВЫЙ НИЖНИЙ угол и срезается там. Он метка порядка, а не элемент, который
   надо прочитать: aria-hidden в разметке стоит, а саму последовательность несёт тег ol.
   У перевёрнутого шага номер переезжает наверх, но срез там МЕЛЬЧЕ (-.06em против -.17em):
   при равном срезе двойка теряет верхнюю дугу и перестаёт читаться как цифра. */
.mk-flow-num { position:absolute; z-index:2; left:-.05em; bottom:-.17em;
  font-size:clamp(88px, 10.5vw, 148px); font-weight:800; line-height:.74; letter-spacing:-.04em;
  color:color-mix(in srgb, var(--paper-0) 48%, transparent); pointer-events:none; }
.mk-flow-step:nth-child(2) .mk-flow-num { bottom:auto; top:-.06em; }
/* Подпись поднята над затемнением своим z-index. Без него она статична и остаётся ПОД
   абсолютным кадром — тот же дефект, что описан у figure выше. */
.mk-flow figcaption { position:relative; z-index:3; color:var(--paper-0); }
.mk-flow figcaption b { display:block; font-size:clamp(17px, 1.5vw, 20px); margin-bottom:6px; }
.mk-flow figcaption span { display:block; font-size:15px; line-height:1.45;
  color:color-mix(in srgb, var(--paper-0) 88%, transparent); max-width:30ch; }

/* --- ТАРИФЫ ---
   Карточек пакетов здесь намеренно НЕТ: полная сетка тарифов живёт на главной, а на витрине
   ряд плашек конкурировал бы с сеткой услуг за то же внимание. Задача блока — снять вопрос
   «сколько», а не продать пакет. Отсюда типографика и линейка сверху вместо карточек.
   Два продукта считаются по-разному: реставрация пакетами обработок, фотокнига за экземпляр
   с доставкой, поэтому цены стоят раздельно, а не сводятся в одну цифру. */
.mk-pricing { padding: var(--section-y) 0; }
/* Подзаголовок секции снят (правка оператора 18.08), поэтому отступ до сетки цен держит сам
   заголовок: 8px были рассчитаны на абзац под ним, без него заголовок липнет к линейкам. */
.mk-pricing h2 { margin:0 0 var(--section-head-gap); }
.mk-price-grid { display:grid; grid-template-columns:repeat(2, minmax(0,1fr)); gap:40px; }
/* Жирная линейка сверху — единственный «разделительный» приём на странице: она задаёт блоку
   свой голос, не добавляя ещё одного вида карточки. */
.mk-price { border-top:2px solid var(--fg); padding-top:16px; min-width:0; }
.mk-price-what { margin:0 0 6px; font-size:15px; color:var(--muted); }
.mk-price-figure { margin:0 0 10px; font-size: clamp(28px, 3.2vw, 38px); line-height:1.05; font-weight:700; }
.mk-price p { margin:0 0 14px; font-size:15px; line-height:1.5; color:var(--muted); max-width:46ch; }
/* Кнопки вместо текстовых ссылок (правка оператора 18.08). Колонка — флекс, кнопка прижата
   к низу через margin-top:auto: описания у продуктов разной длины, и без этого кнопки встают
   на разной высоте. Сами колонки растягиваются грид-контейнером до одной высоты (stretch по
   умолчанию), поэтому низ у них общий.
   align-self:flex-start обязателен: иначе кнопка растянется на всю ширину колонки. */
.mk-price { display:flex; flex-direction:column; }
.mk-price .btn { margin-top:auto; align-self:flex-start; }

/* --- АЛЬБОМ ПАМЯТИ --- */
.mk-memory { padding: var(--section-y) 0; }
/* Плитку строит initMemoryAlbum() из design.js, раскладка и кадрирование живут в
   memory-album.css (.memory-bento): ряд 130px, карточка span 2 = 260px, кадр смещён к лицу
   (center 30%). Витринные правила плитки были бы мёртвым дублем и здесь не держатся. */
/* Высокая карточка занимает два ряда и обрезает портрет слабее всех: там центровка честнее,
   поднятое окно уводит подбородок под подпись. */
/* Подложка подписи берётся с --dark, а не с чистого чёрного: на тёплых снимках чёрный
   уходит в синеву и подпись выглядит наклейкой. */
/* Подпись клиента и его имя разделены: без имени и даты это не воспоминание, а просто текст
   на снимке. Имя мельче и приглушено — оно подпись под цитатой, а не сама цитата. */
.mk-memory-more { margin-top:24px; text-align:center; }

/* --- ФИНАЛЬНЫЙ CTA ---
   Раскладка секции задана выше (.mk-final с фоновым снимком). Здесь только типографика:
   фон и геометрию тут не переобъявлять, иначе картинка снова перекроется заливкой. */
.mk-final h2 { margin:0 0 10px; }
.mk-final p { margin:0 0 22px; font-size:17px; color:var(--mk-ink-strong); }
.mk-final-btns { display:flex; gap:12px; justify-content:center; flex-wrap:wrap; }

/* --- Medium (600–1023) --- */
@media (max-width: 1023px) {
  .mk-hero-inner { grid-template-columns:1fr; min-height:0; padding:28px var(--gutter) 0; }
  .mk-hero-media { position:static; margin-top:24px; border-radius:18px; overflow:hidden; }
  /* Пропорция бокса подогнана под сам кадр (2.36:1): при 16/9 у него срезало бы бока,
     а там книга справа и пустая ткань слева. */
  .mk-hero-media img { aspect-ratio:2.2/1; height:auto; object-position:50% 60%; width:100%; left:0; }
  .mk-hero-media::after { display:none; }
  /* Планшет: 2 колонки. Крупная во всю ширину, «Оживить» перестаёт быть вертикальной —
     на такой ширине высокая карточка рядом с широкой не читается. */
  /* Планшет: 2 колонки. Крупные во всю ширину друг под другом, мелкие парами. */
  .mk-services .vr-quad { grid-template-columns: repeat(2, 1fr); grid-template-rows: none; grid-auto-rows: 320px; }
  .mk-services .vr-quad > .vr-card:nth-child(1),
  .mk-services .vr-quad > .vr-card:nth-child(2) { grid-column: span 2; }
  .mk-books { grid-template-columns:1fr; }
  .mk-books-media { height:clamp(230px,38vh,360px); min-height:0; }
  /* Три кадра выживают и на планшете: они широкие, но низкие. Ломать их на 2+1 нельзя —
     одинокий третий шаг во втором ряду рвёт последовательность. */
  .mk-flow { gap:18px; }
}
/* --- Compact (≤599) --- */
@media (max-width: 599px) {
  .mk-hero-inner { padding:20px var(--gutter) 0; }
  .mk-hero-desc { font-size:16px; }
  /* На телефоне три колонки не читаются: заголовок плашки ломается по слогам. Ставим в столбик. */
  .mk-facts { grid-template-columns:1fr; gap:8px; }
  .mk-facts::-webkit-scrollbar { display:none; }
  .mk-fact { font-size:14px; padding:8px 10px; }
  .mk-fact b { font-size:15px; }
  .mk-hero-btns .btn { width:100%; justify-content:center; }
  .mk-hero-media { margin-top:18px; border-radius:14px; }
  /* На телефоне кадр целиком нечитаем: книга становится мелкой. Берём правую часть,
     где книга и карточки, и держим бокс ближе к квадрату. */
  .mk-hero-media img { aspect-ratio:3/2; object-position:64% 60%; }
  /* Телефон: одна колонка, все карточки одного размера — прод-поведение .vr-quad. */
  /* Телефон: одна колонка, все карточки одного размера — прод-поведение .vr-quad. */
  .mk-services .vr-quad { grid-template-columns: 1fr; grid-template-rows: none; grid-auto-rows: 300px; }
  .mk-services .vr-quad > .vr-card:nth-child(1),
  .mk-services .vr-quad > .vr-card:nth-child(2) { grid-column: auto; }
  .mk-services .vr-quad > .vr-card:nth-child(n+3) h3 { font-size: 19px; }
  .mk-services .vr-quad > .vr-card:nth-child(n+3) .vr-desc { font-size: 14.5px; min-height: 0; }
  .mk-books { padding:20px; border-radius:18px; }
  .mk-books-media { height:clamp(200px,32vh,300px); }
  /* Телефон: кадры друг под другом. Стрелка снимается — вертикальную последовательность
     читает сам порядок сверху вниз, горизонтальная стрелка тут указывала бы за край. */
  .mk-price-grid { grid-template-columns:1fr; gap:28px; }
  .mk-flow { grid-template-columns:1fr; gap:24px; }
  .mk-flow-step { min-height:220px; }
  .mk-flow figcaption span { font-size:16px; }
  /* Тот же расчёт, что на десктопе: колонка на телефоне ~166px, при ряде 120px карточка
     выходила 1.4:1 и снова резала лица. 150px дают почти квадрат. */
  /* Мобильный канон: вспомогательный текст не мельче 14px. Имя автора под подписью
     на десктопе 13px, на телефоне поднимается до порога. */
  /* На узком экране от кадра 2.35:1 остаётся середина: якорь по центру держит в нём книгу,
     а текст ложится на пустую ткань. */
  .mk-final img { object-position:62% 50%; }
  .mk-head { flex-direction:column; align-items:flex-start; gap:6px; }

  /* ═══ МОБИЛЬНЫЙ КАНОН ВИТРИНЫ (приёмка оператора 19.08) ═══════════════════════════════
     Правки приняты на мокапе mock-canon-index.html; замер: 81 нарушение канона → 12.
     Проверка — node scripts/scenario.mjs mobile-canon-audit --page /index.html
     и node scripts/scenario.mjs mock-canon-cards.

     ── УСЛУГИ: карточка-строкой, текст не режется ──
     Корень прежнего дефекта: правила выше задают витрине grid с фиксированной высотой ряда
     и .vr-body { flex: 0 0 auto } — запрет на сжатие. Мобильный блок style.css (~1256-1290,
     написан 29.07 под этот же канон) до него не доходил: style.css подключён РАНЬШЕ.
     Итог: колонка текста распиралась до min-content (489-540px в карточке 341px), и
     overflow: hidden прятал заголовок с описанием — видно 341px из 621-672px. */
  .mk-services .vr-quad {
    grid-template-columns: 1fr;
    grid-template-rows: none;
    /* 1fr, а не auto: карточки выравниваются между собой, а не по длине своего текста
       (было 244 / 224 / 196 — ряд читался ступеньками). Не фиксированное число: высота
       считается по самой длинной карточке текущей ширины, поэтому текст не обрезается —
       именно фиксированные 300px и дали исходный дефект. */
    grid-auto-rows: 1fr;
    gap: 10px;
  }
  .mk-services .vr-quad > .vr-card:nth-child(1),
  .mk-services .vr-quad > .vr-card:nth-child(2) { grid-column: auto; grid-row: auto; }

  .mk-services .vr-quad > .vr-card {
    flex-direction: row;
    align-items: stretch;
    overflow: hidden;
    min-height: 196px;
  }
  /* Кадр прижат к краю карточки и тянется на всю её высоту. Пропорция здесь НЕ задаётся:
     с aspect-ratio вокруг кадра оставались белые поля и снимок читался как наклейка.
     Одинаковую обрезку у всех шести даёт общая высота ряда (grid-auto-rows: 1fr выше). */
  .mk-services .vr-quad > .vr-card .vr-media,
  .mk-services .vr-quad > .vr-card .vr-media--video {
    width: 132px;
    flex: 0 0 132px;
    align-self: stretch;
    height: auto;
    aspect-ratio: auto;
    overflow: hidden;
    border-radius: 0;
  }
  /* Кадр заполняет рамку без полей. У «Убрать фон» стоит object-fit: contain (вырез на
     белом) — на узком мобильном кадре это давало пустые поля по бокам, читалось как брак. */
  .mk-services .vr-quad > .vr-card .vr-media img {
    width: 100%;
    height: 100%;
    object-fit: cover !important;
  }
  /* :nth-child обязателен: у карточек 3-6 выше своё правило с padding 14px, и без равной
     специфичности их колонка выходит уже, а кнопка на 8px короче — ряд кнопок неровный. */
  .mk-services .vr-quad > .vr-card .vr-body,
  .mk-services .vr-quad > .vr-card:nth-child(n+3) .vr-body {
    flex: 1 1 auto;
    min-width: 0;              /* ключевая строка: разрешает колонке сжиматься */
    padding: 12px 10px;        /* 10px, а не 14: кнопка растянута на колонку, поля идут из неё */
    gap: 4px;
    justify-content: center;
  }

  /* ── КЕГЛЬ: канон 16px тело / 14px вспомогательное ── */
  .mk-services .vr-quad > .vr-card h3,
  .mk-services .vr-quad > .vr-card:nth-child(1) h3,
  .mk-services .vr-quad > .vr-card:nth-child(2) h3,
  .mk-services .vr-quad > .vr-card:nth-child(n+3) h3 { font-size: 16px; line-height: 1.25; }
  .mk-services .vr-quad > .vr-card .vr-desc,
  .mk-services .vr-quad > .vr-card:nth-child(n+3) .vr-desc {
    font-size: 16px;           /* было 13.5: описание карточки — тело, канон даёт 16 */
    line-height: 1.35;
    min-height: 0;
    display: block;
  }
  .mk-services .vr-quad > .vr-card .restore-meta,
  .mk-services .vr-quad > .vr-card .restore-meta-i { font-size: 14px; }
  .mk-services .vr-quad > .vr-card .restore-meta {
    justify-content: flex-start; margin-top: 6px; padding: 0; gap: 3px 10px;
  }
  /* Кнопка во всю ширину колонки: по надписи ширины выходили 119-183px и ряд читался
     рваным. Растянутая кнопка заодно вмещает «Улучшить качество» одной строкой.
     Радиус 12 = ровно четверть высоты 48. Без white-space: nowrap — на 320px кнопка
     распирала бы карточку наружу (замер: 28 вылетов за экран). */
  .mk-services .vr-quad > .vr-card .nv-svc-cta,
  .mk-services .vr-quad > .vr-card:nth-child(n+3) .nv-svc-cta {
    min-height: 44px;
    font-size: 16px;
    padding: 10px 12px;
    margin-top: 8px;
    align-self: stretch;
    width: 100%;
    max-width: 100%;
    border-radius: 12px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  /* «Крупно» скрыта: тап по кадру открывает то же сравнение (решение 29.07). */
  .mk-services .vr-quad > .vr-card .vr-zoom { display: none; }
  /* Плашки «До/После» сняты на телефоне (решение оператора 19.08): на кадре 132px метка
     занимала треть ширины и спорила со снимком. Смысл не теряется — шторка читается сама:
     слева тусклое/чёрно-белое, справа результат. На десктопе плашки остаются. */
  .mk-services .vr-quad > .vr-card .ba-tag { display: none; }

  /* ── ФОТОКНИГА: заголовок → картинка → текст → CTA ──
     Было: весь текстовый блок, и только под ним картинка — до кадра нужно было
     проскроллить шесть строк прозы. display: contents распускает текстовую ячейку
     прямыми элементами грида, после чего заголовок, абзац и кнопка получают свой order. */
  .mk-books { grid-template-columns: 1fr; gap: 16px; padding: 20px; }
  .mk-books > div:not(.mk-books-media) { display: contents; }
  .mk-books h2 { order: 1; margin: 0; }
  .mk-books-media { order: 2; }
  .mk-books p { order: 3; margin: 0; }
  /* CTA выровнена так же, как кнопки услуг: во всю ширину, надпись по центру. */
  .mk-books .btn { order: 4; width: 100%; justify-content: center; text-align: center; }
  .mk-books-note { order: 5; text-align: center; }
  /* Пропорция вместо высоты в vh: на низких экранах кадр съедал пол-экрана,
     на высоких вытягивался в полосу. cursor — подсказка, что кадр реагирует на тап. */
  .mk-books-media { height: auto; min-height: 0; aspect-ratio: 4 / 3; cursor: pointer; }
  /* Полоски крупнее: они и индикатор, и вторая точка входа в листание. */
  .mk-books-media .segs { top: 10px; left: 10px; right: 10px; gap: 5px; }
  .mk-books-media .segs button { height: 5px; border-radius: 3px; }

  /* ── ПОЛОСА ФАКТОВ: текст на одной линии ──
     Иконки нарисованы разной ширины (341 / 279 / 546 при равной высоте), а правило выше
     задавало height + width: auto — колонка иконки выходила разной, и текст каждой строки
     начинался со своего отступа: «плавал». Фиксируем колонку, рисунок вписываем внутрь. */
  .mk-fact {
    display: grid;
    grid-template-columns: 64px 1fr;
    align-items: center;
    gap: 16px;
    padding: 10px 0;
  }
  .mk-fact img { height: 56px; width: 64px; object-fit: contain; object-position: center; }
  .mk-fact span { font-size: 16px; line-height: 1.35; }
  .mk-fact b { font-size: 16px; }
  .mk-books-note { font-size: 14px; }
  .mk-price-what { font-size: 16px; }
  .mk-price-card p { font-size: 16px; }

  /* ── ПУТЬ ФОТОГРАФИИ: цифры одинаково у всех трёх шагов ──
     На десктопе у второго шага номер вынесен наверх — так ряд из трёх карточек держит
     ритм. На телефоне карточки идут столбцом, ритма в этом нет, а разнобой читается как
     ошибка. Срез −.06em, а не −.17em: при большем двойка теряет нижнюю дугу и становится
     закорючкой (об этом же предупреждает комментарий у .mk-flow-num). */
  .mk-flow-step .mk-flow-num,
  .mk-flow-step:nth-child(2) .mk-flow-num { top: auto; bottom: -.06em; }
  /* Подпись второго шага прижата книзу правилом justify-content: flex-end — на телефоне
     это ставило текст поверх цифры. Возвращаем общий порядок. */
  .mk-flow-step:nth-child(2) figure { justify-content: flex-start; }
}

/* Компакт ≤360: кадр уже, кегль НЕ снижаем — канон запрещает мельчить шрифт ради
   раскладки, вместо этого сужаем медиа и отдаём место тексту. */
@media (max-width: 360px) {
  .mk-services .vr-quad > .vr-card .vr-media,
  .mk-services .vr-quad > .vr-card .vr-media--video { width: 116px; flex: 0 0 116px; }
  .mk-services .vr-quad > .vr-card .nv-svc-cta { padding: 10px 10px; }
}

/* --- Пониженная подвижность ---
   Смена кадров в слайдере остаётся (иначе полоски перестают что-либо означать), но
   становится мгновенной сменой без наплыва и без наезда масштабом. Автосмену выключает
   скрипт внизу страницы: одним CSS её не остановить. */
@media (prefers-reduced-motion: reduce) {
  .mk-books-media img { transition:opacity 100ms linear; }
  .mk-books-media:hover img.on { transform:none; }
  .mk-books-media .segs button:active { transform:none; }
}
