/* ============================================================
   NUMO — Alen Troyan portfolio
   Монохром + шрифт-гигант + три «дорогих» момента.
   ============================================================ */

/* ---------- 1. TOKENS ---------- */
:root {
  /* цвета */
  --c-bg:        #ffffff;
  --c-bg-dark:   #0e0e0e;
  --c-text:      #1A202C;
  --c-black:     #000000;
  --c-line:      rgba(0,0,0,0.08);
  --c-muted-36:  rgba(0,0,0,0.36);
  --c-muted-48:  rgba(0,0,0,0.48);
  --c-muted-64:  rgba(0,0,0,0.64);
  --c-label:     rgba(0,0,0,0.6);   /* WCAG-AA-совместимый оттенок для мелкого текста (kicker/год/тултип/панель) */
  --c-w-line-08: rgba(255,255,255,0.08);
  --c-w-line-16: rgba(255,255,255,0.16);
  --c-w-36:      rgba(255,255,255,0.36);
  --c-w-48:      rgba(255,255,255,0.48);
  --c-w-64:      rgba(255,255,255,0.64);
  --c-accent:       #38A169;
  --c-accent-pulse: rgba(34,197,94,0.7);

  /* шрифты */
  --f-display: 'Six Caps', 'Oswald', sans-serif;   /* латиница → Six Caps (узкий). Кириллица (RU CTA «Связаться», RU-фразы лоадера) per-glyph падает в Oswald — узкий display-шрифт С кириллицей (Saira Extra Condensed кириллицы НЕ имеет → падало в системный широкий sans-serif) */
  --f-logo:    'Saira Extra Condensed', sans-serif;   /* ЛОГОТИП — ультра-condensed heavy (Saira Extra Condensed 900). */
  --f-body:    'Switzer', 'Inter Tight', system-ui, sans-serif;

  /* типо-шкала */
  --fs-hero-line: max(2.25rem, min((100svh - 300px) / 3, 42vw));   /* svh (НЕ dvh!): на телефоне dvh меняется при прятании адресной строки → шрифт маркизы прыгал в размере при скролле. svh стабилен → размер константный, никаких рывков. floor 2.25rem от схлопывания, 42vw-кап от раздувания одной буквы */
  --fs-mega:      clamp(2.25rem, min(18vw, 26vh), 17.5rem);   /* floor опущен 4.5→2.25rem: на телефонах ≤400px CTA «Связаться»/«GET IN TOUCH» ужимается и не даёт горизонтальный скролл; десктоп CTA независим */
  --fs-h-project: clamp(3rem, 10vw, 8.75rem);
  --fs-h-section: clamp(2rem, 6vw + 1rem, 6rem);
  --fs-h-service: clamp(2rem, 8vw, 6.5rem);
  --fs-loader-word: clamp(3rem, 5vw, 4.375rem);
  --fs-quote:     clamp(1.375rem, 2.2vw + 0.75rem, 3rem);
  --fs-lead:      clamp(0.875rem, 7vw, 2.5rem);
  --fs-email:     clamp(1.25rem, 3vw, 2.5rem);
  --fs-body-lg:   clamp(1rem, 2vw, 1.375rem);
  --fs-base: 1rem;
  --fs-sm: 0.875rem;
  --fs-xs: 0.75rem;

  /* трекинг */
  --ls-kicker: 0.2em;
  --ls-caps-sm: 0.08em;
  --ls-tight: -0.02em;
  --ls-tighter: -0.025em;

  /* сетка */
  --container-max: 1920px;
  --pad-x: clamp(0.9rem, 2.23vw, 44px);   /* был чистый 2.23vw → ~4.5px на 200px (контент впритык к краю). clamp даёт читаемый ~14px отступ на телефонах, кап 44px на больших */
  --header-h-m: 112px;
  --header-h-d: 160px;
  --section-gap-m: 11.75rem;
  --section-gap-d: 14.5rem;
  --gap-inner-m: 2.5rem;
  --gap-inner-d: 4rem;

  /* сетка кейс-страниц — собранная колонка + плотный ритм (не наследуют
     гигантские --section-gap-* главной, чтобы кейс не листался «пустыней») */
  --case-max:   1300px;   /* макс. ширина контент-колонки кейса — крупно, но собранно */
  --case-gap-m: 4.5rem;   /* межблочный ритм, моб. */
  --case-gap-d: 7rem;     /* межблочный ритм, десктоп */
  --case-media: 1.25rem;  /* внутренний зазор галереи, моб. */
  --case-media-d: 2rem;   /* внутренний зазор галереи, десктоп */

  /* easing-словарь */
  --ease-out-expo:  cubic-bezier(0.16, 1, 0.3, 1);
  --ease-out-quint: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-inout:     cubic-bezier(0.76, 0, 0.24, 1);

  /* z-шкала */
  --z-projects: 9;
  --z-header: 10;
  --z-loader: 1000;
  --z-cursor: 2000;
}

/* ---------- 2. RESET ---------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; }   /* НЕ ставить сюда overflow: ломает position:sticky у секции работ (заголовок перестаёт липнуть по центру). Гориз. переполнение гасим у источника — шапки (см. .header) */
body {
  font-family: var(--f-body);
  font-weight: 400;
  color: var(--c-text);
  background: var(--c-bg);
  line-height: 1.4;
  overflow-x: hidden;
  overflow-wrap: break-word;   /* глобальная сетка переноса: длинные строки (email/@handle/RU-CTA) переносятся, а не обрезаются краем при overflow-x:hidden. white-space:nowrap-элементы (маркиза) это игнорируют */
  -webkit-font-smoothing: antialiased;
}
img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
h1, h2, h3 { font-weight: inherit; line-height: 1; }
:focus-visible { outline: 2px solid currentColor; outline-offset: 8px; }

.container {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--pad-x);
}

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* ---------- 3. INTRO STATES (антифликер) ---------- */
html.intro-loading [data-intro="marquee-line"],
html.intro-loading [data-intro="portrait"] { clip-path: inset(100% 0 0 0); }
html.intro-loading [data-intro="meta-item"],
html.intro-loading [data-intro="nav-item"],
html.intro-nav-only [data-intro="nav-item"] { opacity: 0; }
html.intro-skip-loader [data-loader],
html.intro-skip-loader .blinds { display: none !important; }
/* Счётчик-лоадер (шторка 0→100%) виден СТРОГО на первом визите (intro-loading).
   На перезагрузке (intro-blinds/nav-only) он скрыт навсегда — иначе после того как
   runBlindsReveal().finish() снимает класс intro-blinds, чёрный fixed-оверлей со статичным
   «0%» всплыл бы поверх страницы. */
html:not(.intro-loading) [data-loader] { display: none !important; }

/* ---------- 4. HEADER ---------- */
.header {
  position: fixed; top: 0; left: 0; width: 100%;
  z-index: var(--z-header);
}
.header__in {
  position: relative;
  display: flex; align-items: center; justify-content: space-between;
  padding-block: 1.25rem;
}

/* RU/EN тумблер — центр хедера (logo слева, nav справа) */
.lang-toggle {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  display: inline-flex; align-items: center; gap: 0.4rem;
  min-height: 44px;   /* тач-таргет */
  font-family: var(--f-body);
  font-size: var(--fs-sm); font-weight: 500;
  letter-spacing: var(--ls-caps-sm);
  color: var(--c-black);
  padding: 0.5rem 0.75rem; border: 1px solid var(--c-line);
  border-radius: 9999px; background: rgba(255,255,255,0.6);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  transition: border-color 0.4s var(--ease-out-quint), background 0.4s var(--ease-out-quint), color 0.4s var(--ease-out-quint);
  z-index: 1;
}
.lang-toggle:hover { border-color: var(--c-black); }
.lang-toggle__opt { transition: color 0.25s ease; color: var(--c-muted-36); }
.lang-toggle__sep { color: var(--c-muted-36); }
html[lang="ru"] .lang-toggle__opt[data-lang-ru],
html[lang="en"] .lang-toggle__opt[data-lang-en] { color: var(--c-black); }
/* тумблер внутри мобильного меню — обычный поток, не absolute */
.lang-toggle--menu {
  position: static; transform: none;
  align-self: flex-start; margin-bottom: 0.25rem;
}
.logo {
  display: inline-flex; flex-direction: column;
  font-family: var(--f-logo); font-weight: 900;   /* Saira Extra Condensed 900 — не зависит от --f-hero */
  text-transform: uppercase; line-height: 0.82;
  font-size: clamp(1.4rem, 7.3vw, 2.75rem); letter-spacing: 0.005em;   /* плавно уменьшается с шириной экрана; на планшете/десктопе (≥~600px) — те же 2.75rem */
  color: var(--c-black);
  transition: color 0.3s ease;
}
.logo span:nth-child(2) { margin-left: 0.7em; }   /* em → отступ «TROYAN» масштабируется вместе со шрифтом лого */

/* очень узкие экраны (<360px): чуть поджать капсулу языка (размер лого теперь плавный через clamp) */
@media (max-width: 360px) {
  .lang-toggle { padding: 0.4rem 0.6rem; gap: 0.3rem; }
}

.nav { display: none; gap: 2.5rem; }
.nav__link {
  position: relative;
  font-size: var(--fs-base); font-weight: 400;
  color: var(--c-black);
  transition: color 0.3s ease;
}
.nav__num { display: none; }

.menu-btn {
  text-transform: uppercase; letter-spacing: var(--ls-caps-sm);
  font-size: var(--fs-sm); font-weight: 500;
  border: 1px solid var(--c-black); border-radius: 0;
  padding: 0.75rem 1rem; background: #fff;
  transition: background 0.4s var(--ease-out-quint), color 0.4s var(--ease-out-quint), border-color 0.4s var(--ease-out-quint);
}
.menu-btn:hover { background: #f5f5f5; }

/* ---- Инверсия хедера над чёрным экраном контактов (класс тоглит ScrollTrigger) ---- */
.header--on-dark .logo,
.header--on-dark .nav__link,
.header--on-dark .nav__num,
.header--on-dark .lang-toggle { color: #fff; }
.header--on-dark .menu-btn {
  color: #fff; background: transparent; border-color: var(--c-w-line-16);
}
.header--on-dark .menu-btn:hover { background: rgba(255,255,255,0.08); }
.header--on-dark .lang-toggle {
  border-color: var(--c-w-line-16); background: rgba(255,255,255,0.06);
}
.header--on-dark .lang-toggle__opt,
.header--on-dark .lang-toggle__sep { color: var(--c-w-36); }
/* активный язык тумблера в инверсии — белый (i18n-подсветка сохраняется) */
html[lang="ru"] .header--on-dark .lang-toggle__opt[data-lang-ru],
html[lang="en"] .header--on-dark .lang-toggle__opt[data-lang-en] { color: #fff; }

/* мобильное меню */
.mobile-menu {
  position: fixed; inset: 0; z-index: calc(var(--z-header) + 5);
  background: #fff;
  opacity: 0; visibility: hidden;
  overflow-y: auto; -webkit-overflow-scrolling: touch;   /* короткий/ландшафтный экран: контакты в футере меню всегда доскроллятся */
  transition: opacity 0.4s var(--ease-out-expo), visibility 0.4s;
}
.mobile-menu.is-open { opacity: 1; visibility: visible; }
.mobile-menu__in {
  padding-top: 1.25rem; min-height: 100%; height: auto;
  display: flex; flex-direction: column;
}
.menu-close {
  position: fixed; top: calc(var(--header-h-m) / 2); right: var(--pad-x);
  transform: translateY(-50%);   /* ровно на месте кнопки MENU: центр по высоте шапки + правый край. fixed → не уезжает при скролле меню */
  text-transform: uppercase; letter-spacing: var(--ls-caps-sm);
  font-size: var(--fs-sm); font-weight: 500;
  border: 1px solid var(--c-black); border-radius: 0;   /* тот же квадрат-бокс, что у кнопки MENU */
  padding: 0.75rem 1rem; background: #fff;
  transition: background 0.4s var(--ease-out-quint), color 0.4s var(--ease-out-quint), border-color 0.4s var(--ease-out-quint);
}
.menu-close:hover { background: #f5f5f5; }
.mobile-menu__nav {
  display: flex; flex-direction: column; gap: 1rem;
  flex: 1; justify-content: center;
}
.mobile-menu__nav a {
  display: flex; align-items: baseline; gap: 0.6rem;
  font-size: clamp(1.375rem, 8vw, 2rem); font-weight: 500; text-transform: uppercase;
  letter-spacing: var(--ls-tight); overflow-wrap: anywhere;   /* «КОНТАКТЫ» + номер помещаются и ужимаются ≤200px */
}
.mobile-menu__nav .nav__num {
  display: inline-block; font-size: var(--fs-sm);
  color: var(--c-label); font-weight: 400;
}

/* футер мобильного меню — контакты Алена */
.mobile-menu__footer {
  padding-bottom: 2rem;
  display: flex; flex-direction: column; gap: 1rem;
}
.mm-line { height: 1px; width: 100%; background: var(--c-line); }
.mm-email {
  font-size: clamp(1rem, 6vw, 2.5rem);
  font-weight: 300; color: var(--c-text);
  align-self: flex-start;
  overflow-wrap: anywhere; word-break: break-word; max-width: 100%;   /* длинный email не даёт скролл на ≤200px */
}
.mm-social {
  display: flex; flex-wrap: wrap; gap: 1.5rem;
  font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: var(--ls-caps-sm);
}
.mm-social { gap: 0.75rem 1.25rem; }
.mm-social a { color: var(--c-label); display: inline-flex; align-items: center; min-height: 44px; padding-block: 0.6rem; }

/* ---------- 5. LOADER ---------- */
.loader {
  position: fixed; inset: 0; height: 100dvh;
  background: #000; z-index: var(--z-loader);
  display: flex; flex-direction: column; justify-content: flex-end;
  padding-bottom: 3rem;
}
.loader__in {
  display: flex; flex-direction: column; align-items: flex-start;
  gap: 0.4rem;   /* фраза сверху, процент сразу под ней, обе прижаты к левому краю */
}
#loader-word {
  font-family: var(--f-display); font-weight: 400;
  font-size: var(--fs-loader-word); color: #fff;
  text-transform: uppercase; line-height: 0.9; letter-spacing: 0.01em;
}
#loader-count {
  font-family: var(--f-display); font-weight: 400;
  font-size: 5rem; color: #fff; line-height: 0.9;
}
.loader.is-done { transform: translateY(-100vh); transition: transform 1s var(--ease-inout); }

/* колонны-жалюзи */
.blinds {
  position: fixed; inset: 0; display: flex;
  pointer-events: none; z-index: var(--z-loader);
}
.blinds > div { width: 12.5%; height: 100%; background: #000; }

/* Сценарий перезагрузки (html.intro-blinds): играет ТОЛЬКО «вторая часть» —
   чёрные колонны-жалюзи уже видны поверх страницы и быстро схлопываются, открывая сайт.
   Счётчик-шторка НЕ показывается; hero-таймлайн не переигрывается (клип-путь только под intro-loading). */
html.intro-blinds .loader { display: none !important; }
html.intro-blinds .blinds { display: flex; }

/* ---------- 6. HERO ---------- */
main { margin-top: var(--header-h-m); }
.hero {
  position: relative;
  height: calc(100vh - var(--header-h-m));
  height: calc(100svh - var(--header-h-m));   /* svh, не dvh: hero не меняет высоту при прятании адресной строки → строки маркизы не прыгают/не «приближаются рвано» при скролле на телефоне */
  display: flex; flex-direction: column; justify-content: space-between;
  margin-bottom: var(--section-gap-m);
}

.hero__portrait {
  position: absolute; top: 54%; left: 50%;   /* +4% высоты hero → верхняя марка выныривает над фото */
  transform: translate(-50%, -50%);
  width: min(260px, 66vw); aspect-ratio: 2 / 3; overflow: hidden;   /* единственный фикс-px шире 200px → min() не даёт фото вылезти за края на ≤394px */
  /* средний слой: над строками 1–2, под blend-строкой 3 */
  z-index: 2;
}
.hero__portrait-in {
  position: absolute; inset: 0;
  /* will-change ставится в JS только на время интро и снимается на onComplete */
}
.hero__portrait-in img {
  width: 100%; height: 100%; object-fit: cover;
  pointer-events: none;   /* не ловить наведение → браузер (Яндекс) не показывает всплывашку «скопировать/найти фото» */
  -webkit-user-select: none; user-select: none; -webkit-user-drag: none;
}
/* интерактивный WebGL-глитч — прозрачный слой поверх чистого <img> */
.hero__portrait-in canvas {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  pointer-events: none;   /* не перехватывать мышь — события идут на .hero__portrait */
  opacity: 0;             /* по умолчанию скрыт → видно чистое DOM-фото */
  transform: translateZ(0);   /* собственный композиторский слой: blend-строки не тянут WebGL в readback */
  isolation: isolate;
}

.hero__lines {
  /* без z-index: не создаём stacking context, чтобы строки и портрет
     жили в одном контексте .hero и правильно переслаивались */
  position: relative;
  flex: 1; display: flex; flex-direction: column;
  min-height: 0;
}
.marquee {
  position: relative; z-index: 1;   /* строки 1–2 — за портретом (z-index:2) */
  flex: 1; display: flex; align-items: center;
  overflow: hidden;
}
.marquee--black { color: #000; }   /* строка 1 — чистый чёрный (как строка 3 на белом), остаётся под фото */
.marquee--navy  { color: #171923; }  /* строка 2 — тёмный навигационный (как на референсе russellnumo) */
.marquee--blend { color: #fff; mix-blend-mode: difference; z-index: 3; }  /* строки 1/3 — над портретом (z3); difference-инверсия над фото — на ВСЕХ устройствах (эффект, который любит владелец) */

/* Контейнмент hero: гасит горизонтальное переполнение блока с лентой на телефоне
   (можно было тянуть страницу вправо). overflow-x:clip НЕ создаёт stacking context →
   не ломает mix-blend-mode строки-бленда и не трогает липкий sticky секции работ
   (он в другой секции). Только тач — на десктопе body{overflow-x:hidden} и так держит. */
@media (hover: none) {
  .hero { overflow-x: clip; }
}
.marquee__viewport { position: relative; width: 100%; overflow: hidden; }
.marquee__measure {
  visibility: hidden; position: absolute;
  white-space: nowrap; pointer-events: none;
}
.marquee__track {
  display: flex; width: max-content; will-change: transform;
}
.marquee__copy,
.marquee__measure {
  font-family: var(--f-display); font-weight: 400;   /* Six Caps — одновесовой дисплей (как GET IN TOUCH); «толщину» даёт обводка ниже */
  font-size: var(--fs-hero-line);
  line-height: 0.92 !important;   /* достаточно места, чтобы низ высоких букв Six Caps не обрезался полосой (overflow:hidden) */
  text-transform: uppercase;
  white-space: nowrap; width: max-content;
  padding-right: 1.5rem;
  letter-spacing: 0.005em;   /* буквы ближе друг к другу (было 0.03em) */
  /* обводка (-webkit-text-stroke) убрана: на тонких штрихах Six Caps она давала «незаполненный»/
     двойной контур (особенно диагональ N). Теперь буквы сплошные, полностью залиты цветом. */
}

.hero__meta {
  position: relative; z-index: 2;
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 0.25rem 1rem;   /* две строки meta не сталкиваются на ≤200px */
  font-size: var(--fs-sm);
  padding-bottom: 0.5rem;
}
.hero__meta-item {
  display: inline-flex; align-items: center; gap: 0.5rem;
  color: var(--c-muted-64); letter-spacing: 0.02em;
}
.clock::before { content: " • "; white-space: pre; }
.clock { font-variant-numeric: tabular-nums; }

/* статус-точка */
.dot {
  width: 8px; height: 8px; border-radius: 9999px;
  background: var(--c-accent);
  animation: pulse 2s infinite ease-out;
}
@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 var(--c-accent-pulse); }
  100% { box-shadow: 0 0 0 10px rgba(34,197,94,0); }
}

/* ---------- 7. SECTIONS ---------- */
.section { margin-bottom: var(--section-gap-m); }
.section-head {
  display: flex; align-items: center; justify-content: space-between;
  border-bottom: 1px solid var(--c-line);
  padding-bottom: 1rem; margin-bottom: var(--gap-inner-m);
}
.kicker {
  font-size: var(--fs-xs); text-transform: uppercase;
  letter-spacing: var(--ls-kicker); color: var(--c-label);
}

/* about */
.about__statement {
  font-family: var(--f-body); font-weight: 700;
  text-transform: uppercase;
  font-size: var(--fs-h-section); line-height: 1.33;
  letter-spacing: var(--ls-tight);
  color: var(--c-text);
  margin-bottom: var(--gap-inner-m);
}
.about__leads { display: flex; flex-direction: column; gap: var(--gap-inner-m); }
.lead {
  font-size: var(--fs-lead); font-weight: 400; line-height: 1.5;
}

/* reveal split (JS оборачивает слова) */
.w-mask { overflow: hidden; display: inline-block; vertical-align: top; }
.w-inner { display: inline-block; }
/* will-change только пока карточка в ховере (иначе десятки idle-слоёв на весь сеанс) */
.card.is-hover .w-inner { will-change: transform; }

/* ---------- 8. WORKS ---------- */
.works { position: relative; }
.works__sticky {
  position: sticky; top: 0; min-height: 100vh; min-height: 100dvh;
  display: flex; flex-direction: column; justify-content: center; align-items: center;
  text-align: center;
  pointer-events: none;
}
.works__title {
  font-family: var(--f-body); font-weight: 700;
  text-transform: uppercase;
  font-size: var(--fs-h-project); line-height: 0.9;
  letter-spacing: var(--ls-tight);
  overflow-wrap: anywhere;
  transition: opacity 0.4s ease;
}
.works.dim-title .works__title { opacity: 0; }
.works__hint {
  margin-top: 1.5rem;
  font-size: var(--fs-xs); font-weight: 300;
  text-transform: uppercase; letter-spacing: 0.05em; opacity: 0.7;
}

.works__cards { position: relative; z-index: var(--z-projects); }
.card { padding-block: 4rem; background: var(--c-bg); }
.card__meta { margin-bottom: 1rem; }
.card__meta-mask { overflow: hidden; }
.card__meta-row {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem;
  font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: 0.04em;
}
.card__year { color: var(--c-label); }
.card__title {
  font-family: var(--f-body); font-weight: 700;
  text-transform: uppercase;
  font-size: var(--fs-h-project); line-height: 0.9;
  letter-spacing: var(--ls-tight);
  overflow-wrap: anywhere; word-break: break-word;
  margin-bottom: var(--gap-inner-m);
}
.card__row {
  display: flex; flex-direction: column; gap: 2rem;
}
.card__media { width: 100%; overflow: hidden; will-change: transform; }
.card__media-link {
  display: block; overflow: hidden; background: #000;
  border-radius: 6px;   /* aspect-ratio убран — фото показывается ЦЕЛИКОМ, без обрезки сверху/снизу */
}
.card__media-link img { display: block; width: 100%; height: auto; }
.card__body {
  display: flex; flex-direction: column; gap: 1.25rem;
}
.card__desc {
  font-size: var(--fs-body-lg); font-weight: 300;
  color: var(--c-muted-64); max-width: 90%;
}
.card__mlink {
  font-size: var(--fs-sm); font-weight: 500;
  letter-spacing: 0.15em; text-transform: uppercase;
  align-self: flex-start;
  display: inline-flex; align-items: center; min-height: 44px; padding-block: 0.75rem;   /* тач-таргет */
}

/* ---------- 9. STUDIO (manifesto + services) ---------- */
.quote {
  text-align: center;
  font-size: var(--fs-quote); font-weight: 500; line-height: 1.25;
  letter-spacing: var(--ls-tight);
  max-width: 90%; margin-inline: auto;
}
.quote span { opacity: 0.1; transition: opacity 0.05s linear; }

.services-head { margin-top: 7.5rem; }
.services { display: flex; flex-direction: column; }

.acc-item {
  border-top: 1px solid var(--c-line);
  padding-block: 1rem;
  opacity: 0;
  transition: transform .8s var(--ease-out-quint) var(--d, 0s), opacity .8s ease var(--d, 0s);
}
.acc-item:last-of-type { border-bottom: 1px solid var(--c-line); }
.acc-item--start { text-align: left; transform: translateX(-80px); }
.acc-item--end   { text-align: right; transform: translateX(80px); }
.acc-item--indent { padding-left: 10%; }
.services.in .acc-item { opacity: 1; transform: none; }

.acc-btn {
  position: relative; display: inline-block; width: 100%;
  text-align: inherit;
}
.acc-item--end .acc-btn { text-align: right; }
.acc-btn__text {
  font-family: var(--f-body); font-weight: 700;
  text-transform: uppercase;
  font-size: var(--fs-h-service); line-height: 0.9;
  letter-spacing: var(--ls-tighter);
  color: var(--c-text);
  transition: color 0.3s ease;
}
.acc-btn__text .thin { font-weight: 400; }
.acc-btn__text .paren { font-weight: 400; }
.pill {
  display: inline-block; width: 0.62em; height: 0.5em;
  border-radius: 0.08em; background-color: #000;
  background-position: center; background-size: cover; background-repeat: no-repeat;
  vertical-align: middle; margin-inline: 0.06em;
  opacity: 0; transform: scale(0.4);
  transition: opacity .6s var(--ease-out-quint) var(--dp, 0s), transform .6s var(--ease-out-quint) var(--dp, 0s);
}
.services.in .pill { opacity: 1; transform: scale(1); }
.acc-hint {
  position: absolute; top: 50%; transform: translateY(-50%);
  font-size: var(--fs-sm); color: var(--c-label);
  text-transform: uppercase; letter-spacing: var(--ls-caps-sm);
  opacity: 0; transition: opacity 0.3s ease;
  white-space: nowrap; display: none;
}
.acc-item--start .acc-hint { left: auto; right: 0; margin: 0; }   /* держим ВНУТРИ экрана (было left:100% → уезжало за правый край) */
.acc-item--end   .acc-hint { right: auto; left: 0; margin: 0; }   /* было right:100% → уезжало за левый край */
.acc-item:hover .acc-hint { opacity: 1; }

.acc-panel {
  overflow: hidden; max-height: 0; opacity: 0;
  transition: max-height 0.6s var(--ease-out-quint), opacity 0.5s ease;
}
.acc-item.is-open .acc-panel { max-height: 240px; opacity: 1; }
.acc-panel p {
  padding-top: 1.25rem;
  font-size: var(--fs-sm); text-transform: uppercase;
  letter-spacing: var(--ls-caps-sm); color: var(--c-label);
}

.closing {
  margin-top: 4rem;
  display: flex; justify-content: flex-end;
}
.closing p {
  max-width: 480px; color: var(--c-label);
  font-size: var(--fs-body-lg); line-height: 1.5;
}

/* ---------- 10. FOOTER ----------
   Вертикальная композиция (1 экран): средняя полоса (заголовок ↔ фото MJ) →
   линия во весь экран → контакты → футер-бар у самого низа. */
.footer {
  position: relative;
  /* сам футер — flex-колонка, чтобы 100dvh реально дошло до детей (без опоры на %-height) */
  display: flex; flex-direction: column;
  /* ровно один экран: никакого пустого чёрного низа под баром.
     min-height (не жёсткий height): на нормальном экране = 1 экран, на коротком/зумленном — растёт, а не клипает бар */
  min-height: 100vh; min-height: 100dvh; background: transparent; color: #fff;
  overflow: hidden;
  margin-top: var(--section-gap-m);
  padding-top: calc(var(--header-h-m) + 1rem);   /* верхний отступ разводит kicker с fixed-хедером */
  padding-bottom: 1.75rem;                         /* нижний бар почти у самого низа */
}
/* колонка: средняя полоса (flex:1, центр вертикали) → линия → контакты → бар у низа */
.footer__in { display: flex; flex-direction: column; flex: 1; gap: 2rem; }
/* средняя полоса — забирает свободную высоту, содержимое по центру вертикали;
   заголовок слева, портрет MJ справа, на одной линии */
.footer__mid {
  flex: 1; min-height: 0;
  display: flex; align-items: center; justify-content: space-between;
  gap: clamp(2rem, 5vw, 5rem);
}
.footer__head { flex: 1; min-width: 0; }
/* фото MJ: на мобиле скрыто → средняя полоса = только заголовок, футер = ровно 1 экран */
.footer__col--media { display: none; flex-shrink: 0; }
.f-kicker { color: var(--c-w-48); margin-bottom: 1.25rem; }
.f-cta-mask { overflow: hidden; }
.f-cta {
  font-family: var(--f-display); font-weight: 400;
  text-transform: uppercase;
  font-size: var(--fs-mega); line-height: 0.9; letter-spacing: 0.005em;
  overflow-wrap: break-word; hyphens: auto;   /* одиночное слово «Связаться» не даёт скролл на ≤300px */
}
.f-line { height: 1px; width: 100%; background: var(--c-w-line-16); transform-origin: left; }
.f-contacts { display: flex; flex-direction: column; gap: 0.75rem; }
.f-email, .f-tg {
  font-size: var(--fs-email); font-weight: 300; color: var(--c-w-64);
  align-self: flex-start;
  overflow-wrap: anywhere; min-width: 0;   /* длинный email/@handle переносится, а не режется */
}
.f-bar {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 1rem;
  border-top: 1px solid var(--c-w-line-08); padding-top: 1.5rem;
  font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.1em;
}
.f-copy { color: var(--c-w-36); }
.f-nav { display: flex; flex-wrap: wrap; gap: 0.6rem 1.25rem; }
.f-nav a { color: var(--c-w-64); transition: color 0.3s ease; display: inline-flex; align-items: center; min-height: 40px; padding-block: 0.65rem; }
.f-nav a:hover { color: #fff; }
.f-loc { color: var(--c-w-36); display: none; }

/* ---- Портрет MJ + cursor-reveal ч/б → цвет ---- */
.mj {
  position: relative; overflow: hidden; background: #0e0e0e;
  /* портретная рамка, ограничена ПО ВЫСОТЕ (vh) → секция гарантированно остаётся 1 экран,
     фото не растягивается на всю высоту даже на низких вьюпортах */
  height: clamp(320px, 56vh, 620px); width: auto; aspect-ratio: 4 / 5;
}
.mj img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: center 18%;
  pointer-events: none; -webkit-user-select: none; user-select: none;
}
/* цветной слой — ИСТОЧНИК пикселей для canvas; на hover-девайсах скрыт,
   круг цвета рисует canvas-оверлей поверх ч/б .mj-bw */
.mj-color { opacity: 0; }
/* 2D-canvas soft-reveal: каждый кадр полностью clear + redraw круга цветного
   поверх ч/б → неперерисованных «кубиков» контура физически не остаётся
   (в отличие от CSS mask-image, которая на слабом GPU оставляет артефакты композитора) */
.mj-canvas {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  opacity: 0;                 /* JS поднимает до 1 на hover, гасит на leave */
  will-change: opacity;
}
/* тач / reduced-motion: без слежения за курсором → показываем цвет статично, canvas не нужен */
@media (hover: none), (prefers-reduced-motion: reduce) {
  .mj-color { opacity: 1; }
  .mj-canvas { display: none; }
}
/* нет canvas/2d-контекста (getContext вернул null) или JS не загрузился → цвет статично,
   иначе на desktop остался бы вечно ч/б портрет без reveal */
.mj.no-canvas .mj-color { opacity: 1; }
.mj.no-canvas .mj-canvas { display: none; }

/* ---------- 11. LINKS / MAGNETIC / CURSOR ---------- */
.link { position: relative; display: inline-block; }
.link::after {
  content: ''; position: absolute; left: 0; bottom: -2px;
  width: 0; height: 1px; background: currentColor; transition: width 0.5s var(--ease-out-quint);
}
.link:hover::after { width: 100%; }

.cursor {
  position: fixed; top: 0; left: 0; z-index: var(--z-cursor);
  width: 10px; height: 10px; border-radius: 9999px;
  background: #fff; mix-blend-mode: difference;
  pointer-events: none; transform: translate(-50%, -50%);
  display: flex; align-items: center; justify-content: center;
  will-change: transform;
}
.cursor__label {
  font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.1em;
  color: #000; opacity: 0; transform: scale(0.6);
  white-space: nowrap; pointer-events: none;
}

/* состояние «капсула с лейблом» — матовое стекло (frosted glass) + хроматика, как russellnumo.nl */
.cursor--label {
  mix-blend-mode: normal;
  background: rgba(255,255,255,0.14);
  -webkit-backdrop-filter: blur(8px) saturate(1.2);
  backdrop-filter: blur(8px) saturate(1.2);
  border: 1px solid rgba(255,255,255,0.35);
  border-radius: 999px;
  /* контур переживает и тёмный, и светлый бэкдроп: внешняя тёмная кайма даёт силуэт пилюли над светлыми скриншотами, внутренняя светлая — блик над тёмным/глитчем */
  box-shadow:
    0 0 0 0.5px rgba(0,0,0,0.28),
    0 6px 24px rgba(0,0,0,0.22),
    inset 0 1px 0 rgba(255,255,255,0.25);
}
.cursor--label .cursor__label {
  color: #fff;
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  mix-blend-mode: difference;   /* инверсия ограничена матовой заливкой капсулы (backdrop-filter изолирует stacking context), не фоном за ней — читаемость держится за счёт того, что заливка сама подхватывает размытый бэкдроп */
  text-shadow: -0.6px 0 rgba(255,0,80,0.6), 0.6px 0 rgba(0,220,255,0.6);   /* хроматическая аберрация */
}
/* деликатная «дрожь сигнала» — только вне reduced-motion */
@media (prefers-reduced-motion: no-preference) {
  .cursor--label .cursor__label { animation: cursorChroma 3s ease-in-out infinite; }
}
@keyframes cursorChroma {
  0%, 100% { text-shadow: -0.6px 0 rgba(255,0,80,0.6),  0.6px 0 rgba(0,220,255,0.6); }
  50%      { text-shadow: -1.4px 0 rgba(255,0,80,0.55), 1.4px 0 rgba(0,220,255,0.55); }
}

/* тач/без-hover: кастомный курсор не показываем ни при каких условиях */
@media (hover: none), (pointer: coarse) {
  .cursor { display: none !important; }
  /* backdrop-filter пересэмплирует прокручивающийся фон каждый кадр — на телефоне лишняя нагрузка */
  .lang-toggle { -webkit-backdrop-filter: none; backdrop-filter: none; background: rgba(255,255,255,0.9); }
}

/* ---------- 12. FOOTER REVEAL (CSS) ----------
   Скрытые стартовые состояния гейтятся html.js — как и контент кейса: если JS
   выключен/не загрузился, класс html.js не появляется и футер (CTA, email,
   Telegram) виден сразу, а не остаётся белым блоком. При работающем JS его
   раскрывает .footer.in (IntersectionObserver в project.js/main.js), плюс на
   кейс-страницах — CDN-независимый инлайн-фолбэк в <head>. */
.f-kicker { transition: opacity .6s var(--ease-out-expo), transform .6s var(--ease-out-expo); }
.f-cta { transition: transform .9s var(--ease-out-expo) .1s; }
.f-line { transform-origin: left; transition: transform 1s var(--ease-out-expo) .3s; }
.f-email { transition: opacity .6s var(--ease-out-expo) .4s, transform .6s var(--ease-out-expo) .4s, color .3s ease; }
.f-tg { transition: opacity .6s var(--ease-out-expo) .5s, transform .6s var(--ease-out-expo) .5s, color .3s ease; }
html.js .f-kicker { opacity: 0; transform: translateY(20px); }
html.js .f-cta { transform: translateY(100%); }
html.js .f-line { transform: scaleX(0); }
html.js .f-email { opacity: 0; transform: translateY(20px); }
html.js .f-tg { opacity: 0; transform: translateY(20px); }
html.js .footer__col--media { opacity: 0; transform: translateY(24px); }
.footer.in .f-kicker,
.footer.in .f-email,
.footer.in .f-tg { opacity: 1; transform: none; }
.footer.in .f-email:hover, .footer.in .f-tg:hover { color: #fff; }
.footer.in .f-cta { transform: none; }
.footer.in .f-line { transform: scaleX(1); }
.footer__col--media { transition: opacity .9s var(--ease-out-expo) .35s, transform .9s var(--ease-out-expo) .35s; }
.footer.in .footer__col--media { opacity: 1; transform: none; }

/* Кейс-страницы: у футера СВОЙ тёмный фон (не полагаемся на затемнение body
   через GSAP). Если gsap/CDN не загрузится — контакты остаются читаемыми,
   а не «белым по белому». На главной затемнение остаётся плавным (body). */
.case-page .footer { background: var(--c-bg-dark); }

/* ============================================================
   13. DESKTOP  (≥832)
   ============================================================ */
@media (min-width: 832px) {
  main { margin-top: var(--header-h-d); }
  .hero { height: calc(100vh - var(--header-h-d)); height: calc(100dvh - var(--header-h-d)); margin-bottom: var(--section-gap-d); }
  .section { margin-bottom: var(--section-gap-d); }
  .footer {
    margin-top: var(--section-gap-d);
    padding-top: calc(var(--header-h-d) + 1rem);
    padding-bottom: 2.25rem;
  }
  /* десктоп: показываем портрет MJ в правой части средней полосы, по центру вертикали напротив заголовка */
  .footer__col--media { display: block; }
  /* заголовок в левой части средней полосы (flex:1), фото — узкая портретная колонка справа → ужимаем vw-терм, чтобы «GET IN TOUCH» не заезжал под фото */
  .f-cta { font-size: clamp(4.5rem, min(12vw, 26vh), 15rem); }

  .header__in { padding-block: 2rem; }
  .logo { font-size: 3.6rem; }
  .logo span:nth-child(2) { margin-left: 2.4rem; }
  .nav { display: flex; }
  .menu-btn { display: none; }
  .services-head { margin-top: 12.5rem; }
  .f-loc { display: block; }

  .section-head { margin-bottom: var(--gap-inner-d); }
  .about__statement { line-height: 1.2; margin-bottom: var(--gap-inner-d); }
  .about__leads { gap: var(--gap-inner-d); }
  .lead--end { align-self: flex-end; max-width: 60%; }

  /* карточки: скрытые до ховера маски */
  .card { min-height: 80vh; padding-block: 5rem; display: flex; flex-direction: column; justify-content: center; }
  .card__meta { border-bottom: 1px solid transparent; transition: border-color 0.4s ease; }
  .card__meta-row { transform: translateY(100%); transition: transform 1.5s var(--ease-out-quint); }
  .card__title .w-inner { transform: translateY(110%); transition: transform 1.5s var(--ease-out-quint); transition-delay: var(--wd, 0s); }
  .card.is-hover .card__meta { border-color: var(--c-line); }
  .card.is-hover .card__meta-row { transform: translateY(0); }
  .card.is-hover .card__title .w-inner { transform: translateY(0); }

  .card__desc .w-inner { transform: translateY(110%); transition: transform 1.5s var(--ease-out-quint); transition-delay: var(--wd, 0s); }
  .card.is-hover .card__desc .w-inner { transform: translateY(0); }
  .card__mlink { display: none; }

  .card__row { flex-direction: row; gap: 3rem; align-items: center; }
  .card--rev .card__row { flex-direction: row-reverse; }
  .card__media { width: 64%; }   /* фото крупнее и во всю высоту (без обрезки) */
  .card__body { flex: 1; justify-content: center; }

  .acc-hint { display: block; }
}

/* мобильная маска карточек: показаны сразу */
@media (max-width: 831px) {
  .card__meta-row { transform: none; }
  .card__title .w-inner { transform: none !important; }
  .card__desc .w-inner { transform: none !important; }
  /* splitWords оборачивает каждое слово в атомарный inline-block .w-mask>.w-inner,
     который не переносится → «PLATFORM»/«VLADITROYA.RU» вылезали. Схлопываем в inline,
     чтобы заголовок переносился (reveal-трансформ — только на десктопе ≥832px). */
  .card__title .w-mask { display: inline; overflow: visible; }
  .card__title .w-inner { display: inline; }

  /* стрелки-подсказки услуг: на телефоне показываем сразу, в потоке под заголовком (без hover) */
  .acc-hint {
    display: block; position: static; transform: none;
    opacity: 1; margin-top: 0.6rem; white-space: normal;
  }
  .acc-item--start .acc-hint { text-align: left; }
  .acc-item--end .acc-hint { text-align: right; }

  /* на узких экранах домен в блоке «следующий проект» переносим, чтобы не обрезался */
  .case-next__title { white-space: normal; }
}

/* ============================================================
   14. PORTRAIT / QUOTE  (≥1024)
   ============================================================ */
@media (min-width: 1024px) {
  .hero__portrait { width: 350px; }
  .quote { max-width: 80%; }
}

/* ============================================================
   15. REDUCED MOTION
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .dot { animation: none; box-shadow: 0 0 0 2px rgba(34,197,94,0.35); }
  html.intro-loading [data-intro="marquee-line"],
  html.intro-loading [data-intro="portrait"] { clip-path: none; }
  html.intro-loading [data-intro="meta-item"],
  html.intro-loading [data-intro="nav-item"],
  html.intro-nav-only [data-intro="nav-item"] { opacity: 1; }
  [data-loader], .blinds { display: none !important; }   /* лоадер и колонны скрыты → мгновенный показ контента */
  .quote span { opacity: 1 !important; }
  .card__meta-row,
  .card__title .w-inner,
  .card__desc .w-inner { transform: none !important; }
  .acc-item { opacity: 1 !important; transform: none !important; }
  .pill { opacity: 1 !important; transform: none !important; }
  .f-kicker, .f-cta, .f-line, .f-email, .f-tg,
  .footer__col--media { opacity: 1 !important; transform: none !important; }
  .footer { background: var(--c-bg-dark) !important; }
}

/* ============================================================
   16. CASE-STUDY PAGES (project-*.html)
   Тот же монохром/типо-контраст, что и на главной.
   Плейсхолдеры .case-ph легко меняются на <img>.
   ============================================================ */

/* --- reveal-механики (IntersectionObserver → .is-in) ---
   Скрытые стартовые состояния навешиваются ТОЛЬКО при работающем JS
   (html.js ставится инлайн-скриптом до рендера). При выключенном JS
   класс html.js не появляется — контент кейса виден сразу.
   Если же JS есть, но project.js не загрузился (404, блокировка, сеть) —
   инлайн-таймер __caseRevealFallback (5с, тот же <head>-скрипт, что ставит
   html.js) сам добавит .is-in всему контенту, поэтому скрины/заголовки/текст
   гарантированно показываются даже при полном отказе project.js. */
/* ============ ПОЯВЛЕНИЕ КЕЙСА — 100% CSS, без JS/CDN ============
   Приятная анимация появления, которая физически НЕ может задержать показ
   или оставить белую страницу (в отличие от прежнего JS+CDN reveal):
   • всё видимо по умолчанию (opacity:1) — ничего не «спрятано до JS»;
   • hero (выше сгиба) — мягкий каскадный fade-up на загрузке (time-based,
     проигрывается один раз, работает в любом браузере);
   • секции ниже — reveal привязан к прокрутке (animation-timeline: view()):
       – фото/текст красиво проявляются по мере входа во вьюпорт,
       – элемент, уже попавший на экран, показан на 100% (range: entry),
       – браузер без поддержки timeline просто показывает контент сразу;
   • prefers-reduced-motion — всё статично и видно (весь блок под no-preference,
     плюс страховочный reduce-блок 16c ниже). */
[data-cr], [data-cr-clip] { opacity: 1; }

@media (prefers-reduced-motion: no-preference) {

  @keyframes cr-rise {
    from { opacity: 0; transform: translateY(26px); }
    to   { opacity: 1; transform: translateY(0); }
  }
  @keyframes cr-rise-lg {
    from { opacity: 0; transform: translateY(44px); }
    to   { opacity: 1; transform: translateY(0); }
  }
  @keyframes cr-line-in {
    from { opacity: 0; transform: scaleX(0); }
    to   { opacity: 1; transform: scaleX(1); }
  }
  /* фото заметно ВЫЕЗЖАЕТ снизу вверх — фигура-снимок делает slide-up.
     Масштаб/клип фото НЕ трогаем: (1) любой зум даёт кратковременную обрезку
     кадра, а фото должно показываться целиком; (2) .case-frame имеет
     overflow:hidden → это скролл-контейнер, и view()-таймлайн вложенного
     <img> к странице не привязывается. Поэтому анимируем только фигуру. */
  @keyframes cr-photo {
    from { opacity: 0; transform: translateY(88px); }
    to   { opacity: 1; transform: translateY(0); }
  }

  /* --- HERO: каскад на загрузке --- */
  .case-topline  { animation: cr-rise .8s var(--ease-out-expo) both; }
  .case-title    { animation: cr-rise-lg .9s var(--ease-out-expo) .08s both; }
  .case-hairline { transform-origin: left; animation: cr-line-in .9s var(--ease-out-expo) .22s both; }
  .case-hero [data-cr] {
    animation: cr-rise .85s var(--ease-out-expo) both;
    animation-delay: calc(.3s + var(--cr-d, 0s));   /* meta/интро приходят после заголовка */
  }

  /* --- СЕКЦИИ НИЖЕ СГИБА: привязка к прокрутке --- */
  @supports (animation-timeline: view()) {

    /* текстовые блоки — fade-up по мере входа во вьюпорт */
    .case-block [data-cr],
    .case-facts [data-cr],
    .case-next  [data-cr] {
      animation: cr-rise-lg linear both;
      animation-timeline: view();
      animation-range: entry 8% cover 32%;
    }

    /* фигура со снимком заметно ВЫЕЗЖАЕТ снизу вверх (фото внутри — целиком, статично) */
    .case-gallery [data-cr] {
      animation: cr-photo linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 46%;
    }
  }
}

/* --- собранная контент-колонка кейса ---
   Переопределяет широкий .container (1920) на дорого-собранную ширину,
   чтобы медиа не растягивалось «во весь экран», а левый край всех секций совпадал. */
.case-hero,
.case-gallery,
.case-block,
.case-facts,
.case-next { max-width: var(--case-max); }

/* --- hero кейса --- */
.case-hero {
  min-height: calc(100vh - var(--header-h-m));
  min-height: calc(100dvh - var(--header-h-m));
  display: flex; flex-direction: column; justify-content: flex-end;
  padding-bottom: 2.5rem;
  margin-bottom: var(--case-gap-m);
}
.case-topline {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; margin-bottom: auto; padding-top: 1rem;
}
.case-back {
  font-size: var(--fs-sm); font-weight: 500;
  text-transform: uppercase; letter-spacing: var(--ls-caps-sm);
  color: var(--c-text);
  display: inline-flex; align-items: center; min-height: 40px;   /* тач-таргет без гориз. паддинга — topline не выходит за бюджет */
}
.case-index {
  font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--c-label);
}
.case-title {
  font-family: var(--f-body); font-weight: 700;
  text-transform: uppercase;
  white-space: normal; overflow-wrap: anywhere; word-break: break-word; hyphens: auto;   /* на мобиле перенос: nowrap+floor обрезал «MONTAGE PLATFORM»/«VLADITROYA.RU» на ≤282px. Десктоп-nowrap возвращён в @media ≥832px */
  font-size: clamp(1.5rem, 8.5vw, 8rem); line-height: 0.95;
  letter-spacing: var(--ls-tight);
  margin-top: 2rem; margin-bottom: 1.5rem;
}
.case-title .l-mask {
  overflow: hidden; display: inline-block; vertical-align: bottom;
}
.case-title .l-inner {
  display: inline-block; transform: none;   /* виден сразу, без ожидания JS */
  transition: transform .7s var(--ease-out-expo) var(--l-d, 0s);
}
.case-title.is-in .l-inner { transform: translateY(0); }
.case-hairline {
  height: 1px; background: var(--c-line);
  transform-origin: left;
  transition: transform 1s var(--ease-out-expo) var(--cr-d, 0s);
  margin-bottom: 1.5rem;
}
.case-hairline { transform: scaleX(1); }   /* видна сразу — мгновенный показ */

.case-lede {
  display: flex; flex-direction: column; gap: 2rem;
  justify-content: space-between; align-items: flex-start;
}
.case-meta { display: flex; gap: 2.5rem; flex-shrink: 0; flex-wrap: wrap; }
.case-meta-pair { display: flex; flex-direction: column; }
.case-meta-label {
  font-size: var(--fs-xs); text-transform: uppercase;
  letter-spacing: var(--ls-kicker); color: var(--c-label);
  margin-bottom: 0.5rem;
}
.case-meta-value { font-size: var(--fs-sm); letter-spacing: 0.02em; }
.case-intro-col { max-width: 640px; }
.case-intro {
  font-size: var(--fs-body-lg); font-weight: 300; line-height: 1.5;
  color: var(--c-text);
}
.case-live {
  display: inline-flex; align-items: center; min-height: 40px; margin-top: 1.5rem;
  font-size: var(--fs-sm); font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.15em;
}
.case-live--muted { color: var(--c-label); pointer-events: none; }

/* --- галерея / кадры скринов ---
   Ключевое решение против обрезки: у настоящих скринов <img> высота НЕ
   фиксируется (height:auto) — рамка подстраивается под пропорцию картинки,
   поэтому 16:10 (десктоп), полностраничные и мобильные скрины никогда не
   режутся. Пропорцию задаёт сам контент. Плейсхолдеры .case-ph (без <img>)
   получают aspect-ratio через :has(), чтобы держать сетку. */
.case-gallery {
  display: flex; flex-direction: column; gap: var(--case-media);
  margin-bottom: var(--case-gap-m);
}
.case-row { display: flex; flex-direction: column; gap: var(--case-media); }
.case-row > * { flex: 1; min-width: 0; }

/* фигура-кадр: рамка + подпись под ней (authentic-подача) */
.case-shot { display: flex; flex-direction: column; gap: 0.9rem; margin: 0; min-width: 0; }

.case-frame {
  position: relative; overflow: hidden;
  background: #f1f1f2;                 /* тёплая подложка под светлые скрины */
  border-radius: 12px;
  box-shadow:
    0 24px 48px -30px rgba(0,0,0,0.34),
    0 8px 20px -16px rgba(0,0,0,0.18);
}
/* тонкий чёткий кант поверх скруглённого угла */
.case-frame::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,0.09); pointer-events: none; z-index: 2;
}
.case-frame img { width: 100%; height: auto; display: block; }

/* Пропорция задаётся на самой рамке (не через :has), чтобы плейсхолдеры не
   схлопывались в 0px на движках без :has-поддержки — там это мягкая деградация
   к заданному варианту, а не жёсткий обрыв. У настоящих скринов пропорцию
   диктует картинка, поэтому для рамок с <img> aspect-ratio сбрасывается. */
/* Рамка НЕ имеет фиксированной пропорции: её высоту диктует контент.
   У настоящих скринов высоту даёт сама картинка (img height:auto → показывается
   ЦЕЛИКОМ, при любой пропорции, ничего не режется). У заглушек высоту даёт блок
   .case-ph со своим aspect-ratio. Без :has() — работает в любом браузере. */
.case-frame--portrait .case-ph { aspect-ratio: 4 / 5; }
.case-frame--square   .case-ph { aspect-ratio: 1 / 1; }
.case-frame--tall     .case-ph { aspect-ratio: 3 / 4; }

/* подпись под кадром — нумерация + название экрана */
.case-cap {
  display: flex; align-items: baseline; gap: 0.7rem;
  padding-inline: 0.15rem;
}
.case-cap__num {
  font-family: var(--f-body); font-weight: 700;
  font-size: var(--fs-xs); letter-spacing: 0.04em;
  color: var(--c-text); flex-shrink: 0;
}
.case-cap__txt {
  font-size: var(--fs-xs); text-transform: uppercase;
  letter-spacing: var(--ls-kicker); color: var(--c-label);
}

/* плейсхолдер: заменить блок .case-ph на <img> — рамка возьмёт пропорцию скрина */
.case-ph {
  position: relative; width: 100%; aspect-ratio: 16 / 10;   /* заглушка сама даёт высоту рамке (без :has); у рамок с <img> высоту диктует картинка */
  display: flex; align-items: center; justify-content: center;
  background:
    linear-gradient(135deg, #161616 0%, #0a0a0a 60%, #0e0e0e 100%);
}
.case-ph::before {
  /* деликатная диагональная штриховка — «дорогая» пустота, не плоский чёрный */
  content: ''; position: absolute; inset: 0; opacity: 0.5;
  background-image: repeating-linear-gradient(
    -45deg, transparent 0 22px, rgba(255,255,255,0.018) 22px 23px);
}
.case-ph__num {
  font-family: var(--f-display); font-weight: 400;
  font-size: clamp(3rem, 9vw, 8rem); line-height: 0.9;
  color: rgba(255,255,255,0.14); letter-spacing: 0.02em;
}

/* --- текстовые блоки кейса --- */
.case-block { margin-bottom: var(--case-gap-m); }
.case-block__head {
  display: flex; align-items: center; justify-content: space-between;
  border-bottom: 1px solid var(--c-line);
  padding-bottom: 1rem; margin-bottom: var(--gap-inner-m);
}
.case-block__title {
  font-family: var(--f-body); font-weight: 700; text-transform: uppercase;
  font-size: var(--fs-h-section); line-height: 1.2;
  letter-spacing: var(--ls-tight); margin-bottom: 1.5rem;
  overflow-wrap: break-word; word-break: break-word;   /* длинные RU-слова «МУЛЬТИТЕНАНТНОЕ» не вылезают */
}
.case-block__body {
  font-size: clamp(1rem, 2.4vw + 0.55rem, 1.5rem); font-weight: 400; line-height: 1.5;   /* локальный размер вместо --fs-lead(7vw): на телефоне ~4-5 слов/строку было слишком крупно */
  max-width: 900px;
}

/* --- факты / стек --- */
.case-facts {
  display: grid; grid-template-columns: 1fr; gap: 0;
  margin-bottom: var(--case-gap-m);
  border-top: 1px solid var(--c-line);
}
.case-fact {
  display: flex; flex-direction: column; gap: 0.5rem;
  padding-block: 1.5rem; border-bottom: 1px solid var(--c-line);
}
.case-fact__label {
  font-size: var(--fs-xs); text-transform: uppercase;
  letter-spacing: var(--ls-kicker); color: var(--c-label);
}
.case-fact__value {
  font-size: var(--fs-body-lg); font-weight: 300; color: var(--c-text);
}

/* --- следующий проект --- */
.case-next {
  display: block; padding-top: 4rem; padding-bottom: 2rem;
  border-top: 1px solid var(--c-line); overflow: hidden;
}
.case-next__top {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; margin-bottom: 2.5rem;
}
.case-next__eyebrow, .case-next__year {
  font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: var(--ls-kicker);
}
.case-next__eyebrow { color: var(--c-text); }
.case-next__year { color: var(--c-label); }
.case-next__body {
  display: flex; flex-direction: column; gap: 2.5rem; align-items: flex-start;
}
.case-next__main { flex: 1; min-width: 0; }
.case-next__title {
  font-family: var(--f-body); font-weight: 700; text-transform: uppercase;
  font-size: clamp(1.75rem, 7vw, 4.5rem); line-height: 0.95;   /* уменьшено + одинаковый размер на всех кейсах, чтобы домен (VLADITROYA.RU) гарантированно помещался в ОДНУ строку с запасом */
  letter-spacing: var(--ls-tight);
  white-space: nowrap;   /* домены (VLADITROYA.RU / KOKOA) на десктопе не переносим */
}
.case-next__title--wrap { white-space: normal; }   /* исключение: MONTAGE PLATFORM — два слова, можно в две строки */
.case-next__ul {
  height: 1px; background: var(--c-black); transform: scaleX(0);
  transform-origin: left; transition: transform .8s var(--ease-out-expo);
  margin-top: 1rem;
}
.case-next__role {
  margin-top: 1rem; font-size: var(--fs-xs);
  text-transform: uppercase; letter-spacing: var(--ls-kicker); color: var(--c-label);
}
.case-next__thumb {
  width: 100%; position: relative; overflow: hidden;
  background: #0a0a0a; aspect-ratio: 16 / 9;
}
.case-next__img {
  position: absolute; inset: 0; transform: scale(1);
  transition: transform 1.1s var(--ease-out-expo); will-change: transform;
}
.case-next__img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.case-next__arrow { display: inline-block; transition: transform .4s var(--ease-out-expo); }
.case-next:hover .case-next__img { transform: scale(1.04); }
.case-next:hover .case-next__ul { transform: scaleX(1); }
.case-next:hover .case-next__arrow { transform: translateX(12px); }
.case-next__cta {
  display: flex; align-items: center; gap: 0.5rem; margin-top: 1.5rem;
  font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: 0.15em;
}

/* ============================================================
   16b. CASE DESKTOP (≥832)
   ============================================================ */
@media (min-width: 832px) {
  .case-hero {
    min-height: calc(100vh - var(--header-h-d));
    min-height: calc(100dvh - var(--header-h-d));
    padding-bottom: 3rem;
    margin-bottom: var(--case-gap-d);
  }
  .case-title { margin-top: 3rem; margin-bottom: 2.5rem; white-space: nowrap; }   /* десктоп: название снова в одну строку (перенос — только на мобиле) */
  .case-hairline { margin-bottom: 2.5rem; }
  .case-lede { flex-direction: row; gap: 3rem; }
  .case-meta { gap: 4rem; }
  .case-intro-col { max-width: 45%; }

  .case-gallery { gap: var(--case-media-d); margin-bottom: var(--case-gap-d); }
  .case-row { gap: var(--case-media-d); }
  .case-row--pair { flex-direction: row; align-items: flex-start; }

  .case-block { margin-bottom: var(--case-gap-d); }
  .case-block__head { margin-bottom: var(--gap-inner-d); }

  .case-facts {
    grid-template-columns: repeat(3, 1fr);
    column-gap: 3rem;
    margin-bottom: var(--case-gap-d);
  }
  .case-fact { border-bottom: none; padding-bottom: 0; }

  .case-next__body { flex-direction: row; gap: 4rem; align-items: flex-end; }
  .case-next__thumb { width: 38%; transform: translateY(-40px); aspect-ratio: 4 / 5; }
  .case-next__cta { display: none; }
}

/* ============================================================
   16c. CASE REDUCED MOTION
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  [data-cr], [data-cr-clip], .case-frame img,
  .case-topline, .case-title, .case-hairline, .case-title .l-inner {
    animation: none !important;
    opacity: 1 !important; transform: none !important;
    clip-path: none !important;
  }
  .case-next__thumb { transform: none !important; }
}

/* ============================================================
   17. ЗАЩИТА ФОТО ОТ КОПИРОВАНИЯ + ЛАЙТБОКС-КАРУСЕЛЬ
   ============================================================ */

/* --- Убрать hover-панель Яндекс.Браузера (копир./перевод/поиск по фото)
   и запретить перетаскивание/выделение снимков. pointer-events:none на
   самом <img> гасит эту панель, а клики уходят на родителя-обёртку
   (ссылку карточки / рамку кейса / фон лайтбокса) — навигация и открытие
   лайтбокса продолжают работать. --- */
.card__media-link img,
.case-frame img,
.lightbox__img,
.hero__portrait img,
.case-next__thumb img {
  -webkit-user-select: none; -moz-user-select: none; user-select: none;
  -webkit-user-drag: none; user-drag: none;
  pointer-events: none;
}

/* --- Лайтбокс --- */
.case-frame { cursor: zoom-in; }

.lightbox {
  position: fixed; inset: 0; z-index: 300;
  display: flex; align-items: center; justify-content: center;
  padding: clamp(1rem, 4vw, 3rem);
  background: rgba(8, 8, 9, 0.94);
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
  opacity: 0; visibility: hidden;
  transition: opacity .35s ease, visibility .35s ease;
}
.lightbox.is-open { opacity: 1; visibility: visible; }

.lightbox__stage {
  display: flex; align-items: center; justify-content: center;
  max-width: 100%; max-height: 100%;
}
.lightbox__img {
  display: block;
  max-width: min(92vw, 1600px); max-height: 86vh;
  width: auto; height: auto;
  object-fit: contain;                 /* фото ЦЕЛИКОМ — никогда не обрезается */
  border-radius: 8px;
  box-shadow: 0 30px 80px rgba(0, 0, 0, .5);
  transform: scale(.96); opacity: 0;
  transition: transform .4s var(--ease-out-expo), opacity .4s ease;
}
.lightbox.is-open .lightbox__img { transform: scale(1); opacity: 1; }

.lightbox__close,
.lightbox__nav {
  position: absolute; z-index: 2;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid rgba(255, 255, 255, .18);
  background: rgba(255, 255, 255, .06);
  color: #fff; cursor: pointer;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  transition: background .25s ease, border-color .25s ease, transform .2s ease;
}
.lightbox__close:hover,
.lightbox__nav:hover { background: rgba(255, 255, 255, .16); border-color: rgba(255, 255, 255, .45); }
.lightbox__close:focus-visible,
.lightbox__nav:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

.lightbox__close {
  top: clamp(1rem, 3vw, 2rem); right: clamp(1rem, 3vw, 2rem);
  width: 48px; height: 48px; border-radius: 50%;
}
.lightbox__close:active { transform: scale(.92); }

.lightbox__nav {
  top: 50%; transform: translateY(-50%);
  width: 56px; height: 56px; border-radius: 50%;
}
.lightbox__nav:active { transform: translateY(-50%) scale(.92); }
.lightbox__nav--prev { left: clamp(1rem, 3vw, 2.5rem); }
.lightbox__nav--next { right: clamp(1rem, 3vw, 2.5rem); }

.lightbox__close svg { width: 42%; height: 42%; }
.lightbox__nav svg { width: 34%; height: 34%; }
.lightbox__close svg, .lightbox__nav svg {
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}

.lightbox__counter {
  position: absolute; left: 50%; bottom: clamp(1rem, 3vw, 1.75rem);
  transform: translateX(-50%);
  display: flex; gap: .45em; align-items: center;
  font-size: var(--fs-sm); letter-spacing: .08em;
  color: rgba(255, 255, 255, .72);
  font-variant-numeric: tabular-nums;
}
.lightbox__sep { opacity: .5; }

@media (max-width: 640px) {
  .lightbox__nav { width: 46px; height: 46px; }
  .lightbox__nav--prev { left: .55rem; }
  .lightbox__nav--next { right: .55rem; }
  .lightbox__img { max-height: 80vh; }
}

@media (prefers-reduced-motion: reduce) {
  .lightbox, .lightbox__img { transition: none !important; }
  .lightbox__img { transform: none !important; }
}

/* ============================================================
   18. КАСТОМНЫЙ СКРОЛЛ-БАР + ИНДИКАТОР ПРОГРЕССА
   ============================================================ */

/* --- Оригинальный скролл-бар СПРЯТАН: вместо него — индикатор прогресса
   справа (ниже). Прокрутка работает колесом / тачем / Lenis; ширина
   страницы не теряется на gutter. --- */
html { scrollbar-width: none; -ms-overflow-style: none; }        /* Firefox / старый Edge */
::-webkit-scrollbar { width: 0; height: 0; display: none; }      /* WebKit / Chromium / Yandex */

/* --- Индикатор прогресса: тонкая вертикальная линия у самого правого края,
   растёт сверху вниз по мере прокрутки. mix-blend-mode:difference → всегда
   видна на любом фоне (тот же приём, что у кастомного курсора). Чистый CSS
   через animation-timeline:scroll() — синхрон с нативным скроллом (и Lenis).
   Прячется под лайтбоксом/меню (z-index ниже). --- */
.scroll-progress {
  position: fixed; top: 0; right: 0;
  width: 3px; height: 100vh; height: 100dvh;
  z-index: 120; pointer-events: none;
  background: #fff; mix-blend-mode: difference;
  transform: scaleY(0); transform-origin: top center;
}
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .scroll-progress {
      animation: sp-grow linear both;
      animation-timeline: scroll(root block);
    }
  }
}
@keyframes sp-grow {
  from { transform: scaleY(0); }
  to   { transform: scaleY(1); }
}

/* ============================================================
   19. АДАПТИВ — узкие экраны (вплоть до 200px) + низкие вьюпорты
   Размещены В КОНЦЕ файла НАМЕРЕННО: базовые правила объявлены
   позже по исходнику, чем ранний блок @360 (стр. 176), и перебили
   бы медиа-правила, стоящие до них. Порядок тиров по ширине:
   480 → 360 → 260 → 240 — более узкий идёт позже и выигрывает.
   ============================================================ */
@media (max-width: 480px) {
  .card { padding-block: 2.5rem; }
  .card__desc { max-width: 100%; }
  .card__meta-row { gap: 0.5rem; align-items: flex-start; font-size: var(--fs-xs); }
  .case-meta { gap: 1rem 1.5rem; }
  .case-block__title { font-size: clamp(1.375rem, 5.5vw + 0.4rem, 2rem); }
  .f-bar { justify-content: flex-start; gap: 0.75rem 1.25rem; }
}

@media (max-width: 360px) {
  :root { --fs-h-project: clamp(2.25rem, 12vw, 4rem); --fs-email: clamp(1rem, 5vw, 1.25rem); --section-gap-m: 6rem; }
  .hero__meta { flex-direction: column; align-items: flex-start; gap: 0.35rem; }
  .case-meta { gap: 0.75rem 1.25rem; }
  .case-title { margin-top: 1.25rem; margin-bottom: 1rem; }
  .case-topline { flex-wrap: wrap; gap: 0.5rem; }
  .case-next__top { flex-wrap: wrap; row-gap: 0.35rem; }
  .header__in { gap: 0.5rem; }
  .header__in .lang-toggle { position: static; transform: none; }   /* тумблер в поток: логотип | RU/EN | menu, без наложения */
  .lightbox__nav { top: auto; bottom: 0.75rem; transform: none; width: 44px; height: 44px; }   /* стрелки в нижний ряд, не наезжают на фото */
  .lightbox__nav:active { transform: scale(0.92); }
  .lightbox__nav--prev { left: 0.75rem; }
  .lightbox__nav--next { right: 0.75rem; }
  .lightbox__img { max-width: 100%; max-height: 68vh; }
  .lightbox__counter { bottom: calc(0.75rem + 12px); }
}

@media (max-width: 260px) {
  :root { --pad-x: 0.7rem; --fs-mega: clamp(2rem, 13vw, 3rem); --fs-h-project: clamp(1.75rem, 11vw, 2.4rem); --fs-email: clamp(0.9rem, 6vw, 1.1rem); }
  .case-title { font-size: clamp(1.25rem, 9vw, 2rem); }
}

@media (max-width: 240px) {
  .header__in .lang-toggle { display: none; }   /* остаются логотип + menu (~156px в ~191px); язык переключается в футере мобильного меню */
}

/* низкие/ландшафтные вьюпорты по высоте */
@media (max-height: 520px) {
  .mobile-menu__nav { flex: 0 0 auto; justify-content: flex-start; padding: 4.5rem 0 2rem; }   /* без принудительного центрирования — контакты в футере меню доскроллятся */
  .mobile-menu__nav a { font-size: clamp(1.25rem, 7vw, 1.75rem); }
}
@media (max-height: 480px) {
  :root { --header-h-m: 84px; }
  .header__in { padding-block: 0.75rem; }
}
