/* ============================================================
   J-Park — общая дизайн-система сайта
   ------------------------------------------------------------
   Источник токенов: prototype/index.html (hero + «Конструктив»).
   Этот файл — единственная точка правды по палитре, типографике
   и базовым компонентам для ВСЕХ страниц нового сайта.
   Hero и «Конструктив» пока живут инлайном в index.html; когда
   их вынесут — они должны опираться на эти же переменные.
   ============================================================ */

:root{
  /* палитра */
  --cream:#F2EDE4;
  --cream-deep:#E6DECF;
  --ink:#16212B;
  --ink-soft:#4A5560;
  --blue:#377A3E;
  --blue-lift:#449A47;
  /* Заливки кнопок и линий держат --blue (#377A3E) — на них цвет пятном,
     контраст ок. У мелкого текста (≤12px: spec-tag, метки, подписи)
     та же заливка на кремовом фоне уже не проходит контраст по AA —
     для таких меток отдельный, более тёмный оттенок того же зелёного. */
  --blue-text:#2F6A36;
  --amber:#E9B63F;
  --wood:#B4703A;
  --light:#F7F3EB;
  --forest:#1B2118;

  /* производные поверхности: считаются от палитры, а не задаются вручную,
     чтобы смена базового тона тянула за собой всё остальное */
  --line:rgba(22,33,43,.12);
  --line-soft:rgba(22,33,43,.07);
  --glass:rgba(247,243,235,.62);
  --glass-line:rgba(247,243,235,.5);

  /* шрифты */
  --f-display:"Unbounded","Golos Text",system-ui,sans-serif;
  --f-body:"Golos Text","Segoe UI",system-ui,sans-serif;
  --f-mono:"JetBrains Mono",ui-monospace,"Cascadia Mono",monospace;

  /* ритм. --pad-x — боковые поля страницы, ими же выровнены шапка и футер;
     --gap — базовый шаг сеток; --sec-y — вертикаль секции. */
  --pad-x:clamp(20px,3.2vw,56px);
  --maxw:1180px;
  --gap:clamp(16px,1.8vw,26px);
  --sec-y:clamp(64px,9vh,124px);

  --shadow-card:0 18px 44px -30px rgba(22,33,43,.55);
  --shadow-card-hi:0 26px 60px -28px rgba(22,33,43,.5);
  --ease:cubic-bezier(.2,.7,.2,1);
  /* тень текста поверх фото и видео в hero */
  --shadow-text:0 1px 2px rgba(10,16,12,.5), 0 8px 40px rgba(10,16,12,.45);
}

/* ---------- база ---------- */
*{box-sizing:border-box}
body{
  margin:0;
  background:var(--cream);
  color:var(--ink);
  font-family:var(--f-body);
  font-size:17px;
  line-height:1.55;
  -webkit-font-smoothing:antialiased;
  /* clip, а не hidden. Разница невидима глазом, но принципиальна: hidden
     делает body ПРОКРУЧИВАЕМЫМ КОНТЕЙНЕРОМ, а clip просто обрезает и
     контейнера не создаёт. Из-за hidden привязанная к прокрутке анимация
     секции миссии не находила, за чем следить, и стояла мёртвой: браузер
     резолвил ближайший скроллер в body, который сам не прокручивается.
     Тот же побочный эффект hidden ломает position:sticky у потомков. */
  overflow-x:clip;
}
img{max-width:100%;display:block}
a{color:inherit}
::selection{background:var(--amber);color:var(--ink)}
:focus-visible{outline:2px solid var(--amber);outline-offset:3px;border-radius:2px}

/* ---------- раскладка ---------- */
.section{
  position:relative;
  padding:var(--sec-y) var(--pad-x);
  border-top:1px solid var(--line-soft);
}
.section--flat{border-top:0}
.section--deep{background:var(--cream-deep)}
.section--ink{background:var(--forest);color:var(--light)}
.section--ink .eyebrow{color:var(--amber)}
.wrap{max-width:var(--maxw);margin:0 auto;width:100%}
.wrap--wide{max-width:1320px}

/* Шапка секции: моно-надзаголовок + дисплейный H2 + лид одним столбцом.
   Модификатор --split разводит заголовок и правую колонку (лид/ссылку). */
.sec-head{margin:0 0 clamp(30px,4.4vh,56px)}
.sec-head--split{
  display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr);
  gap:var(--gap) clamp(28px,5vw,72px);align-items:end;
}
.sec-head p.lead{margin:0;color:var(--ink-soft);font-size:clamp(15.5px,1.15vw,18px);line-height:1.65;max-width:56ch}
.section--ink .sec-head p.lead{color:rgba(247,243,235,.78)}

/* ---------- типографика ---------- */
.eyebrow{
  font-family:var(--f-mono);font-size:11px;font-weight:500;
  letter-spacing:.24em;text-transform:uppercase;
  color:var(--blue-text);margin:0 0 18px;
  display:flex;align-items:center;gap:12px;
}
.eyebrow::before{content:"";width:26px;height:1px;background:currentColor;flex:none}
.eyebrow--plain::before{display:none}
.eyebrow--center{justify-content:center}

h1,h2,h3{font-family:var(--f-display);font-weight:600;letter-spacing:-.025em;line-height:1.05;margin:0}
.h1{font-size:clamp(2.1rem,4.6vw,4rem);line-height:1.0}
.h2{font-size:clamp(1.7rem,3.2vw,2.8rem);margin:0 0 18px;max-width:20ch}
.h3{font-size:clamp(1.15rem,1.7vw,1.5rem);letter-spacing:-.02em}
.h4{font-family:var(--f-display);font-weight:600;font-size:17px;letter-spacing:-.01em;line-height:1.2;margin:0}
.muted{color:var(--ink-soft)}
.nowrap{white-space:nowrap}
.center{text-align:center}
.sec-head--center .eyebrow{justify-content:center}
.sec-head--center .h2{margin-left:auto;margin-right:auto}

/* Моноширинная строка-спецификация — сквозной приём проекта: всё, что
   является параметром, а не прозой, набирается моно с трекингом. */
.spec-row{
  display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 18px;
  font-family:var(--f-mono);font-size:12px;letter-spacing:.06em;
  color:var(--ink-soft);
}
.spec-row em{font-style:normal;color:var(--blue-text)}
.spec-row span{white-space:nowrap}
.spec-rule{margin-top:18px;padding-top:14px;border-top:1px solid var(--line)}

/* Определения «подпись сверху — значение снизу», как .facts в конструктиве. */
.deflist{display:grid;gap:1px;background:var(--cream-deep);border:1px solid var(--cream-deep);margin:0}
.deflist > div{background:var(--cream);padding:22px 22px 24px}
.section--deep .deflist > div{background:var(--cream-deep);}
.deflist dt{
  font-family:var(--f-mono);font-size:10px;letter-spacing:.2em;text-transform:uppercase;
  color:var(--ink-soft);margin:0 0 10px;
}
.deflist dd{
  margin:0;font-family:var(--f-display);font-weight:500;
  font-size:clamp(1.25rem,2vw,1.7rem);letter-spacing:-.02em;color:var(--blue);
}

/* ---------- кнопки ---------- */
.btn{
  display:inline-flex;align-items:center;gap:10px;
  background:var(--blue);color:var(--light);text-decoration:none;
  font-family:var(--f-body);font-weight:600;font-size:15.5px;line-height:1.2;
  padding:15px 26px;border:0;border-radius:2px;cursor:pointer;text-shadow:none;
  transition:background .3s ease,transform .3s var(--ease);
}
.btn:hover{background:var(--blue-lift);transform:translateY(-2px)}
.btn i{font-style:normal;transition:transform .3s ease}
.btn:hover i{transform:translateX(4px)}
.btn--amber{background:var(--amber);color:var(--ink)}
.btn--amber:hover{background:#F1C55C}
.btn--sm{padding:11px 18px;font-size:14px}
.btn--wide{width:100%;justify-content:center}

.btn-line{
  display:inline-flex;align-items:center;gap:9px;
  border:1px solid var(--line);background:transparent;color:var(--ink);
  font-family:var(--f-body);font-weight:600;font-size:14.5px;line-height:1.2;
  padding:12px 20px;border-radius:2px;cursor:pointer;text-decoration:none;
  transition:border-color .3s ease,color .3s ease,background .3s ease;
}
.btn-line:hover{border-color:var(--blue);color:var(--blue);background:rgba(46,92,138,.05)}

.btn-ghost{
  display:inline-flex;align-items:center;gap:8px;
  text-decoration:none;font-size:15px;font-weight:500;
  color:var(--ink-soft);border-bottom:1px solid rgba(22,33,43,.25);
  padding-bottom:2px;background:none;border-left:0;border-right:0;border-top:0;cursor:pointer;
  transition:color .3s ease,border-color .3s ease;
}
.btn-ghost:hover{color:var(--blue);border-color:var(--blue)}
.section--ink .btn-ghost{color:rgba(247,243,235,.85);border-color:rgba(247,243,235,.3)}
.section--ink .btn-ghost:hover{color:var(--amber);border-color:var(--amber)}

.cta-row{display:flex;flex-wrap:wrap;align-items:center;gap:14px 24px;margin-top:clamp(28px,4vh,44px)}
.cta-row--center{justify-content:center}

/* ---------- сетки ---------- */
.grid{display:grid;gap:var(--gap)}
.grid-2{grid-template-columns:repeat(2,minmax(0,1fr))}
.grid-3{grid-template-columns:repeat(3,minmax(0,1fr))}
.grid-4{grid-template-columns:repeat(4,minmax(0,1fr))}
.grid-auto{grid-template-columns:repeat(auto-fit,minmax(230px,1fr))}

/* ---------- карточки ---------- */
.card{
  position:relative;display:flex;flex-direction:column;
  background:var(--light);border:1px solid var(--line-soft);
  border-radius:3px;overflow:hidden;
  box-shadow:var(--shadow-card);
  transition:transform .4s var(--ease),box-shadow .4s var(--ease),border-color .4s ease;
}
.card:hover{transform:translateY(-5px);box-shadow:var(--shadow-card-hi);border-color:var(--line)}
/* Карточка, которая приезжает через [data-reveal]: правило .is-in ниже
   снимает transform целиком и тем самым гасит hover-подъём (специфичность
   у обоих (0,2,0), а .is-in идёт позже по файлу). Поэтому hover для уже
   показанной карточки поднят по специфичности до (0,4,0) — это и есть
   единственная точка, где два механизма договариваются. Курсор проверяем:
   на тач-экранах :hover залипает после тапа. */
@media (hover:hover) and (pointer:fine){
  .card[data-reveal].is-in:hover{transform:translateY(-5px)}
}
.card__media{
  position:relative;display:block;overflow:hidden;background:var(--cream-deep);
  aspect-ratio:4 / 3;
}
.card__media img{width:100%;height:100%;object-fit:cover;transition:transform .7s var(--ease)}
.card:hover .card__media img{transform:scale(1.045)}
.card__media--wide{aspect-ratio:16 / 10}
.card__media--tall{aspect-ratio:3 / 4}
.card__body{display:flex;flex-direction:column;gap:12px;padding:20px 20px 22px;flex:1 1 auto}
.card__body > .card__foot{margin-top:auto}
.card__foot{display:flex;flex-wrap:wrap;gap:10px;padding-top:4px}
.card__tag{
  position:absolute;left:12px;top:12px;z-index:2;
  font-family:var(--f-mono);font-size:9.5px;letter-spacing:.18em;text-transform:uppercase;
  background:rgba(22,33,43,.78);color:var(--light);padding:6px 10px;border-radius:2px;
  backdrop-filter:blur(3px);
}
.card__date{
  font-family:var(--f-mono);font-size:10.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--ink-soft);
}
.card p{margin:0;font-size:14.5px;line-height:1.6;color:var(--ink-soft)}
/* Карточка-ссылка: подчёркивание сняли, иначе UA рисует его под заголовком
   и карточка перестаёт читаться как плитка. Класс ставится на сам <a>. */
.card__link,.card a{text-decoration:none}

/* Стеклянная поверхность — для блоков поверх фото/тёмного фона. */
.glass{
  background:var(--glass);border:1px solid var(--glass-line);
  backdrop-filter:blur(10px) saturate(1.1);border-radius:4px;
}

/* ---------- формы ---------- */
.form{display:grid;gap:14px}
.field{display:flex;flex-direction:column;gap:7px}
.field label{
  font-family:var(--f-mono);font-size:10px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--ink-soft);
}
.field input,.field textarea,.field select{
  font-family:var(--f-body);font-size:15.5px;color:var(--ink);
  background:var(--light);border:1px solid var(--line);border-radius:2px;
  padding:13px 14px;width:100%;
  transition:border-color .25s ease,box-shadow .25s ease;
}
.field input::placeholder{color:rgba(74,85,96,.5)}
.field input:focus,.field textarea:focus{
  outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(46,92,138,.12);
}
.field input:user-invalid{border-color:#B4553A}
.check{
  display:flex;align-items:flex-start;gap:10px;
  font-size:13px;line-height:1.5;color:var(--ink-soft);cursor:pointer;
}
.check input{margin:2px 0 0;width:16px;height:16px;accent-color:var(--blue);flex:none}
.check a{color:var(--blue)}

/* Антиспам-ловушка (honeypot). Поле остаётся полноценным элементом формы —
   бот его видит и заполняет, — но человека до него не доводит: уводим за
   левый край окна. Именно вынос за экран, а не display:none/visibility:
   hidden — часть спам-скриптов такие поля пропускает. Отрицательный left
   в LTR горизонтальную прокрутку не создаёт. Из таб-порядка поле убирает
   tabindex=-1, от скринридера — aria-hidden на обёртке (см. разметку форм). */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

/* Контейнер невидимой SmartCaptcha. Пока клиентский ключ не задан
   (data-state="off") или виджет не поднялся, места в вёрстке не занимает:
   в невидимом режиме показывать там нечего. */
.captcha{display:grid}
.captcha[data-state="off"],.captcha[data-state="loading"],.captcha[data-state="failed"]{display:none}

/* ---------- табы ---------- */
.tabs{
  display:flex;flex-wrap:wrap;gap:8px;
  border-bottom:1px solid var(--line);margin-bottom:clamp(26px,3.6vh,42px);
}
.tab{
  position:relative;background:none;border:0;cursor:pointer;
  font-family:var(--f-body);font-weight:600;font-size:15px;color:var(--ink-soft);
  padding:12px 4px 14px;margin-right:18px;
  transition:color .3s ease;
}
.tab::after{
  content:"";position:absolute;left:0;right:100%;bottom:-1px;height:2px;
  background:var(--blue);transition:right .35s var(--ease);
}
.tab:hover{color:var(--ink)}
.tab[aria-selected="true"]{color:var(--blue)}
.tab[aria-selected="true"]::after{right:0}
.tabpanel-stack{position:relative;overflow:hidden}
.tabpanel[hidden]{display:none}

@media (prefers-reduced-motion:reduce){
  .tabpanel-stack{transition:none}
}

/* ---------- нумерованные шаги ---------- */
.steps{counter-reset:step;display:grid;gap:1px;background:var(--line-soft)}
.step{
  background:var(--cream);padding:26px 24px 28px;
  display:flex;flex-direction:column;gap:12px;
  transition:background .35s ease;
}
.section--deep .step{background:var(--cream-deep)}
.step:hover{background:var(--light)}
.step__num{
  font-family:var(--f-mono);font-size:11px;letter-spacing:.2em;color:var(--amber);
}

/* ---------- утилиты reveal ----------
   Одно правило на все секции: элемент с [data-reveal] стартует смещённым
   и прозрачным, IntersectionObserver вешает .is-in. Задержку задаёт
   инлайновая --d (её проставляет JS по индексу внутри группы), чтобы не
   плодить классы под каждый шаг лесенки. */
[data-reveal]{
  opacity:0;transform:translateY(18px);
  transition:opacity .7s var(--ease),transform .7s var(--ease);
  transition-delay:var(--d,0ms);
}
[data-reveal].is-in{opacity:1;transform:none}
[data-reveal="fade"]{transform:none}
[data-reveal="left"]{transform:translateX(-22px)}
[data-reveal="right"]{transform:translateX(22px)}
/* На 390 px боковое поле как раз 20 px, и стартовый сдвиг вбок 22 px вылезал
   за вьюпорт: overflow-x:hidden на body его не показывал, но документ всё
   равно становился на 2 px шире экрана. Сдвиг ужимаем — он должен помещаться
   в поле страницы, иначе это скрытое переполнение. */
@media (max-width:620px){
  [data-reveal="left"]{transform:translateX(-12px)}
  [data-reveal="right"]{transform:translateX(12px)}
}

/* ---------- общие утилиты ---------- */
.visually-hidden{
  position:absolute;width:1px;height:1px;margin:-1px;padding:0;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;
}

/* Хлебные крошки — один вид на каталог и внутренние страницы. */
.crumbs{
  font-family:var(--f-mono);font-size:10.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--ink-soft);
  margin:0 0 20px;display:flex;flex-wrap:wrap;gap:8px 10px;align-items:center;
}
.crumbs a{text-decoration:none;opacity:.8;transition:color .25s ease,opacity .25s ease}
.crumbs a:hover{color:var(--blue-text);opacity:1}
.crumbs i{font-style:normal;opacity:.4}

/* ---------- cutout-объекты техснаряжения ----------
   Task 10: карабин / узел сетки / домик на дереве — вырезанные PNG→webp
   с альфой, встроенные у заголовков секций как элементы снаряжения, а не
   стикеры. Общий компонент на все страницы; конкретные координаты
   (top/right/width/поворот) — у каждого вызова свои, живут рядом с
   разметкой секции (index.html <style>, pages.css).

   Двухслойная разметка — не разметка ради разметки: внешний .cutout несёт
   СТАТИЧНОЕ позиционирование и наклон (задаются в модификаторе), внутренний
   .cutout__parallax — только динамический сдвиг от скролла (inline-style,
   пишет pages.js). Раздельно, потому что оба transform нельзя выразить
   одним правилом без риска, что параллакс затрёт персональный rotate()
   модификатора при каждом кадре.

   Параллакс — translateY на -0.06 от положения элемента относительно
   центра вьюпорта (не от абсолютного scrollY страницы — тот на глубоких
   секциях уводил маленькую картинку за пределы экрана), считает и пишет
   inline-style pages.js одним общим rAF-слушателем на все cutout сразу,
   без scroll-jack и без IntersectionObserver. Пока JS не отработал (или
   выключен prefers-reduced-motion/мобильным медиа-запросом ниже), у
   .cutout__parallax нет inline-transform — элемент стоит там, где его
   поставил модификатор, без скачка при первом тике. */
.cutout{position:absolute;pointer-events:none;z-index:2}
.cutout img{display:block;width:100%;height:auto;filter:drop-shadow(0 20px 34px rgba(27,33,24,.4))}
@media (max-width:760px){
  /* Декоративный слой на мобиле только мешает — там и так тесно, а
     четверть экрана под болтающийся карабин никто не заказывал. */
  .cutout{display:none}
}

/* Шапка раздела (первый экран внутренней страницы). */
.section--head{padding-bottom:clamp(26px,4vh,44px)}
.section--head .h1{margin:0 0 18px;max-width:17ch}
.sec-head p.lead strong{color:var(--ink);font-weight:600}

/* ---------- панель фильтров ----------
   Липнет под шапкой: --head-h проставляет pages.js по реальной высоте
   .site-top (шрифт и перенос меню её меняют), fallback — на случай,
   если скрипт не отработал. Используют catalog.html и works.html. */
.bar{
  position:sticky;top:var(--head-h,64px);z-index:30;
  background:var(--cream);
  box-shadow:inset 0 -1px 0 var(--line-soft),0 12px 24px -24px rgba(12,18,14,.6);
}
.bar__in{
  max-width:var(--maxw);margin:0 auto;padding:14px var(--pad-x);
  display:flex;flex-wrap:wrap;align-items:center;gap:12px 18px;
}
.chips{display:flex;flex-wrap:wrap;gap:8px}
.chip{
  font-family:var(--f-mono);font-size:11px;font-weight:500;
  letter-spacing:.14em;text-transform:uppercase;
  color:var(--ink-soft);background:transparent;
  border:1px solid var(--line);border-radius:999px;
  padding:8px 13px;cursor:pointer;white-space:nowrap;
  display:inline-flex;align-items:center;gap:8px;
  transition:color .25s ease,border-color .25s ease,background .25s ease;
}
.chip b{font-weight:500;opacity:.55;font-variant-numeric:tabular-nums}
.chip:hover{color:var(--ink);border-color:rgba(22,33,43,.4)}
.chip[aria-pressed="true"]{color:var(--light);background:var(--blue);border-color:var(--blue)}
.chip[aria-pressed="true"] b{opacity:.75}
.bar__count{
  font-family:var(--f-mono);font-size:10.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--ink-soft);
  font-variant-numeric:tabular-nums;
}

/* ---------- день / ночь на кадре ----------
   Общий компонент двух секций: героя tropa.html и промо-полосы тропы на
   главной (#tropa-promo). Поведение — daynight.js: секция помечена
   [data-daynight], в data-night лежит ночной кадр, скрипт вставляет его
   вторым <img class="shot__bg shot__bg--night"> следом за дневным и
   переключает data-time. Раскладку самого кадра (.shot__bg) задаёт каждая
   секция у себя: у героя — pages.css, у промо-полосы — index.html.

   Переключатель: тёмное стекло с тонкой рамкой — элемент лежит на
   фотографии, и любая плотная плашка выглядела бы на ней заплаткой. Две
   кнопки с aria-pressed, а не один тумблер: у тумблера подпись всегда
   врёт про одно из двух состояний. */
.dnt{
  position:absolute;z-index:3;
  right:clamp(16px,5vw,64px);bottom:clamp(40px,6vh,72px);
  display:flex;gap:2px;padding:3px;
  background:rgba(12,18,14,.42);border:1px solid rgba(247,243,235,.22);
  backdrop-filter:blur(12px) saturate(1.15);border-radius:3px;
}
.dnt__b{
  appearance:none;border:0;cursor:pointer;background:transparent;
  padding:8px 16px;border-radius:2px;
  font-family:var(--f-mono);font-size:11.5px;letter-spacing:.13em;
  text-transform:uppercase;color:rgba(247,243,235,.62);
  transition:background .25s var(--ease),color .25s var(--ease);
}
.dnt__b.is-on{background:rgba(247,243,235,.14);color:var(--light)}
.dnt__b:focus-visible{outline:2px solid var(--amber);outline-offset:2px}

/* Ночной слой лежит поверх дневного: z-index у обоих один, и порядок
   решает исходный порядок в DOM — скрипт вставляет его следующим за
   дневным. Проявляется прозрачностью, а не подменой src: при подмене
   кадр на время загрузки исчезал бы, и секция моргала бы белым. */
.shot__bg--night{opacity:0;transition:opacity .4s var(--ease)}
[data-daynight][data-time="night"] .shot__bg--night{opacity:1}

/* АВТОСМЕНА ВРЕМЕНИ СУТОК (правка заказчика 01.09.2026: «чтобы она
   постепенно из дня в ночь, из ночи в день переходила, и подсветка
   включалась»). Кадр один и тот же, снятый днём и ночью, поэтому смена
   читается не как подмена картинки, а как наступление вечера — но
   только на длинном ходу: на прежних 0.4 с это был бы щелчок.
   Класс вешает скрипт, а не разметка: при выключенной анимации и при
   ручном выборе времени цикл не запускается, и тогда остаётся быстрый
   переход — там он уместен, это ответ на клик. */
[data-daynight].is-cycling .shot__bg--night{
  transition:opacity 3.8s cubic-bezier(.45,0,.35,1);
}

/* На узком экране текст секции занимает всю ширину и доходит до низа —
   переключателю там места нет, он уезжает наверх. Каттаут, который в
   этом углу на десктопе, на мобиле скрыт правилом .cutout{display:none}
   выше, так что конфликта нет. */
@media (max-width:700px){
  .dnt{bottom:auto;top:clamp(64px,12vh,110px);right:var(--pad-x)}
}
/* Условие сознательно сужено 09.09.2026 (правка владельца).
   Системный флаг «уменьшить движение» включается не только осознанно:
   его ставят эмуляция в DevTools, энергосбережение, политики и
   расширения — и сайт превращался в набор неподвижных картинок.
   Решение о движении принимает motion.js (одна точка на все скрипты),
   но CSS он переопределить не может, поэтому здесь добавлено
   `and (scripting: none)`: правила остаются в силе там, где скрипты
   выключены и переопределить нечем, и не срабатывают там, где
   решение уже принято в motion.js. Вернуть прежнее поведение —
   убрать `and (scripting: none)` и поставить RESPECT_SYSTEM = true. */
@media (prefers-reduced-motion:reduce) and (scripting:none){
  .shot__bg--night{transition:none}
  .dnt__b{transition:none}
}

/* ---------- шапка и футер ---------- */
.site-top{
  position:sticky;top:0;z-index:40;
  display:flex;align-items:center;gap:clamp(16px,3vw,44px);
  padding:16px var(--pad-x);
  background:rgba(242,237,228,.9);backdrop-filter:blur(10px);
  box-shadow:inset 0 -1px 0 var(--line-soft);
}
.mark{
  font-family:var(--f-display);font-weight:600;font-size:19px;
  letter-spacing:.02em;text-decoration:none;white-space:nowrap;
  display:flex;align-items:center;gap:9px;
}
.mark span{
  /* 11px вместо 9 и плотность .78 вместо .62 (правка заказчика
     25.08.2026: «на хедере покрупнее написать верёвочные парки»).
     Трекинг убавлен с .22em до .18em — на большем кегле прежний
     разгонял строку так, что она начинала спорить с самим логотипом. */
  font-family:var(--f-mono);font-size:11px;font-weight:500;
  letter-spacing:.18em;text-transform:uppercase;opacity:.78;
}
/* Логотип с прода (prototype/img/logo.png — белая подложка снята
   unmultiply-ключом). Одна и та же разметка марки на всех страницах;
   перекраску в белый силуэт над видео берёт на себя index.html. */
.mark img{display:block;height:32px;width:auto}

/* Меню. Семь пунктов в строку помещаются не всегда — перенос разрешён,
   иначе меню наезжает на телефон. */
.site-nav{
  display:flex;flex-wrap:wrap;justify-content:flex-end;
  gap:2px clamp(12px,1.6vw,26px);margin-left:auto;min-width:0;
}
.site-nav a{font-size:14.5px;font-weight:500;text-decoration:none;opacity:.9;padding:4px 0;position:relative}
.site-nav a::after{
  content:"";position:absolute;left:0;right:100%;bottom:0;height:1px;
  background:var(--amber);transition:right .35s var(--ease);
}
.site-nav a:hover::after{right:0}
.site-nav a[aria-current="page"]{color:var(--blue);opacity:1}
.site-nav a[aria-current="page"]::after{right:0}
.site-tel{
  font-family:var(--f-mono);font-size:13.5px;font-weight:500;
  text-decoration:none;white-space:nowrap;
  border:1px solid currentColor;border-radius:999px;padding:7px 15px;opacity:.9;
  transition:background .3s ease,color .3s ease;
}
.site-tel:hover{background:var(--amber);border-color:var(--amber);color:var(--ink);opacity:1}

.site-foot{
  background:var(--forest);color:rgba(247,243,235,.78);
  padding:clamp(48px,7vh,80px) var(--pad-x) clamp(28px,4vh,44px);
}
.site-foot a{color:inherit;text-decoration:none}
.site-foot a:hover{color:var(--amber)}
.site-foot .mark{color:var(--light)}
.foot-grid{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));
  gap:clamp(24px,3vw,48px);max-width:var(--maxw);margin:0 auto;
}
.foot-title{
  font-family:var(--f-mono);font-size:10px;letter-spacing:.2em;text-transform:uppercase;
  color:rgba(247,243,235,.45);margin:0 0 14px;
}
.foot-list{list-style:none;margin:0;padding:0;display:grid;gap:9px;font-size:14.5px}
.foot-legal{
  max-width:var(--maxw);margin:clamp(28px,4vh,48px) auto 0;
  padding-top:20px;border-top:1px solid rgba(247,243,235,.12);
  display:flex;flex-wrap:wrap;gap:10px 28px;
  font-family:var(--f-mono);font-size:11px;letter-spacing:.06em;
  color:rgba(247,243,235,.5);
}

/* ---------- плавающая кнопка контактов (fab) ----------
   Разметка (#fab) одна и та же на всех страницах, поведение — в fab.js,
   набор каналов — WhatsApp / Telegram / звонок / заявка / почта, состав
   подтверждён заказчиком. Здесь — базовое состояние: кнопка ВИДНА сразу,
   это верно для всех внутренних страниц (там нет хиро, уходить не с чего).
   На главной поверх хиро index.html переопределяет старт (opacity:0) и
   выключателем служит JS-класс .is-visible — см. комментарий у updateFab
   в index.html.

   Угол — левый нижний, сознательно не тот же, что у нижней шторки деталей
   конструктива (.rigsheet, тоже index.html): та в портретной раскладке
   стоит по центру низа, а в альбомной короткой — становится правой
   колонкой. Кнопка в любом случае гасится JS, пока идёт конструктив (см.
   updateFab), но угол разведён и на случай, если это правило когда-нибудь
   ослабят — два плавающих элемента не должны претендовать на одно место
   ни в одной раскладке.

   Форма — круг, а не привычная плашка кнопок сайта (.btn: radius 2px):
   это единственный in-system прецедент круглой формы — тот же приём, что
   у .mapbox__pin (страница «Контакты»): синий круг с мягким кольцом тени
   в rgba(46,92,138,…). Кнопка чата не притворяется типовым виджетом
   стороннего сервиса — она визуально та же деталь, что и метка на карте. */
.fab{
  position:fixed;z-index:45;
  /* Справа, а не слева (правка заказчика 08.09.2026: «наверное, ей смысл
     переместить направо»). Заодно уходит старое соседство: слева внизу
     кнопка ложилась на подписи раскрытой панели в аккордеоне типов. */
  right:max(16px,env(safe-area-inset-right));
  bottom:max(16px,env(safe-area-inset-bottom));
  /* стартовое состояние — «видна»; index.html переопределяет ниже своим
     инлайновым блоком стилей */
}
.fab__toggle{
  position:relative;width:56px;height:56px;border-radius:50%;
  display:grid;place-items:center;padding:0;
  background:var(--blue);border:0;color:var(--light);cursor:pointer;
  box-shadow:var(--shadow-card-hi);
  transition:background .3s ease,box-shadow .3s ease,transform .3s var(--ease);
}
.fab__toggle:hover{background:var(--blue-lift);transform:translateY(-2px)}
/* Пульс — расходящиеся кольца (правка заказчика 08.09.2026: «сделать её
   мигающей, чтобы волны расходились, чтобы привлекала внимание»). Кольца
   рисует отдельный элемент, а не ::before/::after кнопки: те заняты плюсом
   (.fab__icon) и крестом. Два кольца со сдвигом в половину цикла читаются
   как непрерывная волна, при этом пауза между всплесками оставляет кнопку
   спокойной — постоянное мигание рядом с текстом раздражает.
   Кольцо не перехватывает события (pointer-events:none) и скрыто от
   скринридеров: это украшение, а не элемент управления. */
.fab__pulse{
  position:absolute;inset:0;border-radius:50%;pointer-events:none;
}
.fab__pulse::before,.fab__pulse::after{
  content:"";position:absolute;inset:0;border-radius:50%;
  border:2px solid var(--blue);
  animation:fabPulse 2.8s cubic-bezier(.2,.7,.3,1) infinite;
}
.fab__pulse::after{animation-delay:1.4s}
@keyframes fabPulse{
  0%   {transform:scale(1);   opacity:.55}
  60%  {transform:scale(1.85);opacity:0}
  100% {transform:scale(1.85);opacity:0}
}
/* Открытую кнопку не пульсируем: внимание уже привлечено, а кольца лезли
   бы под раскрытый список. */
.fab[data-open="true"] .fab__pulse{display:none}
/* открыто — кольцо тем же янтарём, что курсор шкалы полёта (.rail__cursor):
   один и тот же сигнал «активная точка» в обоих местах сайта. Правило идёт
   ПОСЛЕ :hover, чтобы наведение на открытую кнопку не перебивало цвет —
   специфичность у обоих (0,2,0), решает порядок в файле. */
.fab[data-open="true"] .fab__toggle{
  background:var(--ink);box-shadow:var(--shadow-card-hi),0 0 0 5px rgba(233,182,63,.28);
}
.fab[data-open="true"] .fab__toggle:hover{background:var(--ink)}
/* иконка — плюс, разворачивающийся в крест: тот же геометричный,
   безбрендовый язык, что у стрелок в .btn i и делений шкалы .tick;
   готовых иконок (svg-спрайт, шрифт) в проекте нет и здесь заводить не
   стоит ради одной кнопки */
.fab__icon{position:relative;width:18px;height:18px;display:block;flex:none}
.fab__icon::before,.fab__icon::after{
  content:"";position:absolute;left:50%;top:50%;
  width:18px;height:2px;margin:-1px 0 0 -9px;border-radius:1px;
  background:currentColor;transition:transform .3s var(--ease);
}
.fab__icon::after{transform:rotate(90deg)}
.fab[data-open="true"] .fab__icon::before{transform:rotate(45deg)}
.fab[data-open="true"] .fab__icon::after{transform:rotate(135deg)}

/* Список каналов раскрывается ВВЕРХ от кнопки: внизу экрана расти вниз
   некуда. [hidden] выключает элемент из доступности и раскладки полностью
   (важно для клавиатуры — свёрнутый список не должен ловить Tab); при этом
   .fab__panel сама — flex, и без explicit override здесь браузер взял бы
   класс, а не атрибут (см. тот же приём у .tabpanel[hidden] выше). */
.fab__panel{
  /* Прижата к правому краю вслед за кнопкой; min-width больше не нужен —
     пункты стали иконками фиксированного размера. */
  position:absolute;right:0;bottom:calc(100% + 12px);
  display:flex;flex-direction:column-reverse;align-items:flex-end;gap:8px;
}
.fab__panel[hidden]{display:none}
/* Пункт — иконка И подпись (09.09.2026): одна иконка без слова читается
   быстро, но не всегда однозначно, а «Заявка» и «Почта» узнаваемого знака
   не имеют вовсе. Высота фиксирована, ширина по содержимому — плашки
   выстраиваются по правому краю вслед за кнопкой.
   У WhatsApp значка НЕТ намеренно (решение владельца 09.09.2026): сервис
   принадлежит Meta, признанной в РФ экстремистской, и за размещение логотипов
   таких сервисов штрафуют владельца сайта — а слово-ссылка символикой не
   является. Сам пункт при этом нужен: часть клиентов пишет именно туда, хотя
   с февраля 2026 мессенджер в России и заблокирован. Планируется добавить MAX,
   как только заказчик пришлёт ссылку на профиль (уникальный хеш max.ru/u/…,
   придумать её нельзя). */
.fab__item{
  display:flex;align-items:center;gap:10px;
  height:44px;padding:0 18px;
  background:var(--light);border:1px solid var(--line);border-radius:999px;
  font-family:var(--f-mono);font-size:12px;font-weight:500;
  letter-spacing:.1em;text-transform:uppercase;white-space:nowrap;
  color:var(--ink);text-decoration:none;box-shadow:var(--shadow-card);
  opacity:0;transform:translateY(10px) scale(.96);pointer-events:none;
  transition:opacity .2s var(--ease),transform .2s var(--ease),
             background .25s ease,color .25s ease,border-color .25s ease;
}
.fab__item:hover{background:var(--blue);border-color:var(--blue);color:var(--light)}
/* Иконка наследует color ссылки — поэтому смена цвета на наведении красит
   и её, отдельного правила не нужно. */
.fab__ico{width:19px;height:19px;display:block;flex:none;fill:currentColor}
.fab[data-open="true"] .fab__item{opacity:1;transform:none;pointer-events:auto}
/* лесенка появления — от кнопки наружу: ближний к ней пункт (WhatsApp,
   первый в разметке и в порядке, который подтвердил заказчик) виден
   первым, дальний (почта) — последним. Задержки короче, чем у [data-reveal]
   (там 70мс шаг): пунктов пять и они раскрываются по клику, а не по
   скроллу — ждать полсекунды, чтобы дотянуться до нижнего пункта, уже
   неудобно. */
.fab[data-open="true"] .fab__item:nth-child(1){transition-delay:0ms}
.fab[data-open="true"] .fab__item:nth-child(2){transition-delay:20ms}
.fab[data-open="true"] .fab__item:nth-child(3){transition-delay:40ms}
.fab[data-open="true"] .fab__item:nth-child(4){transition-delay:60ms}
.fab[data-open="true"] .fab__item:nth-child(5){transition-delay:80ms}
@media (max-width:480px){
  .fab__item{height:40px;padding:0 14px;font-size:11px;gap:8px}
  .fab__ico{width:17px;height:17px}
}
@media (prefers-reduced-motion:reduce) and (scripting:none){
  /* Пульс — чистое движение ради внимания, при системном запрете анимаций
     его быть не должно; кнопка остаётся видимой и рабочей. */
  .fab__pulse::before,.fab__pulse::after{animation:none;opacity:0}
}

/* ---------- модальное окно ----------
   Правка заказчика 09.09.2026: «кнопка подобрать парк должна форму обратной
   связи вызывать, попап это хорошее решение». Раньше кнопка уводила в каталог,
   то есть первый экран заканчивался не разговором, а ещё одним списком.

   Разметка живёт в конце страницы и до открытия помечена [hidden] — это
   выключает её и из раскладки, и из таб-порядка: свёрнутая форма не должна
   ловить фокус. Само окно — не <dialog>: у него до сих пор разное поведение
   с прокруткой фона в мобильных браузерах, а нам важнее предсказуемость.

   Прокрутка фона гасится классом на <html> (см. modal.js): без этого страница
   под окном уезжает под пальцем, и человек теряет место, на котором был. */
.modal{position:fixed;inset:0;z-index:60;display:grid;place-items:center;padding:16px}
.modal[hidden]{display:none}
.modal__scrim{
  position:absolute;inset:0;background:rgba(27,33,24,.62);
  backdrop-filter:blur(3px);
  opacity:0;transition:opacity .25s var(--ease);
}
.modal.is-open .modal__scrim{opacity:1}
.modal__box{
  position:relative;width:min(560px,100%);max-height:92svh;overflow:auto;
  background:var(--light);border-radius:18px;padding:clamp(22px,3.4vw,38px);
  box-shadow:0 30px 80px rgba(27,33,24,.35);
  opacity:0;transform:translateY(14px) scale(.98);
  transition:opacity .25s var(--ease),transform .25s var(--ease);
}
.modal.is-open .modal__box{opacity:1;transform:none}
.modal__x{
  position:absolute;top:10px;right:10px;width:40px;height:40px;
  display:grid;place-items:center;border:0;border-radius:50%;
  background:transparent;color:var(--ink);font-size:26px;line-height:1;cursor:pointer;
  transition:background .2s ease;
}
.modal__x:hover{background:rgba(27,33,24,.08)}
.modal__lead{margin:8px 0 18px;color:var(--muted)}
/* Пока окно открыто, страница под ним не прокручивается. */
html.is-modal-open,html.is-modal-open body{overflow:hidden}

/* ---------- адаптив ---------- */
@media (max-width:1080px){
  .grid-4{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:900px){
  body{font-size:16px}
  .sec-head--split{grid-template-columns:1fr;align-items:start}
  .grid-3{grid-template-columns:repeat(2,minmax(0,1fr))}

  /* Backdrop blur у липкой шапки пересчитывает лежащую под ней страницу
     на каждом кадре прокрутки. На мобильном почти непрозрачная заливка
     выглядит так же собранно, но не требует постоянной растеризации. */
  .site-top{
    background:rgba(242,237,228,.97);
    backdrop-filter:none;-webkit-backdrop-filter:none;
  }

  /* Меню на мобильном не прячем: со страницы должно быть куда уйти, а
     бургер на семь пунктов — лишний слой и лишний JS. Шапка разворачивается
     во вторую строку, меню становится горизонтальной лентой с мягким срезом
     справа — тем же приёмом, что чипы фильтров и табы ниже по файлу. */
  .site-top{flex-wrap:wrap;row-gap:8px;padding-bottom:8px}
  .site-tel{margin-left:auto}
  .site-nav{
    order:3;width:100%;margin-left:0;gap:20px;
    flex-wrap:nowrap;justify-content:flex-start;
    overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch;
    padding-bottom:2px;
    -webkit-mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent);
    mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent);
  }
  .site-nav::-webkit-scrollbar{display:none}
  /* Не только строка текста, но и вся её высота должна быть удобной
     мишенью для пальца. Визуально меню остаётся лёгким: свободное место
     добавлено внутрь ссылки, без плашек и рамок. */
  .mark,.site-tel,.site-nav a{min-height:44px}
  .site-tel,.site-nav a{display:flex;align-items:center}
  .site-nav a{white-space:nowrap;font-size:13.5px;flex:none;padding:7px 0}

  /* Чипы фильтров: пять штук в строку уже не помещаются — вместо переноса
     горизонтальный скролл, иначе сортировка повисает одна на второй строке. */
  .chips{
    flex-wrap:nowrap;overflow-x:auto;width:100%;
    scrollbar-width:none;-webkit-overflow-scrolling:touch;padding-bottom:2px;
    -webkit-mask-image:linear-gradient(to right,#000 calc(100% - 34px),transparent);
    mask-image:linear-gradient(to right,#000 calc(100% - 34px),transparent);
  }
  .chips::-webkit-scrollbar{display:none}
  .chip{flex:none}
}
@media (max-width:620px){
  .grid-2,.grid-3,.grid-4,.grid-auto{grid-template-columns:1fr}
  .h2{max-width:none}
  .btn{padding:13px 20px;font-size:14.5px}
  /* Три таба в 390 px не помещаются в строку. Перенос давал вторую строку
     кнопок — полосу, которую легко принять за меню; горизонтальная лента
     читается однозначнее и оставляет подчёркивание активного таба на месте. */
  .tabs{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch}
  .tabs::-webkit-scrollbar{display:none}
  .tab{font-size:14px;margin-right:12px;white-space:nowrap;flex:none}
  .mark span{display:none}
  .mark img{height:28px}
  .bar__in{padding:12px var(--pad-x);gap:10px 12px}
  .chip{font-size:10.5px;padding:7px 13px;letter-spacing:.1em}
}
@media (prefers-reduced-motion:reduce) and (scripting:none){
  [data-reveal]{opacity:1;transform:none;transition:none}
  .card,.card:hover,.card__media img,.btn,.btn:hover{transition:none;transform:none}
  /* открытие/закрытие остаётся мгновенным по hidden — только гасим переезд
     и поворот плюса в крест */
  .fab__toggle,.fab__toggle:hover,.fab__icon::before,.fab__icon::after,.fab__item{transition:none}
}

/* ============================================================
   Заслонка загрузки (правка владельца 01.09.2026: «пока весь контент не
   прогрузится, на сайте должен быть лоадер — я не должна видеть сайт,
   пока все картинки во вьюпорте не отображены»).

   Сделана на псевдоэлементах <html>, а не отдельным блоком в разметке:
   блок пришлось бы вставлять в десять файлов и следить, чтобы он стоял
   первым в body. Класс на <html> ставится инлайн-скриптом в <head>, то
   есть до первой отрисовки, поэтому вспышки контента не бывает вовсе.

   Обычно снимается по window.load — это событие ждёт картинки, попавшие в
   вёрстку, но НЕ ждёт lazy-кадры вне экрана и не ждёт hero-видео (его
   src подставляется уже после load). Ровно то, что просили: «которые во
   вьюпорте». На главной есть более точное правило: инлайн-скрипт ждёт
   decode LCP-постера нужной ориентации, чтобы внешний шрифт не мог держать
   готовую страницу за заслонкой. Сверху страховка таймером: на медленной сети смотреть в
   заслонку дольше нескольких секунд хуже, чем увидеть страницу
   недогруженной.
   ============================================================ */
html.is-loading{overflow:hidden}
html.is-loading body{opacity:0}
html.is-loading::before{
  content:"";position:fixed;inset:0;z-index:9998;background:var(--cream,#F7F3EB);
}
/* Индикатор — кольцо в фирменном зелёном. Тонкое и небольшое: заслонка
   должна читаться как пауза, а не как экран загрузки игры. */
html.is-loading::after{
  content:"";position:fixed;z-index:9999;
  top:50%;left:50%;width:38px;height:38px;margin:-19px 0 0 -19px;
  border:2px solid rgba(31,58,35,.16);border-top-color:var(--green,#2E6B34);
  border-radius:50%;animation:pageload-spin .8s linear infinite;
}
@keyframes pageload-spin{to{transform:rotate(360deg)}}
/* Появление страницы: плавное, чтобы снятие заслонки не читалось как
   щелчок. Заслонка к этому моменту уже удалена из потока (класс снят),
   поэтому анимируется только сам контент. */
html.is-loaded body{animation:pageload-in .45s var(--e2,ease) both}
@keyframes pageload-in{from{opacity:0}to{opacity:1}}
@media (prefers-reduced-motion:reduce) and (scripting:none){
  html.is-loading::after{animation:none}
  html.is-loaded body{animation:none}
}

/* ============================================================
   Лайтбокс — общий просмотрщик снимков (prototype/gallery.js)
   ------------------------------------------------------------
   Жил в catalog.css, пока его открывали только каталог и страница
   модели. С 09.09.2026 тот же просмотрщик открывают страницы работ
   (prototype/works/*.html), а catalog.css они не подключают — стили
   переехали сюда, в общую таблицу, вместо второй копии: две копии
   ловушки фокуса и блокировки прокрутки разъезжаются на первой же
   правке ровно так же, как разъехались бы две копии этих правил.

   Выше всего на странице: шапка 40, панель фильтров 30, плавающая
   кнопка 45 — поэтому 90.
   ============================================================ */
.lbox{position:fixed;inset:0;z-index:90;display:flex;align-items:center;justify-content:center}
.lbox[hidden]{display:none}
.lbox__scrim{
  position:absolute;inset:0;background:rgba(27,33,24,.93);
  opacity:0;transition:opacity .28s ease;
}
.lbox.is-on .lbox__scrim{opacity:1}
/* поле вокруг снимка — часть зоны закрытия, поэтому это не картинка
   с полями, а отдельный слой с padding'ом */
.lbox__stage{
  position:absolute;inset:0;z-index:1;margin:0;
  display:flex;align-items:center;justify-content:center;
  padding:clamp(52px,8vh,84px) clamp(12px,5vw,80px);
  touch-action:pan-y;
  opacity:0;transform:scale(.985);
  transition:opacity .28s ease,transform .28s var(--ease);
}
.lbox.is-on .lbox__stage{opacity:1;transform:none}
/* contain, а не cover: на телефоне снимок должен помещаться целиком */
.lbox__img{
  max-width:100%;max-height:100%;width:auto;height:auto;object-fit:contain;
  -webkit-user-drag:none;user-select:none;
  box-shadow:0 30px 70px -30px rgba(0,0,0,.8);
}
.lbox.is-drag .lbox__img{transition:none}

.lbox__btn{
  position:absolute;z-index:2;border:0;padding:0;cursor:pointer;
  width:44px;height:44px;border-radius:50%;
  background:rgba(242,237,228,.92);color:var(--ink);
  font-size:22px;line-height:1;
  display:flex;align-items:center;justify-content:center;
  transition:background .25s ease,transform .25s ease;
}
.lbox__btn[hidden]{display:none}
.lbox__btn:hover{background:var(--amber)}
.lbox__btn:focus-visible{outline:2px solid var(--cream);outline-offset:2px}
.lbox__close{top:14px;right:14px}
.lbox__nav{top:50%;margin-top:-22px}
.lbox__nav--prev{left:14px}
.lbox__nav--next{right:14px}
.lbox__count{
  position:absolute;left:0;right:0;bottom:16px;z-index:2;margin:0;text-align:center;
  font-family:var(--f-mono);font-size:11px;letter-spacing:.18em;
  color:var(--cream);font-variant-numeric:tabular-nums;pointer-events:none;
}
/* фон под лайтбоксом не прокручивается; ширину исчезнувшего скроллбара
   компенсирует gallery.js инлайновым padding-right, иначе страница
   дёргается вбок в момент открытия */
html.is-lbox,html.is-lbox body{overflow:hidden}

@media (max-width:620px){
  /* кнопки лайтбокса на телефоне не должны наезжать на снимок */
  .lbox__btn{width:38px;height:38px;font-size:19px}
  .lbox__nav{margin-top:-19px}
  .lbox__stage{padding:clamp(46px,7vh,58px) 8px}
}
/* Об условии `and (scripting:none)` — см. одноимённые блоки в site.css выше:
   решение о движении принимает motion.js, CSS его переопределить не может. */
@media (prefers-reduced-motion:reduce) and (scripting:none){
  .lbox__scrim,.lbox__stage,.lbox__btn{transition-duration:.01ms !important}
  .lbox__stage{transform:none !important}
}

/* ============================================================
   HERO НА ВСЮ ШИРИНУ: ПРОЗРАЧНАЯ ШАПКА + КАДР/ВИДЕО
   ------------------------------------------------------------
   Вынесено из index.html 14.09.2026: такой же hero понадобился
   project.html (правка владельца — «как хиро основной, только без
   видео»). Держать две копии одних и тех же правил значило бы, что
   первая же правка главной разведёт страницы. Здесь — всё, что не
   зависит от видео; сам ролик, постер и проявление остались в
   index.html. Поведение шапки при прокрутке — hero-top.js.

   Блок стоит в самом конце файла намеренно: на главной эти правила
   раньше шли встроенным <style> после site.css и перебивали базовые
   .site-top и .mark. Конец файла сохраняет тот же порядок каскада.
   ============================================================ */

/* ---------- шапка поверх hero ----------
   Модификатор --hero переводит шапку из sticky в fixed, снимает кремовую
   подложку и добавляет три независимых состояния:
   • is-light  — тёмный текст поверх кремовой зоны (прозрачная подложка);
   • is-solid  — hero пройден, шапка встаёт на сплошную кремовую заливку;
   • is-hidden — автоскрытие при движении вниз (только transform).
   Разведены по разным свойствам (color / background / transform), поэтому
   любая комбинация складывается без конфликтов. Разделительная линия —
   inset-тенью, а не border-bottom: бордер менял бы высоту фиксированной
   шапки, и текст под ней дёргался бы в момент появления заливки. */
.site-top--hero{
  position:fixed;inset:0 0 auto 0;z-index:40;
  padding:18px var(--pad-x);
  color:var(--light);
  background:none;backdrop-filter:none;box-shadow:none;
  will-change:transform;
  transition:color .45s ease,background-color .3s ease,box-shadow .3s ease,
             transform .3s cubic-bezier(.2,.7,.2,1);
}
.site-top--hero::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background:linear-gradient(to bottom,rgba(12,18,14,.55),rgba(12,18,14,0));
  transition:opacity .45s ease;
}
.site-top--hero.is-light{color:var(--ink)}
.site-top--hero.is-light::before{opacity:0}
.site-top--hero.is-solid{
  background-color:var(--cream);color:var(--ink);
  box-shadow:inset 0 -1px 0 rgba(20,28,22,.10),0 10px 26px -20px rgba(12,18,14,.55);
}
.site-top--hero.is-solid::before{opacity:0}
.site-top--hero.is-hidden{transform:translateY(-100%)}
/* Активный пункт не красим в зелёный: над кадром он провалится в фон. */
.site-top--hero .site-nav a[aria-current="page"]{color:inherit;opacity:1}

/* БЕЛЫЙ ЛОГОТИП — ОТДЕЛЬНЫЙ ФАЙЛ, А НЕ ФИЛЬТР (11.09.2026).
   Раньше белый силуэт делался перекраской filter:brightness(0) invert(1),
   а когда туда дописали тень, Safari и Opera перестали применять цепочку
   целиком: логотип оставался тёмным и на тёмном кадре пропадал. Теперь
   белая версия — настоящий файл img/logo-white.png, а состояния шапки
   меняют, какая из двух картинок видима. Тень — на родителе, одной
   функцией: она держит тонкий знак на светлых участках кадра. */
.mark{position:relative}
.mark__logo{transition:opacity .45s ease}
.mark__logo--white{position:absolute;left:0;top:50%;transform:translateY(-50%);opacity:0}
.site-top--hero .mark{filter:drop-shadow(0 1px 3px rgba(7,14,10,.55))}
.site-top--hero .mark__logo--white{opacity:1}
.site-top--hero .mark__logo:not(.mark__logo--white){opacity:0}
.site-top--hero.is-light .mark,
.site-top--hero.is-solid .mark{filter:none}
.site-top--hero.is-light .mark__logo--white,
.site-top--hero.is-solid .mark__logo--white{opacity:0}
.site-top--hero.is-light .mark__logo:not(.mark__logo--white),
.site-top--hero.is-solid .mark__logo:not(.mark__logo--white){opacity:1}
.site-top--hero.is-light .mark img,
.site-top--hero.is-solid .mark img{filter:none}

/* ---------- сам hero ---------- */
.flight{position:relative;height:100svh;min-height:680px}
.stage{
  position:sticky;top:0;height:100vh;overflow:hidden;
  background:var(--forest);
}
.montage{
  position:absolute;inset:0;z-index:8;overflow:hidden;
  color:var(--light);background:#172016;
}
.montage__shade{
  position:absolute;inset:0;z-index:2;pointer-events:none;
  background:
    linear-gradient(90deg,rgba(7,14,10,.72) 0%,rgba(7,14,10,.38) 43%,rgba(7,14,10,.08) 72%),
    linear-gradient(0deg,rgba(7,14,10,.64) 0%,rgba(7,14,10,.08) 48%,rgba(7,14,10,.30) 100%);
}
/* Неподвижный кадр вместо видео — для внутренних страниц. Картинка, а не
   background: srcset отдаёт 4К-ступень только тем экранам, которым она
   нужна, а fetchpriority позволяет поднять её как главный кадр страницы. */
.montage__still{
  position:absolute;inset:0;width:100%;height:100%;
  display:block;object-fit:cover;
}
.montage__content{
  position:absolute;z-index:5;left:var(--pad-x);right:var(--pad-x);
  top:auto;bottom:112px;transform:none;max-width:min(760px,64vw);
  text-shadow:var(--shadow-text);
}
.montage__content .eyebrow,
.montage__lead{display:none}
.montage__content .eyebrow{color:var(--amber);white-space:nowrap}
.montage__content h1{
  margin:0;font-family:var(--f-display);font-weight:600;
  font-size:clamp(2.35rem,4.6vw,4.9rem);line-height:.96;letter-spacing:-.04em;
}
.montage__content h1 span{display:block}
.montage__lead{
  margin:26px 0 0;max-width:54ch;font-size:clamp(16px,1.25vw,20px);
  line-height:1.55;color:rgba(247,243,235,.88);
}
/* На главной подзаголовок спрятан — там его роль играет само видео. На
   странице с неподвижным кадром текст о предмете страницы нужен. */
.montage--still .montage__lead{display:block}
/* Заголовки внутренних страниц длиннее главной («Подвесная тропа — прогулка
   в кронах деревьев»): при ширине главной тире вместе с половиной фразы
   уходило на отдельную строку. Подзаголовок держит свою меру (54ch). */
.montage--still .montage__content{max-width:min(900px,72vw)}
.montage__actions{display:flex;align-items:center;flex-wrap:wrap;gap:14px 26px;margin-top:30px}
.montage__actions .btn-ghost{color:rgba(247,243,235,.9);border-bottom-color:rgba(247,243,235,.36)}
.montage__actions .btn-ghost:hover{color:var(--amber);border-bottom-color:var(--amber)}
.montage__facts{
  position:absolute;z-index:5;left:var(--pad-x);right:var(--pad-x);bottom:28px;
  display:flex;gap:clamp(20px,4vw,64px);font-family:var(--f-mono);
  font-size:10px;line-height:1.35;letter-spacing:.14em;text-transform:uppercase;
  color:rgba(247,243,235,.62);
}
.montage__facts b{display:block;margin-bottom:3px;color:var(--light);font-size:13px;font-weight:500;letter-spacing:.08em}

/* Надзаголовок и светлая кнопка поверх кадра. Селекторы прибиты к .flight:
   ниже по странице те же .eyebrow/.btn-ghost берут обычный вид. */
.flight .eyebrow{color:var(--amber);white-space:nowrap}
.flight .btn-ghost{color:rgba(247,243,235,.85);border-bottom-color:rgba(247,243,235,.3)}
.flight .btn-ghost:hover{color:var(--amber);border-color:var(--amber)}

/* Плавающая кнопка контактов на страницах с hero. Заказчик: кнопка
   появляется, «когда мы уходим с хиро» — над кадром она либо висела бы
   лишней деталью, либо закрывала бы факты внизу (на телефоне так и было).
   Стартует скрытой: атрибут hidden в разметке не даёт мелькнуть до
   скрипта, а opacity/transform дают появиться не рывком. Момент считает
   hero-top.js. Селектор через соседа-шапку: на страницах без hero кнопка
   видна сразу, как и раньше. */
.site-top--hero ~ .fab{
  opacity:0;transform:translateY(14px) scale(.94);
  transition:opacity .35s ease,transform .35s var(--ease);
}
.site-top--hero ~ .fab.is-visible{opacity:1;transform:none}

@media (max-width:900px){
  /* Вторую строку меню (лента ниже 900 px) шорткат padding выше затирает —
     поэтому нижнее поле задаём здесь явно. */
  .site-top--hero{padding:14px 18px 8px}
  .flight .eyebrow{white-space:normal;font-size:10px;letter-spacing:.18em;margin-bottom:12px}
  .flight .eyebrow::before{width:16px}
}

@media (max-width:700px){
  .flight{min-height:620px}
  .montage__shade{
    background:
      linear-gradient(0deg,rgba(7,14,10,.76) 0%,rgba(7,14,10,.22) 55%,rgba(7,14,10,.38) 100%),
      linear-gradient(90deg,rgba(7,14,10,.46),rgba(7,14,10,.04));
  }
  /* 104px, а не 72: на телефоне строка фактов упиралась в шов со
     следующей секцией (правка владельца 09.09.2026). */
  .montage__content{top:auto;bottom:104px;transform:none;max-width:none}
  .montage__content .eyebrow{white-space:normal;font-size:10px;letter-spacing:.16em}
  .montage__content h1{font-size:clamp(1.95rem,8.7vw,3rem);line-height:1.0}
  /* «Индивидуальный» — самое длинное слово среди заголовков hero: при
     кегле главной (8.7vw) оно упиралось в правый край телефона. Кегль
     уменьшаем, а не рвём слово — перенос посередине корня читается хуже. */
  .montage--still .montage__content h1{font-size:clamp(1.6rem,7.4vw,3rem)}
  .montage__lead{margin-top:18px;font-size:15px;line-height:1.48;max-width:34ch}
  .montage__actions{margin-top:22px;gap:12px 18px}
  .montage__facts{bottom:34px;gap:22px;overflow:hidden}
  .montage__facts span:last-child{display:none}
}

@media (prefers-reduced-motion:reduce) and (scripting:none){
  /* шапка по-прежнему прячется и заливается, но без хода: смена цвета и
     заливки остаётся (это не движение), уезжание вверх — мгновенное */
  .site-top--hero{transition:color .45s ease,background-color .3s ease,box-shadow .3s ease}
  .site-top--hero ~ .fab{transition:none}
}
