/* Сгенерировано tools/clean.mjs — не править руками. */
/* Правки вносить в src/css/overrides.css */
@font-face{font-family:'ANGST';src:url('../fonts/Angst-Thin.woff2?v=c93a25b5') format('woff2');font-weight:100 900;font-style:normal;font-display:block}
*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth}
body{font-family:'ANGST','Roboto',sans-serif;-webkit-font-smoothing:antialiased;background:#1a1a1a;line-height:1.44;overflow-x:hidden}
::selection{background:#9e1f1c;color:#fff}
input::placeholder,textarea::placeholder{color:rgba(38,38,38,.4)}
@keyframes floatUp{from{opacity:0;transform:translateY(24px)}to{opacity:1;transform:translateY(0)}}
@keyframes uspMarquee{from{transform:translateX(0)}to{transform:translateX(-50%)}}
[data-caro-track]{display:grid;gap:16px}
[data-caro="4"] [data-caro-track]{grid-template-columns:repeat(4,1fr)}
[data-caro="3"] [data-caro-track]{grid-template-columns:repeat(3,1fr)}
[data-caro="works"] [data-caro-track]{display:flex;grid-template-columns:none;overflow-x:auto;scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;scrollbar-width:none;gap:16px;padding-bottom:4px}
[data-caro="works"] [data-caro-item]{scroll-snap-align:start;flex:0 0 calc((100% - 32px)/3)}
[data-caro="works"] [data-caro-ctrl]{display:flex !important}
[data-caro-track]::-webkit-scrollbar{display:none}
[data-caro-ctrl]{display:none !important}
body{font-family:'ANGST','Roboto',sans-serif;-webkit-font-smoothing:antialiased;background:#1a1a1a;line-height:1.44}
a{color:#e0726f;text-decoration:none}
a:hover{color:#fff}
[data-caro-track]{display:grid;gap:14px;align-items:start}
[data-caro-track]{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
[data-caro-item] > img, [data-caro-item] > video{width:100%;aspect-ratio:4/5;object-fit:cover;border-radius:6px;display:block;box-shadow:0 18px 48px rgba(0,0,0,.32)}
@media(max-width:860px){
    [data-caro-track]{display:flex !important;grid-template-columns:none !important;overflow-x:auto;scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;scrollbar-width:none;padding-bottom:2px}
    [data-caro-item]{scroll-snap-align:start;flex:0 0 auto;flex-basis:64% !important}
    [data-caro-ctrl]{display:flex !important}
  }
@media(max-width:860px){
    section{padding-left:20px !important;padding-right:20px !important;padding-top:64px !important}
    footer{padding-left:20px !important;padding-right:20px !important}
    h1{font-size:48px !important;line-height:1.08 !important}
    h2{font-size:34px !important;line-height:1.12 !important}
    header{display:flex !important;justify-content:space-between !important;gap:12px !important}
    header nav{display:none !important}
    [data-cols^="1.55fr"]{grid-template-columns:1fr !important}
    [data-cols^="1.4fr.6fr"]{grid-template-columns:1fr !important}
    [data-cols^="1fr1fr"]{grid-template-columns:1fr !important}
    [data-cols^="repeat(5"]{grid-template-columns:repeat(3,1fr) !important}
    [data-cols^="repeat(3"]{grid-template-columns:1fr 1fr !important}
    [data-cols^="1.4fr1fr1fr1fr"]{grid-template-columns:1fr 1fr !important}
  }
@media(max-width:860px){
    section{padding-left:20px !important;padding-right:20px !important;padding-top:52px !important}
    h1{font-size:38px !important;line-height:1.1 !important}
    h2{font-size:28px !important}
    header{padding-left:20px !important;padding-right:20px !important}
    header nav{display:none !important}
    [data-caro-track]{grid-template-columns:repeat(2,1fr) !important;gap:12px !important}
    [data-cols^="1.3fr.7fr"]{grid-template-columns:1fr !important}
    [data-cols^="repeat(2"]{grid-template-columns:1fr !important}
    [data-vhero]{grid-template-columns:1fr !important;gap:26px !important}
    [data-vwrap]{max-width:360px;margin:0 auto}
  }
@media(max-width:860px){
    [data-vhero]{grid-template-columns:1fr !important;gap:26px !important}
    [data-vwrap]{max-width:360px;margin:0 auto}
    section{padding-left:20px !important;padding-right:20px !important;padding-top:56px !important}
    h1{font-size:40px !important;line-height:1.1 !important}
    h2{font-size:30px !important}
    header{padding-left:20px !important;padding-right:20px !important}
    header nav{display:none !important}
    [data-cols^="1.3fr.7fr"]{grid-template-columns:1fr !important}
    [data-cols^="repeat(3"]{grid-template-columns:1fr 1fr !important}
    [data-cols^="repeat(2"]{grid-template-columns:1fr !important}
  }
@media(max-width:860px){
    [data-vhero]{grid-template-columns:1fr !important;gap:26px !important}
    [data-vwrap]{max-width:360px;margin:0 auto}
    section{padding-left:20px !important;padding-right:20px !important;padding-top:56px !important}
    h1{font-size:40px !important;line-height:1.1 !important}
    h2{font-size:30px !important}
    header{padding-left:20px !important;padding-right:20px !important}
    header nav{display:none !important}
    [data-caro-track]{grid-template-columns:repeat(2,1fr) !important;gap:12px !important}
    [data-cols^="1.3fr.7fr"]{grid-template-columns:1fr !important}
    [data-cols^="repeat(2"]{grid-template-columns:1fr !important}
  }
@media(max-width:860px){
    [data-vhero]{grid-template-columns:1fr !important;gap:26px !important}
    [data-vwrap]{max-width:360px;margin:0 auto}
    section{padding-left:20px !important;padding-right:20px !important;padding-top:56px !important}
    h1{font-size:40px !important;line-height:1.1 !important}
    h2{font-size:30px !important}
    header{padding-left:20px !important;padding-right:20px !important}
    header nav{display:none !important}
    [data-caro-track]{grid-template-columns:repeat(2,1fr) !important;gap:12px !important}
    [data-cols^="1.3fr.7fr"]{grid-template-columns:1fr !important}
    [data-cols^="repeat(2"]{grid-template-columns:1fr !important}
    [data-cols^="1fr1fr"]{grid-template-columns:1fr !important}
  }
@media(max-width:860px){
    [data-vhero]{grid-template-columns:1fr !important;gap:26px !important}
    [data-vwrap]{max-width:360px;margin:0 auto}
    section{padding-left:20px !important;padding-right:20px !important;padding-top:48px !important}
    h1{font-size:40px !important;line-height:1.1 !important}
    h2{font-size:30px !important}
    header{padding-left:20px !important;padding-right:20px !important}
    [data-caro-track]{display:flex !important;grid-template-columns:none !important;overflow-x:auto;scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;scrollbar-width:none;padding-bottom:2px}
    [data-caro-item]{scroll-snap-align:start;flex:0 0 auto;flex-basis:82% !important}
    [data-caro-ctrl]{display:flex !important}
    [data-cols^="1.3fr.7fr"]{grid-template-columns:1fr !important}
    [data-cols^="1fr1fr"]{grid-template-columns:1fr !important}
    [data-cols^="repeat(3"]{grid-template-columns:1fr 1fr !important}
  }
@media(max-width:860px){
    section{padding-left:20px !important;padding-right:20px !important;padding-top:48px !important}
    h1{font-size:40px !important;line-height:1.1 !important}
    h2{font-size:30px !important}
    header{padding-left:20px !important;padding-right:20px !important}
    header nav{display:none !important}
    [data-cols^="1.3fr.7fr"]{grid-template-columns:1fr !important}
    [data-cols^="1fr1fr"]{grid-template-columns:1fr !important}
    [data-cols^="repeat(2"]{grid-template-columns:1fr !important}
  }
@media(max-width:860px){
    [data-vhero]{grid-template-columns:1fr !important;gap:26px !important}
    [data-vwrap]{max-width:360px;margin:0 auto}
    section{padding-left:20px !important;padding-right:20px !important;padding-top:48px !important}
    h1{font-size:40px !important;line-height:1.1 !important}
    h2{font-size:30px !important}
    header{padding-left:20px !important;padding-right:20px !important}
    header nav{display:none !important}
    [data-cols^="1.3fr.7fr"]{grid-template-columns:1fr !important}
    [data-cols^="1fr1fr"]{grid-template-columns:1fr !important}
    [data-caro-track]{grid-template-columns:repeat(2,1fr) !important;gap:12px !important}
  }
@media(max-width:600px){[data-caro] [data-caro-item]{flex-basis:85% !important}}
@media(max-width:600px){
    h1{font-size:38px !important}
    h2{font-size:27px !important}
    [data-cols^="repeat(3"]{grid-template-columns:1fr !important}
    [data-cols^="repeat(5"]{grid-template-columns:1fr 1fr !important}
    [data-cols^="1.4fr1fr1fr1fr"]{grid-template-columns:1fr 1fr !important}
  }
@media(max-width:600px){h1{font-size:31px !important}h2{font-size:24px !important}[data-caro-item]{flex-basis:88% !important}[data-vwrap]{max-width:320px}}
@media(max-width:600px){h1{font-size:32px !important}h2{font-size:25px !important}}
@media(max-width:600px){h1{font-size:32px !important}h2{font-size:25px !important}[data-caro-item]{flex-basis:88% !important}}
@media(max-width:600px){h1{font-size:32px !important}[data-cols^="repeat(3"]{grid-template-columns:1fr !important}}
@media(max-width:600px){h1{font-size:32px !important}}
/* Ховеры и фокусы, спасённые из CSSOM прототипа */
.hv-906abf80:hover{background: rgb(184, 36, 31);}
.hv-c71452d6:hover{background: rgb(184, 36, 31); transform: translateY(-2px);}
.hv-9996326b:hover{background: rgba(255, 255, 255, 0.2);}
.hv-b91c0fc8:hover{border-color: rgb(158, 31, 28); transform: translateY(-3px);}
.hv-12a9cda5:hover{opacity: 0.82;}
.hv-a1c58b4f:focus{border-color: rgb(158, 31, 28);}
.hv-250f8c27:hover{border-color: rgb(158, 31, 28); background: rgba(158, 31, 28, 0.06);}
.hv-9b9e5b3c:hover{background: rgba(38, 38, 38, 0.1);}
.hv-98dfe923:hover{background: rgba(255, 255, 255, 0.18);}
.hv-77f798ee:hover{background: rgb(244, 242, 239);}
.hv-3e24cf1a:hover{background: rgba(20, 20, 20, 0.7);}
.hv-6d650ee8:hover{gap: 14px;}
.hv-fd56fee1:hover{color: rgb(255, 255, 255);}
.hv-79fbc317:hover{background: rgba(255, 255, 255, 0.16);}
.hv-a58c2888:hover{background: rgba(255, 255, 255, 0.2); color: rgb(255, 255, 255);}
/* ── src/css/overrides.css ── */
/* ═══════════════════════════════════════════════════════════════
   Правки поверх стилей прототипа.

   Этот файл — единственное место для ручных правок CSS.
   Всё остальное в style.css генерируется из исходников .dc.html
   и затирается при каждой пересборке.

   Дизайн и типографику не меняем — только чиним то, что мешает
   пользоваться сайтом с телефона.
   ═══════════════════════════════════════════════════════════════ */


/* ─── 1. Галереи на страницах работ: сетка, не карусель ───────────

   В прототипе на 860px ВСЕ галереи превращались в горизонтальный
   свайп. На страницах работ это давало 7 рядов по 2 фото шириной
   ~160px и не листалось: стрелки были спрятаны глобальным правилом
   [data-caro-ctrl]{display:none!important}, а overflow-x никто не
   задавал. Решено оставить слайдер только на главной, а на работах
   показывать нормальную сетку.                                     */

body:not([data-page="home"]) [data-caro-track] {
  display: grid !important;
  grid-template-columns: repeat(3, 1fr) !important;
  gap: 16px;
  overflow-x: visible !important;
  scroll-snap-type: none !important;
}

body:not([data-page="home"]) [data-caro-item] {
  flex-basis: auto !important;
  scroll-snap-align: none !important;
}

@media (max-width: 860px) {
  body:not([data-page="home"]) [data-caro-track] {
    grid-template-columns: repeat(2, 1fr) !important;
    gap: 12px;
  }
}

@media (max-width: 600px) {
  /* На телефоне одна колонка: фото во всю ширину, детали видно.
     Две колонки по ~160px — это ровно та проблема, ради которой
     всё и затевалось. */
  body:not([data-page="home"]) [data-caro-track] {
    grid-template-columns: 1fr !important;
    gap: 12px;
  }
}


/* ─── 1а. Заголовки не должны ронять хвост на отдельную строку ───

   На Шотландии заголовок «Объект «Современная классика»» ломался так,
   что закрывающая кавычка уезжала на третью строку одна. Причина не в
   кавычке: колонка под видео забирает 430px, тексту остаётся 834px,
   и 62px-заголовок туда в две строки не влезает.

   text-wrap:balance выравнивает длину строк и не оставляет висячих
   хвостов. Браузеры без поддержки просто игнорируют свойство.          */

h1,
h2,
h3 {
  text-wrap: balance;
}

/* Абзацы — pretty: он борется именно с висячим последним словом. */
p {
  text-wrap: pretty;
}


/* ─── 1а2. Карточки-плитки одной высоты ──────────────────────────

   На главной карточки категорий («Кухни», «Шкафы-купе», …) стояли
   разной высоты: 180, 197, 208, а на телефоне до 247px. Ряд выглядел
   рваным.

   Причина — не в самих карточках, а в слиянии стилей: правило
   [data-caro-track]{align-items:start} пришло со страниц работ, где
   оно нужно фото-сеткам, и задело плитки на главной. Карточки
   переставали растягиваться до высоты ряда.

   align-items:stretch возвращает выравнивание, grid-auto-rows:1fr
   делает одинаковыми и сами ряды — иначе первый ряд был бы 197px,
   а второй 208px.                                                    */

[data-caro-track] {
  align-items: stretch;
}

[data-caro='4'] [data-caro-track],
[data-caro='works'] [data-caro-track] {
  grid-auto-rows: 1fr;
}

/* На мобильном эти дорожки становятся горизонтальным слайдером
   (display:flex). Карточки там тоже разной высоты — у одной работы
   описание в две строки, у другой в три. Растягиваем до самой
   высокой, чтобы в ряду не было ступеньки. */
@media (max-width: 860px) {
  [data-caro='4'] [data-caro-track],
  [data-caro='works'] [data-caro-track] {
    align-items: stretch !important;
  }

  [data-caro='4'] [data-caro-item],
  [data-caro='works'] [data-caro-item] {
    height: auto !important;
    align-self: stretch !important;
  }
}

/* Описание прижимаем к низу: заголовки бывают в одну и в две строки,
   и без этого описания начинались на разной высоте. */
[data-caro='4'] [data-caro-item] > *:last-child {
  margin-top: auto;
}


/* ─── 1б. Ряды из широких кадров ─────────────────────────────────

   Пропорции фото в вёрстке подобраны под сами снимки и не трогаются:
   у Столичного 16/9 стоит на честных 1920×1080, у Делфта 4/3 — на
   858×644. Но широкий кадр, зажатый в три колонки, превращается в
   нечитаемую полоску. Сборка помечает такие ряды data-wide-row —
   разжимаем их до двух колонок, а на телефоне до одной.              */

body:not([data-page="home"]) [data-wide-row] {
  grid-template-columns: repeat(2, 1fr) !important;
}

@media (max-width: 860px) {
  body:not([data-page="home"]) [data-wide-row] {
    grid-template-columns: 1fr !important;
  }
}


/* ─── 1в. Место под будущее видео ────────────────────────────────

   В герое страниц работ есть колонка под вертикальное видео. Там, где
   файла нет (04.08.2026 заказчик попросил временно снять ролики с Хита,
   Души и Шотландии), от неё остаётся пустой блок тех же пропорций:
   композиция геро-блока не съезжает, а служебных надписей конструктора
   («Загрузить видео 9:16») на публичном сайте быть не должно. Когда
   файл вернётся — путь в content/videos.json, и блок снова станет video.

   Блок именно невидим, а не оформлен: рамка со светлой заливкой поверх
   тёмного фото героя читалась не как «здесь будет видео», а как засвет
   на снимке.                                                          */

[data-video-slot] {
  visibility: hidden;
}

@media (max-width: 860px) {
  /* На узком экране герой и так в одну колонку — блок только мешает. */
  [data-video-slot] {
    display: none !important;
  }
}


/* ─── 1г. Навигация по зонам ─────────────────────────────────────

   Блок дорисовывается сборкой на страницах, где секции с якорями
   есть, а чипов не было (Шевченко, Антона Петрова).                 */

[data-zones] {
  scroll-margin-top: 80px;
}

@media (max-width: 860px) {
  [data-zones] {
    padding-left: 20px !important;
    padding-right: 20px !important;
  }
}


/* ─── 2. Слайдер главной: стрелки живы ─────────────────────────── */

body[data-page="home"] [data-caro="works"] [data-caro-ctrl] {
  display: flex !important;
}


/* ─── 3. Фон первого экрана под размер экрана ────────────────────

   media.sh готовит два кропа: горизонтальный 1920 для десктопа и
   вертикальный 900 для телефона. Исходник — квадрат 2000×2000 на
   6 МБ, из которого в обоих случаях видна лишь часть.
   Селектор по инлайновому стилю: перебить его иначе нельзя.        */

@media (max-width: 860px) {
  [style*="hero-1920"] {
    background-image: url('../hero-900.webp?v=a2fd0c86') !important;
  }
}


/* ─── 3б. Первый экран: фото во всю высоту ───────────────────────

   Фон задан фиксированным слоем на весь экран, но поверх лежит
   градиент, который к низу уходит почти в чёрный. На телефоне это
   читалось как тёмная полоса под фотографией — будто картинка
   кончилась. Осветляем нижнюю точку: затемнение нужно только
   настолько, чтобы белый текст оставался читаемым.                  */

@media (max-width: 860px) {
  [style*='linear-gradient'][style*='rgba(18, 18, 18'] {
    background: linear-gradient(
      180deg,
      rgba(18, 18, 18, 0.42) 0%,
      rgba(18, 18, 18, 0.3) 45%,
      rgba(18, 18, 18, 0.42) 100%
    ) !important;
  }
}


/* ─── 4. Тяжёлый скролл ──────────────────────────────────────────

   background-attachment:fixed заставляет браузер перерисовывать
   фоновую картинку на 6 МБ каждый кадр. На iOS это главный источник
   рывков при скролле. Визуально разница минимальна.                */

[style*="background-attachment:fixed"],
[style*="background-attachment: fixed"] {
  background-attachment: scroll !important;
}

@media (max-width: 860px) {
  /* backdrop-filter: blur() композитится дорого. В прототипе их 19.
     На мобильном оставляем только в шапке, остальным ставим
     непрозрачный фон — на глаз почти неотличимо. */
  [style*="backdrop-filter"]:not(header) {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
  }
  [data-caro-item][style*="backdrop-filter"] {
    background: rgba(26, 26, 26, 0.88) !important;
  }
}

@media (prefers-reduced-motion: reduce) {
  /* Бесконечная бегущая строка на 32 секунды. */
  * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}


/* ─── 4. Тач-таргеты ─────────────────────────────────────────────

   Рекомендация Apple и Google — минимум 44×44 CSS-пикселя.
   В прототипе ссылки футера были ~20px, чекбокс согласия 17×17.     */

@media (max-width: 860px) {
  footer a {
    display: inline-flex;
    align-items: center;
    padding: 11px 0;
    min-height: 44px;
  }

  /* Телефон в шапке — главная кнопка на мобильном, а был 22px высотой. */
  header a[href^='tel:'] {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  /* Карточка работы: тап должен ловиться по всей ссылке, а не по строке. */
  [data-caro-item] a,
  a[href*='/works/'] {
    min-height: 44px;
  }

  /* Ссылки-строки вне футера: «Смотреть все работы →» и подобные. */
  section a:not([data-caro-item]):not(.hv-none) {
    min-height: 44px;
  }

  /* Бургер был 22px шириной — палец в него не попадает. */
  .ksh-burger {
    width: 44px;
    min-width: 44px;
    height: 44px;
  }

  /* Логотип — ссылка на главную, высота была 38px по картинке. */
  header a:has(img[src*='logo-']) {
    min-height: 44px;
    align-items: center;
  }

  /* Кнопка «Рассчитать стоимость» в шапке.

     На 390px шапка не помещалась: логотип 72 + блок с телефоном и
     кнопкой 358 + бургер 44 = 474px при экране 390. Страница получала
     горизонтальный скролл на 127px — на телефоне это сразу заметно
     и выглядит как сломанная вёрстка.

     Кнопку убираем: ровно то же действие уже есть в нижнем баре,
     который висит на всех страницах. Телефон и бургер остаются. */
  header button:not(.ksh-burger),
  header a[href*='#calc'] {
    display: none !important;
  }

  /* Страховка от любого другого источника горизонтального скролла. */
  html,
  body {
    overflow-x: hidden;
  }

  input[type='checkbox'] {
    width: 22px !important;
    height: 22px !important;
    flex: none;
  }

  /* Подпись к чекбоксу тоже кликабельна — расширяем зону нажатия. */
  label:has(input[type='checkbox']) {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    min-height: 44px;
    padding: 6px 0;
  }

  button,
  [role='button'] {
    min-height: 44px;
  }
}


/* ─── 4б. Квиз на мобильном: компактнее и в два столбца ──────────

   Карточки выбора типа мебели шли в одну колонку: шесть штук по
   88px — почти два экрана прокрутки только чтобы выбрать «Кухня».
   Ставим в два столбца и ужимаем внутренние отступы формы.          */

@media (max-width: 860px) {
  [data-quiz] {
    padding: 24px 18px !important;
  }

  /* Сетки внутри квиза: типы мебели, конфигурации, техника. */
  [data-quiz] [data-cols^='repeat(3'],
  [data-quiz] [data-cols^='repeat(5'] {
    grid-template-columns: repeat(2, 1fr) !important;
    gap: 10px !important;
  }

  /* Сама карточка ниже: иконка и подпись помещаются и так. */
  [data-quiz] button[data-act='type'] {
    padding: 16px 10px !important;
    gap: 7px !important;
  }

  [data-quiz] button[data-act='config'] {
    min-height: 92px !important;
    padding: 12px 6px !important;
  }

  /* Индикатор шагов занимал треть первого экрана формы. */
  [data-quiz] > div:first-child {
    margin-bottom: 22px !important;
  }
}

@media (max-width: 400px) {
  /* Размеры — три поля в ряд на 390px нечитаемы. */
  [data-quiz] [data-cols^='repeat(3'] {
    gap: 8px !important;
  }
}


/* ─── 5. Инпуты: iOS зумит страницу при фокусе, если шрифт < 16px ── */

input,
textarea,
select {
  font-size: max(16px, 1rem);
}


/* ─── 6. Картинки не должны разрывать вёрстку ──────────────────── */

img,
video {
  max-width: 100%;
}


/* ─── 7. Нижний бар с кнопками на мобильном ──────────────────────

   Разметку добавляет app.js — здесь только оформление.
   Появляется после первого экрана, чтобы не закрывать герой.       */

.ksh-cta-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 90;
  display: none;
  gap: 1px;
  background: rgba(255, 255, 255, 0.12);
  padding-bottom: env(safe-area-inset-bottom);
  transform: translateY(100%);
  transition: transform 0.25s ease;
}

.ksh-cta-bar[data-shown] {
  transform: none;
}

.ksh-cta-bar a {
  flex: 1;
  min-height: 52px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  background: #1f1f1f;
  color: #fff;
  font-size: 14px;
  font-weight: 500;
  text-decoration: none;
  letter-spacing: 0.02em;
}

.ksh-cta-bar a.is-primary {
  background: #9e1f1c;
}

@media (max-width: 860px) {
  .ksh-cta-bar {
    display: flex;
  }

  /* Чтобы бар не накрывал последние строки футера. */
  body {
    padding-bottom: 52px;
  }
}


/* ─── 7б. Шапка на мобильном: логотип по центру ───────────────────

   Телефон из шапки переехал в меню — на 390px он занимал треть
   ширины и толкал бургер за край. Осталось двое: логотип и бургер,
   поэтому логотип ставим по центру, а бургер прижимаем вправо.     */

@media (max-width: 860px) {
  header {
    position: relative;
    justify-content: center !important;
    gap: 0 !important;
  }

  header a:has(img[src*='logo-']) {
    justify-self: center;
  }

  /* Телефон и всё лишнее из шапки — в меню. */
  header a[href^='tel:'],
  header nav {
    display: none !important;
  }

  .ksh-burger {
    position: absolute;
    right: 20px;
    top: 50%;
    transform: translateY(-50%);
  }
}


/* ─── 7в. Панель меню ────────────────────────────────────────────

   Отдельный слой вне шапки: подмешивание класса к тому же <nav>
   спорило с инлайновыми стилями прототипа, и пункты налезали на
   первый экран.                                                    */

.ksh-menu[hidden] {
  display: none;
}

.ksh-menu {
  position: fixed;
  inset: 0;
  z-index: 120;
  display: flex;
  flex-direction: column;
  padding: 14px 24px 32px;
  /* Непрозрачный: при полупрозрачном сквозь пункты просвечивал
     заголовок первого экрана и мешал читать. */
  background: #101010;
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* Своя верхняя строка: логотип и крестик. */
.ksh-menu-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 26px;
}

.ksh-menu-top img {
  height: 38px;
  width: auto;
  display: block;
}

.ksh-menu-close {
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.28);
  border-radius: 3px;
  color: #fff;
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
  padding: 0;
}

.ksh-menu nav {
  display: flex;
  flex-direction: column;
}

.ksh-menu nav a {
  display: flex;
  align-items: center;
  min-height: 56px;
  padding: 4px 0;
  color: #fff;
  font-size: 20px;
  letter-spacing: 0.02em;
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.09);
}

/* Контакты прижаты к низу экрана, пункты — сразу под логотипом. */
.ksh-menu-foot {
  margin-top: auto;
  padding-top: 28px;
}

.ksh-menu-phone {
  display: block;
  color: #fff;
  font-size: 26px;
  font-weight: 700;
  text-decoration: none;
  letter-spacing: 0.01em;
}

.ksh-menu-note {
  margin: 6px 0 20px;
  color: rgba(255, 255, 255, 0.5);
  font-size: 14px;
}

.ksh-menu-cta,
.ksh-menu-wa {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 52px;
  border-radius: 2px;
  font-size: 15px;
  font-weight: 700;
  text-decoration: none;
}

.ksh-menu-cta {
  background: #9e1f1c;
  color: #fff;
  margin-bottom: 10px;
}

.ksh-menu-wa {
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.2);
  color: #fff;
}

html.ksh-menu-open,
html.ksh-menu-open body {
  overflow: hidden;
}

/* Панель самодостаточна: у неё своя верхняя строка с логотипом и
   крестиком, поэтому поднимать липкую шапку над ней не требуется. */


/* ─── 8. Бургер-меню ─────────────────────────────────────────────

   В прототипе на мобильном навигации не было вообще:
   header nav {display:none!important}, а на главной <nav> ещё и
   пустой. Разметку наполняет app.js.                               */

.ksh-burger {
  display: none;
  width: 44px;
  height: 44px;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.28);
  border-radius: 3px;
  cursor: pointer;
  padding: 0;
}

.ksh-burger span {
  display: block;
  width: 20px;
  height: 1.5px;
  background: #fff;
  position: relative;
  transition: background 0.2s;
}

.ksh-burger span::before,
.ksh-burger span::after {
  content: '';
  position: absolute;
  left: 0;
  width: 20px;
  height: 1.5px;
  background: #fff;
  transition: transform 0.25s ease;
}

.ksh-burger span::before { top: -6px; }
.ksh-burger span::after  { top: 6px; }

.ksh-burger[aria-expanded='true'] span { background: transparent; }
.ksh-burger[aria-expanded='true'] span::before { transform: translateY(6px) rotate(45deg); }
.ksh-burger[aria-expanded='true'] span::after  { transform: translateY(-6px) rotate(-45deg); }

@media (max-width: 860px) {
  .ksh-burger {
    display: flex;
  }
}


/* ─── 9. Лайтбокс ────────────────────────────────────────────────

   Открывается тапом по фото в галерее. Логика в app.js.            */

.ksh-lb {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: none;
  align-items: center;
  justify-content: center;
  background: rgba(10, 10, 10, 0.96);
  touch-action: pinch-zoom;
}

.ksh-lb[data-open] {
  display: flex;
}

.ksh-lb img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  display: block;
}

.ksh-lb button {
  position: absolute;
  min-width: 44px;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.25);
  color: #fff;
  font-size: 20px;
  cursor: pointer;
  border-radius: 50%;
}

.ksh-lb .lb-close { top: 16px; right: 16px; }
.ksh-lb .lb-prev  { left: 16px;  top: 50%; transform: translateY(-50%); }
.ksh-lb .lb-next  { right: 16px; top: 50%; transform: translateY(-50%); }

.ksh-lb .lb-count {
  position: absolute;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  color: rgba(255, 255, 255, 0.7);
  font-size: 14px;
}

/* Пока лайтбокс открыт, страница под ним не скроллится. */
html.ksh-lb-open,
html.ksh-lb-open body {
  overflow: hidden;
}

/* ─────────────────────────── Плеер ───────────────────────────
 *
 * Постер и кнопка вместо автозапуска. Ролики идут по 36-77 секунд и весят
 * 6.6-14.4 МБ против 350-400 КБ у самой страницы — автозапуск такого
 * означал бы эти мегабайты на каждом визите.
 *
 * Обёртка забирает оформление исходного <video> — пропорции, скругление,
 * тень, — потому что кнопку надо позиционировать относительно неё. */
.vplay {
  position: relative;
  overflow: hidden;
  background: #111;
}

.vplay > video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Кнопка центрируется через inset+margin:auto, а не через transform:
 * transform здесь уже занят наведением, и они бы дрались. */
.vplay-btn {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 74px;
  height: 74px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(158, 31, 28, 0.92);
  color: #fff;
  cursor: pointer;
  display: grid;
  place-items: center;
  box-shadow: 0 12px 34px rgba(0, 0, 0, 0.45);
  transition: transform 0.18s ease, background 0.18s ease;
}

.vplay-btn svg {
  width: 30px;
  height: 30px;
  margin-left: 4px; /* оптический центр треугольника левее геометрического */
}

.vplay-btn:hover,
.vplay-btn:focus-visible {
  background: #9e1f1c;
  transform: scale(1.07);
}

.vplay.is-playing .vplay-btn {
  display: none;
}

@media (max-width: 600px) {
  .vplay-btn { width: 62px; height: 62px; }
  .vplay-btn svg { width: 25px; height: 25px; }
}

/* Плашка «ВИДЕО». Оформление один в один с той, что была вписана руками
 * в исходниках Мичурина и Жемчуга, — чтобы на этих двух страницах вид
 * не изменился, а на остальных четырёх появился такой же. */
.vplay-badge {
  position: absolute;
  top: 12px;
  left: 12px;
  display: flex;
  align-items: center;
  gap: 7px;
  background: rgba(20, 20, 20, 0.66);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  padding: 6px 12px;
  border-radius: 2px;
  pointer-events: none;
  text-transform: uppercase;
}

.vplay-badge span {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #9e1f1c;
  display: block;
}

/* Индикатор загрузки видео. Показывается, пока браузер набирает буфер:
 * без него кадр просто замирает и это читается как зависший сайт. */
.vplay.is-loading .vplay-btn svg { display: none; }

.vplay.is-loading .vplay-btn::after {
  content: '';
  width: 26px;
  height: 26px;
  border: 2px solid rgba(255, 255, 255, 0.35);
  border-top-color: #fff;
  border-radius: 50%;
  animation: vplay-spin 0.7s linear infinite;
}

/* Пока грузится, кнопку не прячем и повторные нажатия игнорируем — иначе
 * блок выглядит мёртвым ровно в тот момент, когда что-то происходит. */
.vplay.is-loading.is-playing .vplay-btn { display: grid; }

@keyframes vplay-spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .vplay.is-loading .vplay-btn::after { animation-duration: 2s; }
}

/* ─── Промежуток между первым экраном и бегущей строкой ──────────

   На 390px между кнопками и бегущей строкой зияло 209px. Складывалось
   из трёх независимых источников, и правка любого одного давала мало:
   нижний отступ героя 90px, отбивка под рядом кнопок 54px и общий
   section{padding-top:48px}, который применяется ко всем секциям сразу.

   Верх героя не трогаем — там отступ работает, кнопки не должны липнуть
   к шапке. Режем только низ.                                          */

@media (max-width: 860px) {
  section[data-hero] {
    padding-bottom: 24px !important;
  }

  /* Ряд кнопок первого экрана: 54px под ним — это отбивка от блока цифр,
     которого здесь давно нет, он убран сборкой как дубль бегущей строки. */
  section[data-hero] [data-cta-row] {
    margin-bottom: 20px !important;
  }

  section[data-marquee] {
    padding-top: 24px !important;
  }
}

@media (max-width: 860px) {
  /* Остаток промежутка — не отступы, а «воздух»: секция растянута на
     всю высоту экрана (min-height:100vh-67px), содержимое центрировано,
     и лишние ~200px делятся поровну сверху и снизу. Ста пикселей снизу
     хватало, чтобы бегущая строка уезжала за сгиб и между ней и
     кнопками зияла пустота.

     Отпускаем высоту: фотография первого экрана всё равно нарисована
     отдельным фиксированным слоем во весь экран, поэтому «полноэкранность»
     от этого не теряется — меняется только то, где начинается следующий
     блок. Заодно край бегущей строки становится виден у сгиба и подсказывает,
     что страница продолжается. */
  section[data-hero] {
    min-height: 0 !important;
    padding-top: 56px !important;
    padding-bottom: 28px !important;
  }
}

/* ─── Появление первого экрана ───────────────────────────────────

   В прототипе контейнер героя анимируется через floatUp с режимом both,
   а это значит, что до старта анимации у него opacity:0 — весь первый
   экран пуст. Само по себе задумка, но на записи загрузки видно, чем это
   оборачивается: сначала тёмный экран без заголовка и кнопок, и только
   потом контент. Заказчик описал это как «сначала показывает что-то не то».

   Анимацию не убираем — она часть дизайна. Меняем стартовую точку:
   текст виден с первого же кадра и только доезжает снизу. Переопределение
   работает, потому что overrides.css склеивается в конец style.css,
   а из двух @keyframes с одним именем побеждает последний.               */

@keyframes floatUp {
  from { opacity: .45; transform: translateY(12px); }
  to   { opacity: 1;   transform: translateY(0); }
}

/* ─── Заглушка и кольцо загрузки под каждым фото ─────────────────

   Обёртку .ph ставит сборка вокруг каждой картинки: в ней лежит размытая
   заглушка (LQIP, вшита data-URI). Раньше заглушка вешалась на родителя
   картинки, а в галерее родитель — сам грид, поэтому одна размытая копия
   растягивалась фоном под всю сетку, а остальные отсекались проверкой
   «фон уже есть».

   Класс is-loading ставит JS и только тем фото, которые на момент запуска
   ещё не загрузились. В разметке его нет намеренно: если скрипт не
   отработает, кольцо не появится и не зависнет навсегда поверх готового
   снимка. Саму картинку ничем не скрываем — браузер и так не рисует
   её, пока не получил, а любое скрытие через CSS ломается ровно в тот
   момент, когда JS недоступен.                                          */

.ph > img {
  width: 100%;
  height: 100%;
  display: block;
}

.ph.is-loading::after {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 34px;
  height: 34px;
  border: 2px solid rgba(255, 255, 255, 0.28);
  border-top-color: rgba(255, 255, 255, 0.9);
  border-radius: 50%;
  /* Та же анимация, что у кнопки видео, — чтобы на сайте не было двух
     разных вращений с разной скоростью. */
  animation: vplay-spin 0.7s linear infinite;
  pointer-events: none;
}

/* На маленьких превью кольцо в 34px занимает половину карточки. */
@media (max-width: 600px) {
  .ph.is-loading::after { width: 28px; height: 28px; }
}

/* ─── Формы: подсказки в полях и зазор между кнопками ────────────

   Цвет подсказки в прототипе задан один на весь сайт — rgba(38,38,38,.4),
   почти чёрный. Для светлой формы квиза это верно, а на страницах работ
   форма стоит на тёмном: подсказки «Ваше имя» и «Номер телефона» на ней
   почти неразличимы, и поля читаются как пустые серые прямоугольники.
   Заказчик так и написал — «в полях пусто».

   Класс fld-dark сборка ставит полям, у которых белый текст, то есть
   тёмная подложка. Селектор по инлайновому фону не годится: браузер
   нормализует такие стили, и в этом проекте подобные селекторы уже
   один раз молча перестали совпадать.                                 */

.fld-dark::placeholder {
  color: rgba(255, 255, 255, 0.55);
}

.fld-dark::-webkit-input-placeholder {
  color: rgba(255, 255, 255, 0.55);
}

/* Кнопка отправки и «Спросить в WhatsApp» стояли вплотную: у ссылки
   margin-top:auto, который прижимает её к низу колонки, но при нехватке
   места даёт ровно нулевой зазор — кнопки слипались в одну плашку.
   Свой отступ у кнопки гарантирует зазор, не ломая выравнивание по низу. */
[data-lead-submit] {
  margin-bottom: 10px;
}

/* Ряд кнопок мессенджеров. Было две — WhatsApp и Telegram, — сборка
   достраивает третью, MAX (clean.mjs, шаг 6е). Втроём на 390px они
   ужимаются до ~100px, и «WhatsApp» перестаёт влезать в кнопку.
   Разрешаем перенос и задаём минимум по самой длинной подписи:
   на широком экране ряд остаётся в одну строку, на телефоне MAX
   уходит вниз во всю ширину.                                          */
[data-msg-row] {
  flex-wrap: wrap;
}

[data-msg-row] > a {
  min-width: 116px;
}

/* Номер телефона одним куском.

   В карточке контактов он набран 28px, в бургер-меню 26px — на 390px
   шестнадцать знаков в такой кегль не влезают, и номер рвётся пополам:
   «+7 996 700-91-» и «00» отдельной строкой. Читается как две разные
   строки, а не как телефон. Уменьшаем кегль и запрещаем перенос —
   в дизайне номер и был единой строкой.                               */
@media (max-width: 600px) {
  #contacts a[href^='tel:'],
  .ksh-menu-phone {
    font-size: 23px;
    white-space: nowrap;
  }
}

/* ─── Шрифтовая система: текст — Stolzl, заголовки — ANGST ────────

   ANGST — капсовый шрифт: строчных глифов в нём физически нет, и любой
   абзац им выглядит сплошным капсом, раздуваясь на телефоне на треть.
   По решению заказчика (26.07.2026) рабочий текст переведён на Stolzl
   в обычном регистре, заголовки остаются капсом ANGST.

   Механика: body переводит всё, что не несёт свой font-family; сборка
   (clean.mjs, шаг 6д) снимает инлайновый ANGST с кнопок, полей и лидов,
   оставляя его заголовкам, и помечает абзацы атрибутом data-prose.

   font-display:block безопасен только вместе с preload — оба шрифта
   предзагружаются в buildHead (см. docs/BUILD.md про FOIT).            */

@font-face {
  font-family: 'Stolzl';
  src: url('../fonts/Stolzl-Light.woff2?v=bc3451c2') format('woff2');
  font-weight: 300;
  font-style: normal;
  font-display: block;
}

@font-face {
  font-family: 'Stolzl';
  src: url('../fonts/Stolzl-Regular.woff2?v=7d655aea') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: block;
}

@font-face {
  font-family: 'Stolzl';
  src: url('../fonts/Stolzl-Medium.woff2?v=e9e2c4d7') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: block;
}

@font-face {
  font-family: 'Stolzl';
  src: url('../fonts/Stolzl-Bold.woff2?v=dd89f2d4') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: block;
}

body {
  font-family: 'Stolzl', 'Roboto', sans-serif;
}

/* Межстрочный 1.8–2.0 был подобран под капс ANGST — у строчного Stolzl
   он превращает абзац в редкую лесенку. Инлайновые line-height перебить
   можно только с !important.

   Вес 300: Stolzl Regular рядом с тонким капсом ANGST Thin выглядит
   тяжелее самого заголовка — иерархия переворачивается (замечание
   заказчика по карточке «Что было сделано»). Light возвращает заголовку
   главенство; жирные вставки <strong> внутри абзацев остаются жирными. */
[data-prose] {
  font-weight: 300;
  line-height: 1.6 !important;
}

/* На телефоне текст ещё и ужимаем — ради этого всё и затевалось. */
@media (max-width: 860px) {
  [data-prose] {
    font-size: 16px !important;
    line-height: 1.55 !important;
  }

  /* «−10%» в блоке скидки: 120px жирного Stolzl — неразрывный кусок,
     min-content грида раздувал блок за край экрана. 72px влезает
     с запасом и на 320px-экране.                                    */
  [data-promo-num] {
    font-size: 72px !important;
  }
}

/* Заголовки карточек каталога: «Осовременивание» в 26px жирного
   Stolzl шире карточки слайдера — без переноса текст обрезался
   правым краем. Дефисный перенос, а разрыв без дефиса — страховка. */
[data-card-title] {
  overflow-wrap: break-word;
  hyphens: auto;
}

/* Кнопка отправки квиза: «Получить расчёт бесплатно» жирным Stolzl
   на 390px ломалась на три строки и обрезалась низом карточки.
   На своей строке во всю ширину надпись помещается в одну строку
   (контейнер кнопок в quiz.js для этого получил flex-wrap).        */
@media (max-width: 600px) {
  [data-quiz] [data-act='submit'] {
    flex: 1 1 100%;
  }
}

/* Низ карточки каталога — одна ссылка-флекс: слева span-метка
   «Объект целиком · N зон», справа span «Смотреть →». Со Stolzl
   стрелка отрывалась от «Смотреть» на вторую строку. Запрещаем
   разрыв только правому span — метка переносится как раньше,
   margin-left держит зазор, когда метка в одну строку впритык.     */
[data-caro-item] a > span:last-child {
  white-space: nowrap;
  margin-left: 14px;
}

/* Футер на телефоне. Прототип складывал четыре колонки в две, но со
   строчным Stolzl в колонке ~150px телефон рвался на две строки, а
   текст про компанию шёл по одному-два слова. Одна колонка, и всё
   по центру (просьба заказчика 27.07): часть ссылок центрирована
   инлайновым justify-content ещё в прототипе — ровняем под них
   остальное, а не наоборот.                                        */
@media (max-width: 600px) {
  footer {
    text-align: center;
  }

  footer [data-cols^='1.4fr1fr1fr1fr'] {
    grid-template-columns: 1fr !important;
  }

  footer a {
    justify-content: center;
  }

  footer img {
    display: block;
    margin-left: auto;
    margin-right: auto;
  }
}

/* ─── Меню в шапке ────────────────────────────────────────────────

   Сборка заполняет пустой <nav> якорями на секции главной. На узких
   экранах четыре пункта не помещаются рядом с логотипом и телефоном —
   шапка складывалась бы в три этажа. Прячем: на телефоне до тех же
   секций ведут чипы под первым экраном и футер.                     */

@media (max-width: 860px) {
  [data-mainnav] {
    display: none !important;
  }
}
