/* ═══════════════════════════════════════════════════════════════════════
   Стили сайта визажиста Яны.  ВЕРСИЯ: 14

   ПОМЕНЯЛ ЧТО-ТО ЗДЕСЬ — подними номер выше И в ссылке в index.html:
   <link rel="stylesheet" href="styles.css?v=14">
   Файл кэшируется на год как immutable (vercel.json), поэтому без смены
   адреса вернувшийся посетитель останется на старых стилях.

   Вынесены из index.html 2026-08-19. Правки цвета, типографики и раскладки
   идут сюда; разметка и тексты остаются в index.html.

   Порядок правил значим: утилита .is-hidden привязана к родителю
   (.works > .is-hidden), потому что одиночный класс проигрывает по порядку
   правилу .work{display:block} ниже по файлу.
   ═══════════════════════════════════════════════════════════════════════ */

/* ─────────────────────────────────────────────────────────────────────────
   ТОКЕНЫ

   Страница собрана из трёх источников по выбору заказчика:
   · типографика и тон  — вариант C «Камерная»  (Playfair Display + Golos Text)
   · первый экран       — вариант A «Разворот»  (тёмный тёплый, фото во всю ширину)
   · остальная страница — вариант B «Полоса»    (почти белая тёплая бумага)

   Акцент один — пыльная роза, но в двух светлотах: на почти белой бумаге
   светлая роза даёт контраст 2.2:1 и не читается, поэтому для светлых
   поверхностей взят тот же тон глубже.
   ───────────────────────────────────────────────────────────────────────── */
:root{
  /* бумага основной части — из варианта B */
  --paper:      #F4F2EE;
  --paper-lift: #FBFAF8;
  --paper-deep: #E9E5DE;
  --line:       #D8D3CB;

  /* чернила: тёплый тёмный, родственный первому экрану */
  --ink:      #231D1B;
  --ink-soft: #635853;

  /* акцент — пыльная роза в двух светлотах */
  --accent:      #9E5A50;   /* на светлом */
  --accent-lift: #D9A79E;   /* на тёмном */

  /* первый экран и подвал — из варианта A */
  --dark:       #1A1210;
  --cream:      #F3EBE2;
  --cream-soft: rgba(243,235,226,.72);
  --cream-dim:  rgba(243,235,226,.46);
  --cream-line: rgba(243,235,226,.16);

  --f-display:'Playfair Display', Georgia, 'Times New Roman', serif;
  --f-body:'Golos Text', 'Helvetica Neue', Arial, sans-serif;

  --gut:  clamp(1.25rem, 5vw, 4.5rem);
  --wide: 1320px;
  --sec:  clamp(4.5rem, 11vw, 9.5rem);
  --head: 4.75rem;

  /* Разрез первого экрана: слева тёмная текстовая зона, справа фотография.
     На нём же стоит шапка — знак в левой зоне, меню и Telegram в правой.
     Одно значение на два блока, поэтому сетка у них общая по определению.
     На 980 px и уже разреза нет: там фотография во всю ширину, как было */
  --split: 41.5%;

  --ease: cubic-bezier(.22,.61,.36,1);

  /* Скругление — только у кнопок, остальная страница прямоугольная.
     В px, а не в rem: радиус привязан к углу кнопки, а не к кеглю, —
     при крупном системном шрифте кнопка растёт, угол остаётся тем же */
  --btn-round: 20px;
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{
  margin:0;
  background:var(--paper);
  color:var(--ink);
  font-family:var(--f-body);
  font-size:1rem;
  line-height:1.8;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
img{max-width:100%;height:auto;display:block}
h1,h2,h3,h4{margin:0;font-weight:500;font-family:var(--f-display);line-height:1.05;letter-spacing:-.02em}
p{margin:0}
a{color:inherit}
ul{margin:0;padding:0;list-style:none}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px}

/* Переход по якорю из меню не должен прятать заголовок под шапкой */
[id]{scroll-margin-top:calc(var(--head) + 1rem)}

.skip{
  position:absolute;left:-9999px;top:0;z-index:100;
  background:var(--ink);color:var(--paper);padding:.75rem 1.25rem;text-decoration:none;
  border-radius:var(--btn-round);
}
.skip:focus{left:0}

.wrap{max-width:var(--wide);margin:0 auto;padding-inline:var(--gut)}

/* Служебный тип — капслок с разрядкой на Golos Text. Третьей гарнитуры нет
   намеренно: каждый шрифтовой файл стоит миллисекунд, а обвал конверсии
   приходится на первые две секунды (research §3.1) */
.micro{
  font-size:.6875rem;letter-spacing:.2em;text-transform:uppercase;
  font-weight:500;line-height:1.6;
}

/* ── ШАПКА: кремовая поверх тёмного героя, чернильная на бумаге ────────── */
.top{
  position:fixed;top:0;left:0;right:0;z-index:60;
  color:var(--cream);
  border-bottom:1px solid transparent;
  transition:background .45s var(--ease), color .45s var(--ease), border-color .45s var(--ease);
}
/* Прозрачная шапка нужна только в покое, на первом кадре героя. Как только
   контент поехал под неё — подложка обязательна, иначе имя наезжает на кнопку */
.top.is-dark{
  background:rgba(26,18,16,.74);
  backdrop-filter:blur(14px) saturate(1.2);
  border-bottom-color:var(--cream-line);
}
.top.is-light{
  color:var(--ink);
  background:var(--paper);
  background:color-mix(in srgb, var(--paper) 90%, transparent);
  backdrop-filter:blur(14px) saturate(1.2);
  border-bottom-color:var(--line);
}
/* Шапка стоит на сетке первого экрана, а не на своей: колонки те же самые,
   поэтому знак попадает в тёмную зону, а меню с кнопкой — в фотографическую.
   Полей у полосы нет, их держат сами зоны: иначе разрез поехал бы */
.top__in{
  height:var(--head);
  display:grid;grid-template-columns:var(--split) 1fr;align-items:center;
  transition:height .45s var(--ease);
}
.mark{justify-self:center}
.top__side{
  justify-self:end;display:flex;align-items:center;gap:2rem;
  padding-right:clamp(1.25rem,5vw,4.5rem);
}
/* Ниже первого экрана шапка подбирается: полоса и знак ниже. Подложка,
   размытие и нижняя граница уже включены в .top.is-light выше.
   --head при этом не трогаем — на нём висит отступ якорей и верхнее поле
   героя, и они должны считаться по полной высоте, а не по сжатой */
.top.is-light .top__in{height:3.75rem}
.top.is-light .mark__logo{height:1.875rem}
/* Подстановка вместо логотипа: имя набрано текстом.
   Знак встанет на это место без переверстки шапки (brief.md §11) */
.mark{
  font-family:var(--f-display);font-size:1.0625rem;font-weight:500;
  letter-spacing:.34em;text-transform:uppercase;text-decoration:none;
  white-space:nowrap;
}
/* Знак в шапке. Слово берёт цвет шапки и переключается вместе с ней, росчерк
   держит акцент сам: на тёмной подложке светлая роза, на бумаге — глубокая.
   Светлую розу на бумагу нельзя, это 2.2:1, знак растворяется (см. ТОКЕНЫ) */
.mark__logo{display:block;height:2.25rem;width:auto;transition:height .45s var(--ease)}
.mark__swash{color:var(--accent-lift)}
.top.is-light .mark__swash{color:var(--accent)}
.nav{display:flex;gap:1.75rem}
.nav a{
  text-decoration:none;font-size:.8125rem;letter-spacing:.04em;
  opacity:.72;position:relative;padding-block:.25rem;
  transition:opacity .3s var(--ease);
}
.nav a::after{
  content:'';position:absolute;left:0;bottom:0;height:1px;width:100%;
  background:currentColor;transform:scaleX(0);transform-origin:left;
  transition:transform .4s var(--ease);
}
.nav a:hover{opacity:1}
.nav a:hover::after{transform:scaleX(1)}
.top__tg{
  text-decoration:none;border:1px solid currentColor;opacity:.85;
  padding:.5rem 1.0625rem;border-radius:var(--btn-round);white-space:nowrap;
  transition:opacity .3s var(--ease), background .3s var(--ease), color .3s var(--ease);
}
.top__tg:hover{opacity:1}
.top.is-light .top__tg:hover{background:var(--ink);color:var(--paper)}
/* ── МОБИЛЬНОЕ МЕНЮ ────────────────────────────────────────────────────
   Гамбургер: две полоски, при открытии складываются в крест */
.burger{
  display:none;position:relative;flex:none;
  width:2.75rem;height:2.75rem;margin-right:-.75rem;
  align-items:center;justify-content:center;
  background:none;border:0;color:inherit;cursor:pointer;
}
.burger span{
  position:absolute;left:.75rem;right:.75rem;height:1px;background:currentColor;
  transition:transform .35s var(--ease);
}
.burger span:nth-child(1){transform:translateY(-3px)}
.burger span:nth-child(2){transform:translateY(3px)}
.top.is-open .burger span:nth-child(1){transform:rotate(45deg)}
.top.is-open .burger span:nth-child(2){transform:rotate(-45deg)}

/* Панель раскрывается по max-height, а не по height: высота зависит от числа
   пунктов, и назвать её числом заранее нельзя. 420 px — потолок с запасом,
   панель до него не доезжает, поэтому скорость не зависит от длины меню.

   visibility обязательна: у закрытой панели max-height:0 и overflow:hidden,
   но ссылки внутри всё равно ловятся табом — на десктопе это шесть невидимых
   остановок курсора. Переключается без плавности и с задержкой на время
   закрытия, иначе панель пропадала бы раньше, чем схлопнулась */
.mnav{
  max-height:0;overflow:hidden;visibility:hidden;
  transition:max-height .35s var(--ease), visibility 0s linear .35s;
  background:rgba(26,18,16,.92);
  backdrop-filter:blur(14px) saturate(1.2);
}
.top.is-open .mnav{
  max-height:420px;visibility:visible;
  transition:max-height .35s var(--ease), visibility 0s;
}
.top.is-light .mnav{background:rgba(244,242,238,.98)}
.mnav a{
  display:block;text-decoration:none;color:inherit;
  padding:.9rem var(--gut);font-size:.9375rem;letter-spacing:.04em;
  border-top:1px solid var(--cream-line);
}
.top.is-light .mnav a{border-top-color:var(--line)}
/* Открытая панель на прозрачной шапке висела бы в воздухе: полоса шапки
   обязана взять ту же подложку, что и панель под ней */
.top.is-open:not(.is-light){
  background:rgba(26,18,16,.92);
  backdrop-filter:blur(14px) saturate(1.2);
}

/* Полное меню из шести пунктов вместе со знаком и кнопкой Telegram перестаёт
   помещаться в фиксированную высоту шапки раньше, чем на телефоне, — отсюда
   980, а не 900. Замена появляется только при JS: без скрипта панель
   раскрыть нечем, и меню остаётся на месте, пусть и тесное */
@media (max-width:980px){
  .js .nav{display:none}
  .js .burger{display:inline-flex}
  /* Разреза здесь нет — шапка снова обычная полоса по краям страницы */
  .top__in{
    display:flex;gap:2rem;
    max-width:var(--wide);margin:0 auto;padding-inline:var(--gut);
  }
  .mark{margin-right:auto}
  .top__side{gap:1.25rem;padding-right:0}
}

/* ══ ПЕРВЫЙ ЭКРАН — вариант A: тёмный, фото во всю ширину ═══════════════ */
/* Первый экран разрезан на две зоны: слева плоская тёмная панель с текстом,
   справа фотография во всю высоту. Разрез — общий токен --split, на нём же
   стоит шапка. Строка брендов идёт под обеими зонами и служит им швом */
.hero{
  position:relative;min-height:100vh;min-height:100svh;
  display:grid;
  grid-template-columns:var(--split) 1fr;
  grid-template-rows:1fr auto;
  background:var(--dark);color:var(--cream);
  isolation:isolate;
}
/* Три кадра сменяют друг друга сами. Радиальный градиент остаётся под ними:
   он виден первую долю секунды, пока грузится первый кадр, и подстраховывает,
   если картинка не пришла вовсе */
.hero__photo{
  grid-column:2;grid-row:1;
  position:relative;overflow:hidden;
  background:radial-gradient(92% 74% at 66% 28%, #A98874 0%, #6B5147 44%, #3B2A25 76%, #221816 100%);
}
/* object-position смещён вверх: кадры вертикальные, а первый экран на десктопе
   горизонтальный, и по центру обрезка срезала бы лица */
.hero__photo img{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:50% 28%;
  opacity:0;
  animation:heroCycle 21s var(--ease) infinite;
}
/* Первый кадр непрозрачен и без анимации: так он и выглядит при выключенном
   движении, и не мигает, если анимация ещё не стартовала */
.hero__photo img:nth-child(1){opacity:1}
.hero__photo img:nth-child(2){animation-delay:7s}
.hero__photo img:nth-child(3){animation-delay:14s}
/* На телефоне круг короче: 15 с вместо 21, то есть 5 с на кадр вместо 7.
   Экран меньше, кадр считывается быстрее, и семь секунд там уже тянутся.
   Меняется только длительность — проценты в @keyframes и задержки съезжают
   пропорционально, поэтому переход остаётся плавным (1.3 с вместо 1.8)
   и затухание одного кадра по-прежнему точно совпадает с проявлением
   следующего. Задержки обязаны делить длительность на три, иначе разъедется */
@media (max-width:720px){
  .hero__photo img{animation-duration:15s}
  .hero__photo img:nth-child(2){animation-delay:5s}
  .hero__photo img:nth-child(3){animation-delay:10s}
}
/* Затемнения на десктопе нет вовсе: текст живёт на своей тёмной панели, и
   гасить ради него фотографию больше незачем — кадр идёт в полную силу.
   Слой возвращается там, где разрез пропадает и текст снова ложится
   поверх снимка, то есть на 980 px и уже */
.hero__photo::after{content:none}
.hero__in{
  grid-column:1;grid-row:1;
  display:flex;flex-direction:column;justify-content:flex-end;
  padding:calc(var(--head) + 2rem) clamp(1.5rem,2.2vw,2.5rem) clamp(2.5rem,6vw,4.5rem);
}
/* Кегль заголовка считается от ширины панели, а не экрана: 9.4vw рассчитаны
   на всю ширину, и в зоне на 41.5 % «Вы себя» вылезло бы за разрез */
.hero h1{
  font-size:clamp(2.875rem,6.4vw,6.75rem);
  line-height:1.0;letter-spacing:-.03em;
}
/* Ниже 980 разреза нет: кадр возвращается на всю ширину и уходит под текст,
   поверх него — затемнение, иначе кремовые буквы на светлом снимке пропадут.
   Композиция ровно та, что была до раздельной раскладки.

   Блок обязан стоять ПОСЛЕ десктопных правил выше: вес у селекторов
   одинаковый, медиазапрос его не добавляет, и решает порядок в файле.
   Стоял выше — и весь перебивался, вместе с затемнением и кеглем */
@media (max-width:980px){
  .hero{display:flex;flex-direction:column}
  .hero__photo{position:absolute;inset:0;z-index:-1}
  .hero__photo::after{
    content:'';position:absolute;inset:0;
    background:linear-gradient(to top, rgba(26,18,16,.90) 0%, rgba(26,18,16,.52) 34%, rgba(26,18,16,.14) 72%, rgba(26,18,16,.30) 100%);
  }
  .hero__in{
    flex:1;max-width:var(--wide);width:100%;margin:0 auto;
    padding:calc(var(--head) + 2rem) var(--gut) clamp(2.5rem,6vw,4.5rem);
  }
  .hero h1{font-size:clamp(2.875rem,9.4vw,7.5rem)}
}
/* overflow:hidden нужен для въезда строки снизу, но он же срезает выносные
   элементы кириллицы — «у», «д», «з». Padding расширяет маску вниз,
   отрицательный margin возвращает исходную высоту блока */
.hero h1 .ln{display:block;overflow:hidden;padding-bottom:.22em;margin-bottom:-.16em}
.hero h1 .ln > span{display:block}
.hero h1 em{font-style:italic;font-weight:500;color:var(--accent-lift)}

.hero__lead{
  /* курсивный хвост «у» в «узнаете» съедает верхний отступ — берём с запасом */
  margin-top:clamp(2.25rem,4vw,3.25rem);
  max-width:31ch;color:var(--cream-soft);
  font-size:clamp(1rem,1.7vw,1.1875rem);line-height:1.72;
}
.hero__row{
  margin-top:clamp(2rem,4vw,2.75rem);
  display:flex;flex-wrap:wrap;align-items:center;gap:1.25rem 2rem;
}
.hero__geo{color:var(--cream-dim);letter-spacing:.16em}

/* Строка брендов — шов между тёмной обложкой и светлым разворотом.
   Названия набраны текстом, без фирменных логотипов (brief.md §7) */
.hero__brands{
  grid-column:1/-1;grid-row:2;
  position:relative;border-top:1px solid var(--cream-line);
  max-width:var(--wide);width:100%;margin:0 auto;
  padding:1.25rem var(--gut);
  display:flex;align-items:baseline;gap:1.75rem;
  color:var(--cream-dim);
}
.hero__brands b{color:var(--accent-lift);font-weight:500;flex:none}
/* Бегущая строка брендов. Рамка режет ленту по краям, дорожка внутри едет
   влево ровно на половину своей ширины — там стоит вторая копия списка,
   и кадр совпадает с исходным. min-width:0 обязателен: без него флекс-элемент
   не даёт себя сжать, лента распирает строку и обрезать нечего */
.brands{flex:1;min-width:0;overflow:hidden}
.brands__track{display:flex;width:max-content;animation:brandsMarquee 26s linear infinite}
.brands__row{display:flex;flex:none}
/* Шаг между брендами — отступ у каждого, а не gap дорожки: gap не ставится
   после последнего в копии, на стыке шаг вышел бы короче и лента дёргалась
   бы раз в цикл */
.brands__row > span{margin-right:1.75rem;white-space:nowrap}

/* ── КНОПКИ ────────────────────────────────────────────────────────────── */
.btn{
  display:inline-flex;align-items:center;gap:.7rem;
  font-family:var(--f-body);font-size:.75rem;font-weight:500;
  letter-spacing:.14em;text-transform:uppercase;text-decoration:none;
  padding:1.0625rem 2.125rem;border-radius:var(--btn-round);
  /* overflow:hidden здесь не только ради ::before — он же обрезает наезжающий
     слой по скруглению, иначе тёмная заливка вылезет за углы */
  position:relative;overflow:hidden;
  border:1px solid var(--accent);background:var(--accent);color:#fff;
  transition:border-color .45s var(--ease);
}
.btn::before{
  content:'';position:absolute;inset:0;background:var(--ink);
  transform:translateY(101%);transition:transform .45s var(--ease);
}
.btn span{position:relative}
.btn:hover{border-color:var(--ink)}
.btn:hover::before{transform:translateY(0)}
/* На тёмном первом экране кнопка светлее фона, а не темнее */
.btn--onDark{border-color:var(--accent-lift);background:var(--accent-lift);color:#221816}
.btn--onDark::before{background:var(--cream)}
.btn--onDark:hover{border-color:var(--cream)}

.link{
  display:inline-block;text-decoration:none;color:var(--accent);
  font-size:.875rem;font-weight:500;letter-spacing:.02em;
  position:relative;padding-bottom:.25rem;
}
.link::after{
  content:'';position:absolute;left:0;bottom:0;height:1px;width:100%;
  background:currentColor;transform:scaleX(0);transform-origin:left;
  transition:transform .45s var(--ease);
}
.link:hover::after{transform:scaleX(1)}
.link .arw{display:inline-block;transition:transform .45s var(--ease)}
.link:hover .arw{transform:translateX(5px)}

/* ── СЕКЦИЯ: редакционная левая колонка-колонтитул ─────────────────────── */
.sec{padding-block:var(--sec)}
.sec + .sec{padding-top:0}
.sec__grid{
  display:grid;
  grid-template-columns:minmax(140px,190px) minmax(0,1fr);
  gap:clamp(1.75rem,4vw,4rem);
}
.sec__aside{position:sticky;top:calc(var(--head) + 1.5rem);align-self:start}
.sec__aside .micro{color:var(--accent)}
.sec__aside p{margin-top:.75rem;font-size:.8125rem;line-height:1.7;color:var(--ink-soft)}
@media (max-width:860px){
  .sec__grid{grid-template-columns:1fr;gap:1.25rem}
  .sec__aside{position:static}
  .sec__aside p{display:none}
}
.sec h2{font-size:clamp(2.125rem,5.2vw,3.875rem);line-height:1.08;max-width:17ch}
.sec h2 em{font-style:italic;color:var(--accent)}
.sec__intro{
  margin-top:1.5rem;max-width:52ch;color:var(--ink-soft);
  font-size:1.0625rem;line-height:1.78;
}

/* ── ПОРТФОЛИО: табы на :checked, без JS ───────────────────────────────── */
.tabs{margin-top:clamp(2.5rem,5vw,3.75rem);position:relative}
.tabs input{position:absolute;opacity:0;pointer-events:none;width:1px;height:1px}
.tabs__bar{
  display:flex;flex-wrap:wrap;align-items:flex-end;gap:0 2.25rem;
  border-bottom:1px solid var(--line);
}
.tabs__bar label{
  cursor:pointer;color:var(--ink-soft);
  font-family:var(--f-display);font-size:clamp(1rem,2.1vw,1.375rem);
  position:relative;padding-bottom:1rem;
  transition:color .35s var(--ease);
}
.tabs__bar label::after{
  content:'';position:absolute;left:0;right:0;bottom:-1px;height:1px;
  background:var(--accent);transform:scaleX(0);transform-origin:left;
  transition:transform .45s var(--ease);
}
.tabs__bar label:hover{color:var(--ink)}
/* Инпуты стоят перед .tabs__bar, поэтому фокус ловится общим братом, а не «+» */
#cat-1:focus-visible ~ .tabs__bar label[for="cat-1"],
#cat-2:focus-visible ~ .tabs__bar label[for="cat-2"],
#cat-3:focus-visible ~ .tabs__bar label[for="cat-3"],
#cat-4:focus-visible ~ .tabs__bar label[for="cat-4"]{outline:2px solid var(--accent);outline-offset:4px}
.tabs__panel{display:none;padding-top:clamp(2rem,4vw,3rem)}
#cat-1:checked ~ .tabs__bar label[for="cat-1"],
#cat-2:checked ~ .tabs__bar label[for="cat-2"],
#cat-3:checked ~ .tabs__bar label[for="cat-3"],
#cat-4:checked ~ .tabs__bar label[for="cat-4"]{color:var(--ink)}
#cat-1:checked ~ .tabs__bar label[for="cat-1"]::after,
#cat-2:checked ~ .tabs__bar label[for="cat-2"]::after,
#cat-3:checked ~ .tabs__bar label[for="cat-3"]::after,
#cat-4:checked ~ .tabs__bar label[for="cat-4"]::after{transform:scaleX(1)}
#cat-1:checked ~ #panel-1,
#cat-2:checked ~ #panel-2,
#cat-3:checked ~ #panel-3,
#cat-4:checked ~ #panel-4{display:block;animation:panelIn .55s var(--ease) both}
@keyframes panelIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@media (max-width:560px){
  .tabs__bar{gap:0 1.125rem}
  .tabs__bar label{font-size:.9375rem}
}
@media (max-width:380px){
  .tabs__bar{gap:0 .875rem}
  .tabs__bar label{font-size:.875rem}
}

/* ── «ПОКАЗАТЬ ЕЩЁ» ────────────────────────────────────────────────────
   Карточки сверх первой порции лежат в разметке, а не подгружаются
   скриптом. Две причины: робот видит все работы — иначе смысл раздела
   для поиска теряется; а loading="lazy" не даёт браузеру качать скрытые
   изображения, поэтому вес первой загрузки от них не растёт */
/* Специфичность здесь не украшение: одиночный .is-hidden (0,1,0) равен
   .work{display:block} ниже по файлу, и при равенстве побеждает последнее
   правило — карточки оставались видимыми. Селектор с родителем (0,2,0)
   выигрывает независимо от порядка правил */
.works > .is-hidden,
.proj > .is-hidden{display:none}
.more-row{margin-top:clamp(1.75rem,3.5vw,2.5rem)}
/* Без JS кнопки нет: мёртвая кнопка хуже её отсутствия.
   Видны первые шесть работ, страница остаётся полной для робота */
.more{display:none}
.js .more{
  display:inline-flex;align-items:center;gap:.6rem;
  font-family:var(--f-body);font-size:.75rem;font-weight:500;
  letter-spacing:.14em;text-transform:uppercase;
  padding:.9375rem 2rem;cursor:pointer;border-radius:var(--btn-round);
  background:transparent;color:var(--ink);border:1px solid var(--line);
  transition:border-color .35s var(--ease), color .35s var(--ease);
}
.js .more:hover{border-color:var(--accent);color:var(--accent)}
.more[hidden]{display:none}

.works{display:grid;gap:clamp(1rem,2.2vw,1.75rem);grid-template-columns:repeat(3,1fr)}
@media (max-width:860px){ .works{grid-template-columns:repeat(2,1fr)} }
@media (max-width:520px){ .works{grid-template-columns:1fr} }
.work{display:block;text-decoration:none;margin:0}
.work__media{overflow:hidden;background:var(--paper-deep)}
/* Заглушка и настоящий кадр живут в одной рамке 3:4: пока заменены не все
   карточки, сетка не должна прыгать. object-fit добирает те файлы, что
   пришли не ровно 3:4 — кадрируется по центру, а не тянется. */
.work__media .ph,
.work__media img{aspect-ratio:3/4;width:100%;height:auto;object-fit:cover;transition:transform .8s var(--ease)}
.work:hover .work__media .ph,
.work:hover .work__media img{transform:scale(1.035)}
.work figcaption{margin-top:.875rem;font-size:.875rem;line-height:1.55}
.work .cred{display:block;margin-top:.3rem;color:var(--ink-soft);font-size:.75rem;letter-spacing:.04em}

/* Съёмки поданы проектами, а не папкой фото (приём EvaGher, research §1.5) */
.proj{display:grid;gap:clamp(1.5rem,3vw,2.5rem)}
.proj__row{
  display:grid;grid-template-columns:minmax(0,.85fr) minmax(0,1.15fr);
  gap:clamp(1.25rem,3vw,2.5rem);align-items:center;
  padding-bottom:clamp(1.5rem,3vw,2.5rem);border-bottom:1px solid var(--line);
}
.proj__row:last-child{border-bottom:0;padding-bottom:0}
.proj__row .ph{aspect-ratio:4/3}
/* nowrap на элементах: их стало три, и на узком экране «месяц, год»
   разрывалось посреди себя, а не по границе между полями */
.proj__meta{display:flex;flex-wrap:wrap;gap:.5rem 1.25rem;color:var(--accent)}
.proj__meta span{white-space:nowrap}
.proj__row h3{margin-top:.75rem;font-size:clamp(1.5rem,3vw,2.25rem)}
.proj__row p{margin-top:.75rem;color:var(--ink-soft);max-width:46ch;font-size:.9375rem;line-height:1.72}
@media (max-width:720px){ .proj__row{grid-template-columns:1fr} }

/* ── Кадры съёмки: баннер на месте одной фотографии ────────────────────
   В рамке всегда один кадр. Листается скроллом или свайпом, встаёт по месту
   благодаря scroll-snap, доступен с клавиатуры стрелками через tabindex.
   Своего JS блок не стоит ни строчки.

   Кружочки под рамкой — обычные ссылки на кадры. Они делают две вещи сразу:
   показывают, сколько кадров в съёмке, и переключают на нужный по клику.
   Без них у баннера нет ни счётчика, ни способа листать мышью: колесо
   прокручивает страницу, а не рамку.

   Рамка одна на все кадры съёмки, поэтому object-fit:contain, а не cover.
   В одной съёмке лежат и вертикальные портреты, и готовые развороты каталога
   с подписями и артикулами по краям — cover срезал бы у разворотов ровно
   подписи. Contain оставляет поля, зато не режет содержимое. */
.shoot{min-width:0}
.shoot__frame{
  display:flex;overflow-x:auto;overscroll-behavior-x:contain;
  scroll-snap-type:x mandatory;
  background:var(--paper-lift);
  scrollbar-width:none;
}
.shoot__frame::-webkit-scrollbar{display:none}
.shoot__frame:focus-visible{outline:2px solid var(--accent);outline-offset:4px}
/* Курсор — единственное, что подсказывает мышью, что рамку можно тянуть.
   Класс is-dragging вешает скрипт на время перетаскивания */
.shoot__frame{cursor:grab}
.shoot__frame.is-dragging{cursor:grabbing;user-select:none}
/* Глобальный scroll-margin-top для [id] здесь нужен и не отключается: в
   запасном варианте кружочки — якорные ссылки, а переход по якорю ставит цель
   к верхнему краю экрана. Без отступа выбранный кадр уехал бы под шапку. */
.shot{flex:0 0 100%;margin:0;scroll-snap-align:center}
.shot img{width:100%;aspect-ratio:3/4;object-fit:contain;background:var(--paper-lift)}

.shoot__dots{display:flex;justify-content:center;flex-wrap:wrap;margin-top:.875rem}
/* Кружок рисуется псевдоэлементом, а сама ссылка держит область нажатия:
   восьмипиксельная точка пальцем не берётся */
.shoot__dots a{
  display:grid;place-items:center;width:1.75rem;height:1.75rem;
  text-decoration:none;
}
.shoot__dots a::before{
  content:'';width:.5rem;height:.5rem;border-radius:50%;
  background:color-mix(in srgb, var(--ink-soft) 32%, transparent);
  transition:background .3s var(--ease), transform .3s var(--ease);
}
.shoot__dots a:hover::before{background:var(--accent);transform:scale(1.3)}

/* Где браузер умеет маркеры прокрутки — отдаём кружочки ему. Разница одна,
   но существенная: маркер знает, какой кадр сейчас в рамке, и подсвечивает
   свою точку. Ссылками вручную это не сделать — они не отслеживают позицию.
   Ручные кружочки при этом остаются в разметке и работают там, где маркеров
   ещё нет; здесь они просто прячутся, чтобы не задвоиться. */
@supports (scroll-marker-group: after){
  .shoot__dots{display:none}
  .shoot__frame{scroll-marker-group:after}
  .shoot__frame::scroll-marker-group{
    display:flex;justify-content:center;flex-wrap:wrap;margin-top:.875rem;
  }
  .shot::scroll-marker{
    content:'';width:.5rem;height:.5rem;border-radius:50%;margin:.625rem;
    background:color-mix(in srgb, var(--ink-soft) 32%, transparent);
    transition:background .3s var(--ease), transform .3s var(--ease);
  }
  .shot::scroll-marker:hover{background:var(--accent)}
  .shot::scroll-marker:target-current{background:var(--accent);transform:scale(1.3)}
}

.cta-row{margin-top:clamp(2rem,4vw,3rem)}

/* ── ПРАЙС: сигнатурный блок страницы ──────────────────────────────────
   Цены набраны антиквой в заголовочном кегле. Причина не декоративная:
   8 000 ₽ — нижняя граница московского коридора (research §2.6), и цифра
   должна читаться как уверенность, а не как уровень мастера (brief §8) */
.price{margin-top:clamp(2.5rem,5vw,3.75rem);border-top:1px solid var(--ink)}
.price__row{
  display:grid;grid-template-columns:minmax(0,1fr) auto;
  gap:.5rem clamp(1.5rem,4vw,3rem);align-items:baseline;
  padding-block:clamp(1.5rem,3vw,2.125rem);
  border-bottom:1px solid var(--line);
}
.price__name{font-family:var(--f-display);font-size:clamp(1.375rem,3.2vw,2.125rem);line-height:1.16}
.price__what{
  grid-column:1;margin-top:.5rem;max-width:44ch;
  color:var(--ink-soft);font-size:.9375rem;line-height:1.7;
}
.price__val{
  font-family:var(--f-display);font-size:clamp(1.75rem,4.4vw,3.125rem);
  line-height:1;white-space:nowrap;letter-spacing:-.02em;
  grid-column:2;grid-row:1;
}
/* Подсветка строки при наведении. Только там, где есть настоящий курсор:
   на тач-экране :hover залипает после тапа, и строка осталась бы подсвеченной
   до следующего касания в другом месте. Подсветка идёт вровень с текстом —
   внутренних полей у ряда нет, и добавлять их нельзя: они сдвинули бы
   названия и цены вправо относительно остальной страницы */
@media (hover:hover){
  .price__row{transition:background .3s var(--ease)}
  .price__row:hover{background:var(--paper-lift)}
}

/* На узком экране цена уходит под название, а не сжимает его в столбик */
@media (max-width:560px){
  .price__row{grid-template-columns:1fr}
  .price__val{grid-column:1;grid-row:auto;order:2;color:var(--accent)}
  .price__what{order:3;margin-top:.75rem}
  .price__add{order:4}
}
/* Наценки — подстроками того же ряда: видно, что это добавка к цене
   выше, а не отдельный скрытый платёж (research §2.7, п.4) */
.price__add{
  grid-column:1/-1;margin-top:1.125rem;
  display:flex;flex-wrap:wrap;gap:.6rem 2rem;
  padding-top:1.125rem;border-top:1px dashed var(--line);
}
.price__add div{display:flex;align-items:baseline;gap:.7rem;color:var(--ink-soft);font-size:.9375rem}
.price__add b{
  font-family:var(--f-display);font-weight:500;color:var(--accent);
  font-size:1.125rem;white-space:nowrap;
}

/* «Всё включено» — обязательный сосед прайса (brief §8) */
.included{
  margin-top:clamp(2rem,4vw,3rem);padding:clamp(1.5rem,3.5vw,2.75rem);
  background:var(--paper-lift);border-left:2px solid var(--accent);
}
.included h3{font-size:clamp(1.375rem,2.8vw,1.875rem);max-width:20ch}
.included p{margin-top:1rem;color:var(--ink-soft);max-width:56ch;line-height:1.78}
.included ul{
  margin-top:1.25rem;display:flex;flex-wrap:wrap;gap:.6rem 1.75rem;font-size:.9375rem;
}
.included li::before{content:'—';color:var(--accent);margin-right:.55rem}

/* Смена «по запросу» — с объяснением, не голое «цены по запросу»
   (research §1.6, п.4: без объяснения так не делает никто из премиума) */
.onreq{
  margin-top:clamp(1.5rem,3vw,2rem);padding:clamp(1.5rem,3.5vw,2.75rem);
  border:1px solid var(--line);
}
.onreq h3{font-size:clamp(1.25rem,2.6vw,1.75rem)}
.onreq p{margin-top:1rem;color:var(--ink-soft);max-width:58ch;line-height:1.78}
.onreq .link{margin-top:1.5rem}

/* ── ОБУЧЕНИЕ: лестница форматов ───────────────────────────────────────── */
.learn{margin-top:clamp(2.5rem,5vw,3.75rem);display:grid;gap:clamp(1rem,2.2vw,1.5rem);grid-template-columns:repeat(3,1fr)}
@media (max-width:860px){ .learn{grid-template-columns:1fr} }
.lcard{
  display:flex;flex-direction:column;
  padding:clamp(1.5rem,3vw,2.25rem);background:var(--paper-lift);
  border-top:2px solid var(--line);
  transition:border-color .45s var(--ease), transform .45s var(--ease);
}
.lcard:hover{border-top-color:var(--accent);transform:translateY(-4px)}
.lcard .micro{color:var(--accent)}
.lcard h3{margin-top:1rem;font-size:clamp(1.375rem,2.6vw,1.75rem);max-width:14ch}
.lcard p{margin-top:.875rem;color:var(--ink-soft);font-size:.9375rem;line-height:1.72;flex:1}
.lcard .lp{font-family:var(--f-display);font-size:clamp(1.75rem,3.4vw,2.375rem);margin-top:1.75rem;line-height:1}
.lcard .link{margin-top:1.25rem;align-self:start}

/* ── ОБО МНЕ ───────────────────────────────────────────────────────────── */
.about__grid{
  margin-top:clamp(2.5rem,5vw,3.5rem);
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.72fr);
  gap:clamp(2rem,4vw,3.5rem);align-items:start;
}
@media (max-width:860px){ .about__grid{grid-template-columns:1fr} }
.about__text p{margin-top:1.5rem;max-width:56ch;line-height:1.85}
.about__text p:first-child{margin-top:0}
.about__text .big{
  font-family:var(--f-display);font-size:clamp(1.4375rem,3vw,2rem);
  line-height:1.32;max-width:23ch;
}
.about__figure .ph,
.about__figure img{aspect-ratio:4/5;width:100%;height:auto;object-fit:cover;display:block}
/* Портрет снят вертикальнее рамки, кроп по центру срезал бы макушку —
   сдвигаем видимую часть вверх */
.about__figure img{object-position:50% 22%}
.facts{
  margin-top:clamp(2.5rem,5vw,3.5rem);display:grid;
  grid-template-columns:repeat(3,1fr);gap:1.5rem;
  border-top:1px solid var(--line);padding-top:clamp(1.5rem,3vw,2.25rem);
}
@media (max-width:640px){ .facts{grid-template-columns:1fr;gap:1.25rem} }
.facts b{display:block;font-family:var(--f-display);font-weight:500;font-size:clamp(1.75rem,3.6vw,2.5rem);line-height:1}
/* Подпись — только прямой потомок ячейки. `.facts span` цеплял и число внутри
   .facts b: цифра садилась на .875rem, крупным оставался один знак «+» */
.facts > div > span{display:block;margin-top:.5rem;color:var(--ink-soft);font-size:.875rem;line-height:1.6;max-width:26ch}
/* Число: ширину на время отсчёта придерживает скрипт, разряды — табличные */
.facts .fact__n{display:inline-block;font-variant-numeric:tabular-nums}

/* ── КАК ЭТО ПРОИСХОДИТ ────────────────────────────────────────────────
   Единственная секция с нумерацией: здесь порядок несёт смысл */
.steps{margin-top:clamp(2.5rem,5vw,3.75rem);border-top:1px solid var(--line)}
.step{
  display:grid;grid-template-columns:auto minmax(0,1fr);
  gap:clamp(1.25rem,3vw,2.5rem);align-items:start;
  padding-block:clamp(1.5rem,3vw,2rem);border-bottom:1px solid var(--line);
}
.step__n{
  font-family:var(--f-display);font-style:italic;color:var(--accent);
  font-size:clamp(1.125rem,2.2vw,1.5rem);line-height:1.2;min-width:2.5ch;
}
.step h3{font-size:clamp(1.125rem,2.4vw,1.5rem);line-height:1.3}
.step p{margin-top:.625rem;color:var(--ink-soft);max-width:56ch;font-size:.9375rem;line-height:1.75}

/* ── ОТЗЫВЫ ────────────────────────────────────────────────────────────── */
.revs{margin-top:clamp(2.5rem,5vw,3.5rem);display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(1rem,2.2vw,1.5rem)}
@media (max-width:760px){ .revs{grid-template-columns:1fr} }
.rev{padding:clamp(1.5rem,3vw,2.25rem);background:var(--paper-lift);margin:0}
.rev blockquote{margin:0;font-family:var(--f-display);font-size:clamp(1.125rem,2.2vw,1.4375rem);line-height:1.45}
.rev figcaption{margin-top:1.25rem;color:var(--ink-soft);font-size:.8125rem;letter-spacing:.06em}
.rev--todo{border:1px dashed var(--accent);background:transparent}
.rev--todo blockquote{color:var(--ink-soft);font-style:italic}

/* ── СТУДИЯ ────────────────────────────────────────────────────────────── */
.studio__grid{
  margin-top:clamp(2.5rem,5vw,3.5rem);display:grid;
  grid-template-columns:minmax(0,.85fr) minmax(0,1.15fr);
  gap:clamp(2rem,4vw,3.5rem);align-items:start;
}
@media (max-width:860px){ .studio__grid{grid-template-columns:1fr} }
.studio__text p{margin-top:1.25rem;color:var(--ink-soft);max-width:48ch;line-height:1.8}
.studio__text p:first-child{margin-top:0;color:var(--ink)}
.studio__addr{
  margin-top:1.75rem;padding-top:1.75rem;border-top:1px solid var(--line);
  display:grid;gap:1rem;
}
.studio__addr div span{display:block;color:var(--accent);margin-bottom:.3rem}
.studio__addr a{text-decoration:none;border-bottom:1px solid var(--line);transition:border-color .3s var(--ease)}
.studio__addr a:hover{border-color:var(--accent)}
.studio__map .ph{aspect-ratio:16/11}

/* ── FAQ ───────────────────────────────────────────────────────────────── */
.faq{margin-top:clamp(2.5rem,5vw,3.5rem);border-top:1px solid var(--line);max-width:60rem}
.faq details{border-bottom:1px solid var(--line)}
.faq summary{
  cursor:pointer;list-style:none;padding-block:clamp(1.125rem,2.4vw,1.5rem);
  display:flex;gap:1.5rem;align-items:baseline;justify-content:space-between;
  font-family:var(--f-display);font-size:clamp(1.0625rem,2.2vw,1.375rem);
  line-height:1.38;transition:color .3s var(--ease);
}
.faq summary::-webkit-details-marker{display:none}
.faq summary:hover{color:var(--accent)}
.faq summary .sign{flex:none;width:1rem;height:1rem;position:relative;translate:0 -.15em}
.faq summary .sign::before,
.faq summary .sign::after{
  content:'';position:absolute;left:0;top:50%;width:100%;height:1px;background:currentColor;
  transition:transform .4s var(--ease);
}
.faq summary .sign::after{transform:rotate(90deg)}
.faq details[open] summary .sign::after{transform:rotate(0)}
.faq details[open] summary{color:var(--accent)}
.faq__a{padding-bottom:1.5rem;max-width:58ch;color:var(--ink-soft);line-height:1.8}
.faq__a p + p{margin-top:.875rem}
.todo{color:var(--accent);font-size:.8125rem;letter-spacing:.06em}

/* ── ПОДВАЛ: тем же тоном, что первый экран — тёмное начало, тёмный конец ─ */
.foot{background:var(--dark);color:var(--cream);padding-block:clamp(3rem,7vw,5.5rem)}
.foot__grid{display:grid;grid-template-columns:minmax(0,1.2fr) repeat(2,minmax(0,1fr));gap:clamp(2rem,4vw,3rem)}
@media (max-width:860px){ .foot__grid{grid-template-columns:1fr 1fr} }
@media (max-width:560px){ .foot__grid{grid-template-columns:1fr} }
.foot .mark{display:inline-block;margin:0 0 1.25rem}
.foot__claim{color:var(--cream-soft);max-width:26ch;font-size:.9375rem;line-height:1.7}
.foot h4{
  font-family:var(--f-body);font-size:.6875rem;letter-spacing:.2em;
  text-transform:uppercase;font-weight:500;color:var(--accent-lift);
}
.foot ul{margin-top:1.125rem;display:grid;gap:.7rem}
.foot a{text-decoration:none;font-size:.9375rem;color:var(--cream-soft);transition:color .3s var(--ease)}
.foot a:hover{color:var(--cream)}
.foot__bottom{
  margin-top:clamp(2.5rem,5vw,4rem);padding-top:1.5rem;
  border-top:1px solid var(--cream-line);
  display:flex;flex-wrap:wrap;gap:.75rem 2rem;justify-content:space-between;
  color:var(--cream-dim);font-size:.75rem;letter-spacing:.05em;
}

/* ── СКВОЗНАЯ ПЛАВАЮЩАЯ КНОПКА ─────────────────────────────────────────── */
.float{
  position:fixed;right:clamp(1rem,3vw,2rem);bottom:clamp(1rem,3vw,2rem);z-index:70;
  display:inline-flex;align-items:center;gap:.6rem;
  padding:.9rem 1.375rem;border-radius:var(--btn-round);text-decoration:none;
  background:var(--ink);color:var(--paper);
  font-size:.75rem;font-weight:500;letter-spacing:.12em;text-transform:uppercase;
  box-shadow:0 12px 36px -16px rgba(35,29,27,.7);
  opacity:0;transform:translateY(14px);pointer-events:none;
  transition:opacity .5s var(--ease), transform .5s var(--ease), background .35s var(--ease);
}
.float.is-on{opacity:1;transform:none;pointer-events:auto}
.float:hover{background:var(--accent)}
.float svg{flex:none}
@media (max-width:520px){ .float{padding:.8rem 1.125rem;font-size:.6875rem} }

/* ── ЗАГЛУШКИ ФОТО ─────────────────────────────────────────────────────── */
.ph{
  position:relative;width:100%;
  background:linear-gradient(158deg,#E6DFD6,#CDC1B5 58%,#AC9C8D);
  display:grid;place-items:center;
}
.ph span{
  font-size:.625rem;letter-spacing:.18em;text-transform:uppercase;
  color:rgba(35,29,27,.42);text-align:center;padding:1.25rem;line-height:1.7;
}

/* ── ЛАЙТБОКС ──────────────────────────────────────────────────────────
   Курсор — единственная подсказка, что кадр открывается: рамка и подпись
   остаются как были, чтобы сетка не превратилась в набор кнопок.
   Ставится только при JS: без него открывать нечего, и лупа обманывала бы */
.js .work__media img{cursor:zoom-in}
.lb{
  position:fixed;inset:0;z-index:90;
  background:rgba(26,18,16,.92);
  display:grid;place-items:center;
  cursor:zoom-out;
}
.lb[hidden]{display:none}
/* Кадр вписывается в экран целиком: object-fit добирает те файлы, что
   пришли не в ту сторону, — вертикальный снимок на горизонтальном экране */
.lb img{max-width:92vw;max-height:92vh;width:auto;height:auto;object-fit:contain}
.lb__close{
  position:absolute;top:clamp(.75rem,2vw,1.5rem);right:clamp(.75rem,2vw,1.5rem);
  width:2.75rem;height:2.75rem;
  display:grid;place-items:center;
  background:none;border:1px solid var(--cream-line);border-radius:var(--btn-round);
  color:var(--cream);font-size:1.5rem;line-height:1;cursor:pointer;
  transition:border-color .3s var(--ease)}
.lb__close:hover{border-color:var(--cream)}

/* ── ДВИЖЕНИЕ ──────────────────────────────────────────────────────────
   Первый экран — одна срежиссированная сцена на CSS (работает без JS).
   Дальше по странице — один и тот же тихий приём, без разнобоя */
@keyframes rise{from{transform:translateY(105%)}to{transform:translateY(0)}}
@keyframes fade{from{opacity:0}to{opacity:1}}
@keyframes scrim{from{opacity:0;transform:scale(1.05)}to{opacity:1;transform:none}}
/* Половина ширины дорожки — это ровно одна копия списка брендов.
   Доехав до неё, лента возвращается в начало, и кадр совпадает сам с собой */
@keyframes brandsMarquee{from{transform:translateX(0)}to{transform:translateX(-50%)}}
/* Смена кадров первого экрана. Цикл 21 с на три кадра: семь секунд на каждый,
   из них 1.8 с уходит на переход. Проценты посчитаны от этих секунд:
   1.8/21 = 8.6 %, 7/21 = 33.3 %. Слои сдвинуты задержками 0 / 7 / 14 с,
   поэтому затухание одного точно совпадает с проявлением следующего */
@keyframes heroCycle{
  0%    {opacity:0}
  8.6%  {opacity:1}
  33.3% {opacity:1}
  41.9% {opacity:0}
  100%  {opacity:0}
}

.hero__photo{animation:scrim 1.5s var(--ease) both}
.hero h1 .ln > span{animation:rise 1s var(--ease) both}
.hero h1 .ln:nth-child(1) > span{animation-delay:.28s}
.hero h1 .ln:nth-child(2) > span{animation-delay:.38s}
.hero__lead{animation:fade .9s var(--ease) .66s both}
.hero__row{animation:fade .9s var(--ease) .8s both}
.hero__brands{animation:fade .9s var(--ease) .96s both}

.js .rv{opacity:0;transform:translateY(18px)}
.js .rv.is-in{opacity:1;transform:none;transition:opacity .9s var(--ease), transform .9s var(--ease)}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation:none!important;transition-duration:.01ms!important}
  .js .rv{opacity:1;transform:none}
  /* Остановленная лента показала бы четыре бренда из семи, остальные под
     обрезкой. Возвращаем строке исходный вид: переносится, копия убрана */
  .brands{overflow:visible}
  .brands__track{flex-wrap:wrap;width:auto}
  .brands__row{flex-wrap:wrap}
  .brands__row[aria-hidden]{display:none}
}
