/* =============================================
   RESET & BASE
   ============================================= */
@font-face {
  font-family: 'Uncut Sans Variable';
  src:
    local('Uncut Sans Variable'),
    local('Uncut Sans'),
    url('../fonts/Uncut-Sans/Webfonts/UncutSans-Variable.woff2') format('woff2');
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
}

*, *::before, *::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

:root {
  --black: #000000;
  --white: #ffffff;
  --gray: #f2f2f2;
  --gray-mid: #e0e0e0;
  /* Figma `Base/Balck/Black A55` (#0000008c). Используется для тонких
     hairline-разделителей и .btn border'ов в дизайн-системе. */
  --black-a55: rgba(0, 0, 0, 0.55);
  --text-secondary: #666666;
  /* Card Radius — единый responsive-токен для всех image-карточек проекта.
     Desktop 40 → Tablet 36 → Mobile 20 (по Figma design system, токен
     `Radius/Card Radius`). Переопределяется через :root в @media ниже,
     поэтому хардкодить border-radius в карточках больше не нужно. */
  --radius-card: 40px;
  --radius-btn: 100px;
  --transition: 0.4s cubic-bezier(0.16, 1, 0.3, 1);
  --ease-viscous: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-overshoot: cubic-bezier(0.3, 1.18, 0.64, 1);
  --font-sans: 'Uncut Sans Variable', 'Uncut Sans', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --composition-scale: 1;
  --page-gutter-fluid: 204px;
  --page-gutter-visible: calc(var(--page-gutter-fluid) * var(--composition-scale));
  --type-label-1-size: 90px;
  --type-label-1-line: 90px;
  --type-label-1-tracking: -0.8px;
  --type-body-4-size: 20px;
  --type-body-4-line: 24px;
  --type-body-4-tracking: 0.4px;
  --type-body-5-size: 15px;
  --type-body-5-line: 20px;
  --type-body-5-tracking: 0.4px;
  --type-weight-medium: 500;
}

html {
  overflow-x: hidden;
  scrollbar-width: none;
  /* Android Chrome рисует overlay-скроллбар корневого скроллера сам и
     игнорирует scrollbar-width/::-webkit-scrollbar — красим его в
     прозрачный через scrollbar-color (толкает и thumb, и track). */
  scrollbar-color: transparent transparent;
}

html::-webkit-scrollbar {
  display: none;
}

html.lenis, html.lenis body {
  height: auto;
}

.lenis.lenis-stopped {
  overflow: hidden;
}

.lenis.lenis-smooth {
  scroll-behavior: auto;
}

.lenis.lenis-smooth [data-lenis-prevent] {
  overscroll-behavior: contain;
}

body {
  font-family: var(--font-sans);
  background-color: var(--white);
  color: var(--black);
  line-height: 1.4;
  overflow-x: hidden;
  font-weight: 500;
  font-variation-settings: 'wght' 500;
  text-rendering: geometricPrecision;
}

.page-scale-shell {
  position: relative;
  width: 100%;
  overflow: clip;
}

.page-scale-content {
  position: relative;
  width: 1920px;
  transform-origin: top left;
  will-change: transform;
}

.page-scale-content > main,
.page-scale-content > footer {
  width: 100%;
}

a {
  color: inherit;
  text-decoration: none;
}

img, video {
  display: block;
  max-width: 100%;
}

button {
  border: none;
  background: none;
  font-family: inherit;
}

/* =============================================
   CUSTOM CURSOR — Cuberto Mouse Follower style
   ============================================= */

/* Hybrid mode: native system cursor stays visible AND the custom .cb-cursor
   dot floats on top. Goes against the original Cuberto convention (single
   custom cursor only) — kept by explicit user request. The custom cursor has
   `pointer-events: none`, so clicks pass through to native targets normally. */

.cb-cursor {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 250;
  contain: layout style size;
  pointer-events: none;
  color: var(--black);
  /* Color transition is intentionally short: when the bg under a stationary
     cursor changes (scroll into a dark section, menu open, etc.) the dot must
     re-contrast almost instantly so the user never loses it visually.
     Anything longer than ~120ms makes the cursor visibly disappear during the
     blend. */
  transition: opacity 0.3s, color 0.12s linear;
  will-change: transform;
  /* Visibility: hidden until JS sets first position */
  opacity: 0;
  --cursor-text-scale-x: 1;
  --cursor-text-scale-y: 1;
}

/* ── The dot ── */
.cb-cursor::before {
  content: "";
  position: absolute;
  top: -24px;
  left: -24px;
  display: block;
  width: 48px;
  height: 48px;
  background: currentColor;
  border-radius: 50%;
  transform: scale(0.32);
  transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1),
              opacity 0.1s;
}

/* ── Inner wrapper (pill / text state) ── */
.cb-cursor-inner {
  position: absolute;
  top: -24px;
  left: -24px;
  width: 48px;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ── Text label inside the pill ── */
.cb-cursor-text {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) scale(0) rotate(10deg);
  white-space: nowrap;
  background: var(--black);
  color: var(--white);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: 10px 22px;
  border-radius: 100px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s, transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}

/* ══════════════════════════════════════
   CURSOR STATES
   ══════════════════════════════════════ */

/* Default — dot ~15.4px (48×0.32) */
/* (set in ::before above) */

/* Active / mousedown — slightly larger */
.cb-cursor.-active::before {
  transform: scale(0.4);
}

/* Pointer — on links/buttons — slightly larger dot */
.cb-cursor.-pointer::before {
  transform: scale(0.38);
}
.cb-cursor.-pointer.-active::before {
  transform: scale(0.3);
}

/* Opaque — large expanded circle, exclusion blend */
.cb-cursor.-opaque::before {
  transform: scale(1.32);
}
.cb-cursor.-opaque.-active::before {
  transform: scale(1.2);
}

/* Drag — large + exclusion blend for drag zones */
.cb-cursor.-drag::before {
  transform: scale(1.32);
}
.cb-cursor.-drag.-active::before {
  transform: scale(1.2);
}

/* Menu — enlarged sticky circle for menu component */
.cb-cursor.-menu::before {
  transform: scale(1.32);
}
.cb-cursor.-menu.-active::before {
  transform: scale(1.2);
}

/* Text state — dot hides, pill appears */
.cb-cursor.-text::before {
  transform: scale(0);
  opacity: 0;
}
.cb-cursor.-text .cb-cursor-text {
  opacity: 1;
  transform: translate(-50%, -50%) scale(var(--cursor-text-scale-x), var(--cursor-text-scale-y)) rotate(0deg);
}
.cb-cursor.-text.-active .cb-cursor-text {
  transform: translate(-50%, -50%) scale(calc(var(--cursor-text-scale-x) * 0.92), calc(var(--cursor-text-scale-y) * 0.92)) rotate(0deg);
  transition-duration: 0.15s;
}

.cb-cursor.-explore::before {
  transform: scale(0);
  opacity: 0;
}

.cb-cursor.-explore .cb-cursor-text {
  background: var(--black);
  color: var(--white);
  border: 1px solid rgba(0, 0, 0, 0.55);
  font-size: 24px;
  font-weight: 500;
  line-height: 32px;
  letter-spacing: 0.4px;
  padding: 32px;
  border-radius: 100000px;
  transition:
    opacity 0.28s ease,
    transform 0.72s cubic-bezier(0.19, 1, 0.22, 1);
}

.cb-cursor.-explore.-inverse .cb-cursor-text {
  background: var(--white);
  color: var(--black);
  border-color: rgba(255, 255, 255, 0.55);
}

.cb-cursor.-explore.-active .cb-cursor-text {
  transform: translate(-50%, -50%) scale(calc(var(--cursor-text-scale-x) * 0.96), calc(var(--cursor-text-scale-y) * 0.96)) rotate(0deg);
}

/* Close — белый круг с чёрным крестиком поверх открытого showreel-оверлея
   (крестик = геометрия иконки меню в открытом состоянии: две линии ±45°). */
.cb-cursor.-close::before {
  transform: scale(1.32);
  background: var(--white);
}
.cb-cursor.-close.-active::before {
  transform: scale(1.2);
}
.cb-cursor.-close .cb-cursor-inner::before,
.cb-cursor.-close .cb-cursor-inner::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 18px;
  height: 2px;
  background: var(--black);
  border-radius: 1px;
}
.cb-cursor.-close .cb-cursor-inner::before {
  transform: translate(-50%, -50%) rotate(45deg);
}
.cb-cursor.-close .cb-cursor-inner::after {
  transform: translate(-50%, -50%) rotate(-45deg);
}

/* Hidden */
.cb-cursor.-hidden::before {
  transform: scale(0);
  opacity: 0;
}
.cb-cursor.-hidden .cb-cursor-text {
  opacity: 0;
  transform: translate(-50%, -50%) scale(0);
}

/* Inverse — white dot (e.g. on dark backgrounds) */
.cb-cursor.-inverse {
  color: var(--white);
}
.cb-cursor.-inverse .cb-cursor-text {
  background: var(--white);
  color: var(--black);
}

/* Exclusion blend mode — on dark sections */
@supports (mix-blend-mode: exclusion) {
  .cb-cursor.-opaque,
  .cb-cursor.-drag {
    mix-blend-mode: exclusion;
    color: var(--white);
  }

  /* Постоянная инверсия относительно фона (showreel: пёстрое видео, где
     luminance-детект бесполезен): -blend — Play-пилла, -close — крестик.
     Белые области инвертируют фон, чёрные — «вырезают» его. */
  .cb-cursor.-blend,
  .cb-cursor.-close {
    mix-blend-mode: exclusion;
  }
  .cb-cursor.-blend .cb-cursor-text {
    background: var(--white);
    color: var(--black);
    border-color: transparent;
  }
}

/* On-button color override: cursor must contrast with the .btn fill colour,
   not the ambient section. Without this a white cursor vanishes on a white
   .btn-white fill, and a black cursor vanishes on a black .btn fill. */
.cb-cursor.-on-btn-dark  { color: var(--white); }
.cb-cursor.-on-btn-light { color: var(--black); }

/* On-menu color override: the -menu circle must contrast with the section
   background, not the default cursor colour. Matched by a rule further down
   that flips the hamburger icon to the opposite colour so it stays readable
   inside the circle (Cuberto-style). */
.cb-cursor.-on-menu-dark  { color: var(--white); }
.cb-cursor.-on-menu-light { color: var(--black); }

/* =============================================
   PAGE TRANSITION OVERLAY
   ============================================= */
.page-transition {
  position: fixed;
  inset: 0;
  background: var(--black);
  z-index: 9990;
  transform: scaleY(0);
  transform-origin: bottom;
  pointer-events: none;
}

/* =============================================
   HEADER
   ============================================= */
.header {
  position: fixed;
  top: 0;
  left: 0;
  /* Контент сцены (.page-scale-content) шириной (vw − 2) из-за safety-margin
     в composition-scale (initCompositionScale: viewportWidth − 2, origin 0 0).
     Сдвигаем правый край хедера на эти 2px, иначе правый гаттер хедера на 2px
     правее контента и хедер «выглядывает» справа. */
  right: var(--composition-safety, 2px);
  z-index: 251;
  padding: 48px var(--page-gutter-visible);
  display: flex;
  align-items: center;
  justify-content: space-between;
  color: var(--black);
  /* БЕЗ transition на padding: при смене composition-scale (resize) контент
     масштабируется мгновенно (transform), а transition заставлял гаттер хедера
     отставать/залипать и не совпадать с контентом. */
}

.header-logo {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  position: relative;
  z-index: 251;
  transition:
    transform var(--transition),
    opacity var(--transition);
  will-change: transform, opacity;
}

.site-logo {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* Вращение лого — только на hover-девайсах: на touch тап залипает в
   :hover и лого остаётся повёрнутым. */
@media (hover: hover) {
  .header-logo:hover {
    transform: rotate(90deg);
  }
}

.header-right {
  display: flex;
  align-items: center;
  gap: 24px;
  position: relative;
  color: var(--black);
  white-space: nowrap;
  overflow: visible;
}

.header-menu-text {
  font-size: 24px;
  font-weight: 500;
  line-height: 32px;
  letter-spacing: 0.4px;
  color: currentColor;
  flex-shrink: 0;
  position: relative;
  z-index: 120;
  transition:
    transform var(--transition),
    opacity var(--transition);
  will-change: transform, opacity;
}

.header-menu-btn {
  width: 24px;
  height: 24px;
  display: block;
  flex-shrink: 0;
  position: relative;
  top: 1px;
  z-index: 10001;
  overflow: visible;
  color: var(--black);
  transition: color 0.55s var(--ease-viscous);
}

.header-menu-btn::before {
  content: "";
  position: absolute;
  inset: -20px;
}

.header-menu-btn span {
  display: block;
  position: absolute;
  left: 0;
  width: 24px;
  height: 2px;
  background: currentColor;
  transition: transform 0.58s var(--ease-overshoot),
              opacity 0.35s ease,
              background-color 0.55s var(--ease-viscous),
              top 0.58s var(--ease-overshoot);
  transform-origin: center;
  z-index: 1;
  will-change: transform, top;
}

.header-menu-btn span:nth-child(1) {
  top: 8px;
}

.header-menu-btn span:nth-child(2) {
  top: 14px;
}

.header-menu-btn.is-inverse {
  color: var(--white);
}

/* Whole-header inversion on dark sections — flips the logo SVG via
   `filter: invert` (turns the black-circle/white-X mark into a white circle
   with a black X to match the Figma footer/contact lockup) and colors
   "menu" white. JS toggles `.is-inverse` on `.header` in syncHeaderState. */
.header.is-inverse .site-logo {
  filter: invert(1);
}

.header.is-inverse .header-menu-text {
  color: var(--white);
}

/* Belt-and-suspenders: when menu is open, the panel slides over the right
   half of the viewport (white) — menu-btn must read as black on it. JS
   removes `is-inverse` synchronously, but during the open animation's first
   frames the inverted state can briefly leak. Higher specificity than
   `.header-menu-btn.is-inverse` guarantees the icon stays black throughout. */
html.menu-open .header-menu-btn,
html.menu-open .header-menu-btn.is-inverse {
  color: var(--black);
}

.header-right.is-hovered .header-menu-btn {
  color: var(--white);
}

/* On dark sections the cursor circle becomes white (see .cb-cursor.-on-menu-dark),
   so the icon must flip to black to stay readable inside the circle. */
.header-right.is-hovered .header-menu-btn.is-inverse {
  color: var(--black);
}

.header-menu-btn.active span:nth-child(1) {
  top: 11px;
  transform: rotate(45deg);
}

.header-menu-btn.active span:nth-child(2) {
  top: 11px;
  transform: rotate(-45deg);
}

.header.is-compact .header-logo,
.header.is-compact .header-menu-text {
  transform: translateY(calc(-100% - 16px));
  opacity: 0;
}

.header.is-compact .header-logo {
  pointer-events: none;
}

@media (hover: hover) {
  .header.is-compact .header-logo:hover {
    transform: translateY(calc(-100% - 16px));
  }
}

html.menu-open .header-right {
  color: var(--black);
}

html.menu-open .header .header-menu-text,
html.menu-open .header.is-compact .header-menu-text {
  transform: none;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

html.menu-open .header-right.is-hovered .header-menu-btn {
  color: var(--white);
}

html.menu-open .header-logo {
  transform: none;
  opacity: 1;
  pointer-events: auto;
}

html.menu-open .header.is-compact .header-logo {
  transform: none;
  opacity: 1;
  pointer-events: auto;
}

html.menu-open,
body.menu-open {
  overflow: hidden;
}

/* =============================================
   SIDE MENU
   ============================================= */
.nav-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: none;
  pointer-events: none;
}

.nav-overlay.open {
  pointer-events: auto;
}

.nav-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.18);
  opacity: 0;
}

.nav-panel {
  position: absolute;
  top: 0;
  right: 0;
  width: min(100vw, 640px);
  /* 100vh на мобильном Chrome/Safari БОЛЬШЕ видимого вьюпорта (URL-бар),
     и низ панели (Socials) уходит за фолд. dvh = реальная динамическая
     высота; 100vh остаётся фолбэком для старых браузеров. */
  height: 100vh;
  height: 100dvh;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: none;
}

.nav-panel::-webkit-scrollbar {
  display: none;
}

.nav-panel-fill {
  position: fixed;
  top: 0;
  right: 0;
  width: min(100vw, 640px);
  height: 100vh;
  background: var(--white);
  transform: scaleX(0);
  transform-origin: right center;
  box-shadow: -28px 0 80px rgba(0, 0, 0, 0.08);
  will-change: transform;
  z-index: 0;
  pointer-events: none;
}

.nav-panel-inner {
  position: relative;
  min-height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 64px;
  padding: 140px;
  will-change: transform, opacity;
  z-index: 1;
}

.nav-panel-body {
  display: flex;
  flex-direction: column;
  gap: 40px;
  width: 100%;
}

/* ── Body 5 — Section titles (Menu / Socials) ── */
.nav-panel-title {
  font-size: var(--type-body-5-size);
  font-weight: var(--type-weight-medium);
  line-height: calc(var(--type-body-5-line) / var(--type-body-5-size));
  letter-spacing: var(--type-body-5-tracking);
  color: var(--black-a55);
}

/* ── Socials block (footer of the panel) ── */
.nav-socials {
  display: flex;
  flex-direction: column;
  gap: 32px;
  width: 100%;
}

/* ── Body 4 — Social links (horizontal row) ── */
.nav-social-list {
  list-style: none;
  display: flex;
  flex-direction: row;
  gap: 32px;
  flex-wrap: wrap;
}

/* `<li>` is shrink-to-fit (flex item, no flex-grow), so its content box equals
   the `<a>` width. When the `<a>` shifts via `position: relative; left: 8px`,
   any `overflow: hidden` on the `<li>` would clip the rightmost glyphs. */
.nav-social-list a {
  display: inline-block;
  position: relative;
  left: 0;
  font-size: var(--type-body-4-size);
  font-weight: var(--type-weight-medium);
  line-height: calc(var(--type-body-4-line) / var(--type-body-4-size));
  letter-spacing: var(--type-body-4-tracking);
  color: var(--black);
  white-space: nowrap;
  transition:
    opacity 0.3s ease,
    left 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}

/* Hover соц-ссылок меню — единый Cuberto-эффект (.cb-link: линия к центру +
   инверс-курсор), см. секцию LINKS ниже. */

/* ── Label 1 — Main menu links ── */
.nav-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
}

.nav-list li {
  overflow: hidden;
  /* fit-content (не 100%) → hit-зона <li> = ширине текста + padding, а не всей
     панели. <li> статичен и НЕ уезжает при hover, поэтому слайд внутреннего
     <a> (left:14px) не выводит его из-под курсора → нет hover-петли
     («курсор судорожно прыгает у края пункта»). padding-right даёт место
     для сдвига вправо, overflow:hidden клипает выезд. */
  width: fit-content;
  max-width: 100%;
  padding-right: 20px;
}

.nav-list a {
  display: inline-block;
  position: relative;
  left: 0;
  font-size: var(--type-label-1-size);
  font-weight: var(--type-weight-medium);
  color: var(--black);
  line-height: calc(var(--type-label-1-line) / var(--type-label-1-size));
  letter-spacing: var(--type-label-1-tracking);
  padding: 2px 0;
  transition:
    opacity 0.3s ease,
    left 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}

/* Слайд драйвится hover'ом по СТАБИЛЬНОМУ <li>, а не по самому <a>: иначе
   уезжающий <a> теряет курсор и hover дребезжит (см. .nav-list li). */
.nav-list li:hover a {
  left: 14px;
}

/* Текущая страница (ставится в initMenu + aria-current="page"):
   точка-маркер слева от пункта. Дот висит в левом поле (за пределами li),
   поэтому у этого li снимаем overflow: hidden — он там только клипает
   hover-выезд вправо, который и так умещается в padding-right: 20px.
   Размеры в em — масштабируются вместе с font-size пункта на брейкпойнтах.
   Дот — ::before у <a>: едет вместе с пунктом при hover-слайде. */
.nav-list li:has(.is-current) {
  overflow: visible;
}

.nav-list a.is-current::before {
  content: '';
  position: absolute;
  left: -0.42em;
  top: 50%;
  transform: translateY(-50%);
  width: 0.15em;
  height: 0.15em;
  border-radius: 50%;
  background: currentColor;
  /* Точка НЕ участвует в hit-тесте: она висит за пределами li и едет вместе
     с <a> при hover-слайде — если бы она ловила hover, наведение на неё
     запускало бы петлю «съехал → точка ушла из-под курсора → вернулся»
     (та же петля, от которой li сделан fit-content, см. .nav-list li). */
  pointer-events: none;
}

/* =============================================
   TEXT ANIMATION UTILITY
   ============================================= */
/* Cuberto SplitText mask:"words" — маска клипает с запасом 0.2em со всех
   сторон (margin -0.2em на маске + padding 0.2em на слове = layout-
   нейтрально, дескендеры не режутся). Дублирует inline-стили из
   applyWordMaskStyles() в main.js — единый источник правды параметров. */
.word {
  display: inline-block;
  overflow: clip;
  vertical-align: top;
  margin: -0.2em;
}

/* anim-text and anim-fade: initial state set by GSAP in initTextAnimations() */
.word-inner {
  display: inline-block;
  padding: 0.2em;
}

/* =============================================
   SECTION 1 — HERO
   ============================================= */
.section-hero {
  min-height: 900px;
  padding: 0 var(--page-gutter-fluid);
  display: flex;
  align-items: flex-end;
  padding-bottom: 90px;
  position: relative;
}

.hero-content {}

.hero-top {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 0;
}

.hero-gif-slot {
  width: 182px;
  padding-top: 17px;
  padding-bottom: 11px;
  flex-shrink: 0;
}

.hero-gif {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 182px;
  height: 112px;
  border-radius: 100px;
  background: var(--gray);
  overflow: hidden;
  flex-shrink: 0;
}

.hero-gif img,
.hero-gif-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 100px;
}

.hero-gif-placeholder {
  width: 100%;
  height: 100%;
  background: linear-gradient(135deg, #ff6fd8, #3813c2, #00d2ff, #7cffcb);
  background-size: 400% 400%;
  animation: gradientShift 4s ease infinite;
  border-radius: 100px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 40px;
}

@keyframes gradientShift {
  0% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}

.hero-title {
  /* Display 2: 162/140/-8 — design-pixels (внутри page-scale-content vw даёт
     двойной шринк, см. ловушку 14.9). */
  font-size: 162px;
  font-weight: 500;
  line-height: 0.8641975309;
  letter-spacing: -0.0494em;
  color: var(--black);
}

.hero-title-line {
  display: flex;
  align-items: center;
  gap: 48px;
  overflow: hidden;
  padding-bottom: 0.16em;
  margin-bottom: -0.16em;
}

.hero-title-line-inner {
  display: flex;
  align-items: center;
  gap: 48px;
  padding-bottom: 0.02em;
  transform: translateY(110%);
  transition: transform 1s cubic-bezier(0.16, 1, 0.3, 1);
}

.hero-title-line-inner.line-2 {
  transition-delay: 0.15s;
}

.hero-title-line.is-visible .hero-title-line-inner {
  transform: translateY(0);
}

/* Hero gif has TWO possible homes in DOM (one slot per visual layout):
     • .hero-gif-slot--inline   — line-1, after "Product"  (desktop default)
     • .hero-gif-slot--leading  — line-2, before "Designer" (tablet/phone)
   By default we only show the inline slot. The leading slot and the 3rd
   line ("& Engineer") are revealed inside the tablet/phone media queries.
   See initHeroGifSlot() in main.js for runtime placement. */
.hero-gif-slot--leading {
  display: none;
}
.hero-title-line--mobile-only {
  display: none;
}

/* =============================================
   SECTION 2 — VIDEO/IMAGE
   ============================================= */
.section-video {
  width: 100%;
  /* Figma 201:445 — 1920×1080 (16:9). aspect-ratio в design-pixels вместо vw,
     иначе высота (vw) скейлится дважды и ломает соотношение на sub-1920. */
  aspect-ratio: 1920 / 1080;
  background: var(--black);
  overflow: hidden;
  position: relative;
}

.section-video-inner {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.85;
}

/* =============================================
   SHOWREEL FULLSCREEN OVERLAY (Cuberto-style)
   Создаётся динамически в initShowreelOverlay(). z-index 249 — ПОД кастомным
   курсором (250), который рисует крестик; хедер (251) прячется классом на
   body. Живёт вне .page-scale-content — размеры в реальных viewport px.
   ============================================= */
.video-overlay {
  position: fixed;
  inset: 0;
  z-index: 249;
  background: var(--black);
  display: none;
  align-items: center;
  justify-content: center;
}

.video-overlay.is-open {
  display: flex;
}

.video-overlay-video {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* Крестик-кнопка — только для touch (на fine pointer крестик рисует
   кастомный курсор). Геометрия линий — как у .header-menu-btn в открытом
   состоянии (две линии ±45°), белая на чёрном фоне оверлея. */
.video-overlay-close {
  display: none;
  position: fixed;
  top: 20px;
  right: 20px;
  width: 48px;
  height: 48px;
  padding: 0;
  background: transparent;
  border: 0;
  cursor: pointer;
}

.video-overlay-close span {
  position: absolute;
  left: 12px;
  top: 23px;
  width: 24px;
  height: 2px;
  background: var(--white);
  border-radius: 1px;
}

.video-overlay-close span:first-child {
  transform: rotate(45deg);
}

.video-overlay-close span:last-child {
  transform: rotate(-45deg);
}

/* Кнопка-крестик видна на touch-девайсах И на mobile/tablet ширинах —
   там курсорный -close отключён, закрытие только через неё. */
@media (hover: none), (max-width: 1279px) {
  .video-overlay-close {
    display: block;
  }
}

/* Пока showreel открыт — хедер спрятан (меню недоступно, как у Cuberto).
   !important — намеренно: initHeroAnimation (gsap.from) оставляет на .header
   inline `opacity: 1`, который иначе перекрывает это правило. */
body.video-overlay-open .header {
  opacity: 0 !important;
  pointer-events: none;
  transition: opacity 0.25s ease;
}

.section-video-placeholder {
  width: 100%;
  height: 100%;
  background: var(--black);
  display: flex;
  align-items: center;
  justify-content: center;
}

.section-video-placeholder svg {
  width: 80px;
  height: 80px;
  color: rgba(255,255,255,0.15);
}

/* =============================================
   SECTION 3 — ABOUT TEASER
   ============================================= */
.section-about {
  padding: 160px var(--page-gutter-fluid);
}

.section-about-inner {
  /* Figma 201:447 — блок 936px, прижат к правому краю (justify-end). */
  max-width: 936px;
  margin-left: auto;
  padding-right: 0;
}

.section-about-text {
  /* Body 1: 40/48/0 — design-pixels (см. ловушку 14.9). */
  font-size: 40px;
  font-weight: 500;
  line-height: 48px;
  letter-spacing: 0;
  color: var(--black);
  margin-bottom: 64px;
}

/* anim-fade--about-text and anim-fade--about-cta: timing controlled by GSAP */

/* =============================================
   BUTTONS
   ============================================= */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--black);
  border-radius: var(--radius-btn);
  padding: 0 28px;
  min-height: 64px;
  font-family: inherit;
  font-size: clamp(20px, 1.4583333333vw, 28px);
  font-weight: 500;
  font-variation-settings: 'wght' 500;
  line-height: 1.3571428571;
  letter-spacing: 0.0143em;
  color: var(--black);
  background: transparent;
  position: relative;
  overflow: hidden;
  /* `will-change: transform` хинт для компоузера — JS-таймлайн (Cuberto-jelly
     squash в initCursor → updateForcedBtn) каждый hover-enter крутит
     scaleX/scaleY через GSAP. */
  will-change: transform;
  transition: color 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}

.btn::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--black);
  border-radius: var(--radius-btn);
  transform: translateY(101%);
  border-radius: 50% 50% 0 0;
  transition: transform 0.5s cubic-bezier(0.4, 0, 0, 1),
              border-radius 0.5s cubic-bezier(0.4, 0, 0, 1);
}

/* Hover-заливка — ТОЛЬКО на hover-девайсах: на touch тап «залипает» в
   :hover, и кнопка остаётся залитой после касания. .is-hover ставит
   только desktop-трекер в initCursor (на touch он выключен) — ему
   медиа-гейт не нужен. */
@media (hover: hover) {
  .btn:hover::before {
    transform: translateY(0);
    border-radius: 0;
  }

  .btn:hover {
    color: var(--white);
    border-color: var(--black);
  }
}

.btn.is-hover::before {
  transform: translateY(0);
  border-radius: 0;
}

.btn.is-hover {
  color: var(--white);
  border-color: var(--black);
}

.btn span {
  position: relative;
  z-index: 1;
}

/* Short label is hidden by default — only revealed inside the mobile footer
   social row, see the @media block at the bottom of this file. */
.btn-text-short {
  display: none;
}

.btn-white {
  border-color: var(--white);
  color: var(--white);
}

.btn-white::before {
  background: var(--white);
}

@media (hover: hover) {
  .btn-white:hover {
    color: var(--black);
    border-color: var(--white);
  }
}

.btn-white.is-hover {
  color: var(--black);
  border-color: var(--white);
}

.btn-large {
  min-height: 102px;
  padding: 0 40px;
  /* Body 2: 28/38/0.2 — design-pixels (override базового .btn clamp(vw),
     иначе двойной шринк внутри page-scale-content, см. ловушку 14.9). */
  font-size: 28px;
  line-height: 38px;
  letter-spacing: 0.2px;
}

/* =============================================
   SECTION 4 — RECENT WORK (FEATURED)
   ============================================= */
.section-featured {
  padding: 0 var(--page-gutter-fluid) 80px;
}

.section-label {
  /* Label 1: 90/90/-0.8 — design-pixels (см. ловушку 14.9). */
  font-size: 90px;
  font-weight: 500;
  line-height: 90px;
  letter-spacing: -0.0089em;
  margin-bottom: 64px;
  color: var(--black);
}

.featured-grid {
  display: grid;
  /* Figma 201:452 — Big (flex 936) + Special 552, gap 24. */
  grid-template-columns: minmax(0, 1fr) 552px;
  gap: 24px;
  align-items: center;
}

.card-big {
  border-radius: var(--radius-card);
  overflow: hidden;
  background: var(--gray);
  height: 700px;
  position: relative;
  display: block;
}

.card-big img,
.card-big-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.card-special {
  border-radius: var(--radius-card);
  overflow: hidden;
  /* Figma 201:454 — Special card bg = gray-900 (#111213), не чистый чёрный. */
  background: #111213;
  width: 552px;
  height: 700px;
  position: relative;
  display: block;
}

.card-special img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.6;
}

.card-info {
  position: absolute;
  inset: 0;
  padding: 32px 40px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  color: var(--white);
}

.card-info-top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 40px;
  font-weight: 500;
  line-height: 48px;
  letter-spacing: 0;
  opacity: 1;
}

.card-info-bottom {
  font-size: 72px;
  font-weight: 500;
  line-height: 86px;
  letter-spacing: -0.8px;
}

/* =============================================
   SECTION 5 — HORIZONTAL SCROLL WORKS
   ============================================= */
.section-works {
  /* Figma 201:455 — без верхнего паддинга (отступ даёт pb-80 у featured). */
  padding: 0 0 160px;
}

.section-works-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--page-gutter-fluid);
  margin-bottom: 64px;
}

.works-drag-pill {
  --works-drag-pill-expanded-width: 194px;
  --works-drag-pill-expanded-height: 72px;
  --works-drag-pill-collapsed-width: 97px;
  --works-drag-ball-travel: 40px;
  --works-drag-pill-color: 0, 0, 0;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--works-drag-pill-expanded-width);
  height: var(--works-drag-pill-expanded-height);
  overflow: visible;
  pointer-events: none;
}

.works-drag-pill::before {
  content: '';
  position: absolute;
  top: calc(50% - 4px);
  left: calc(50% - 4px);
  display: block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(var(--works-drag-pill-color), 1);
  animation: worksDragBall 3s cubic-bezier(0.55, 0, 0.1, 1) infinite;
}

.works-drag-pill-dot {
  display: none;
}

.works-drag-pill-text {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: var(--works-drag-pill-expanded-height);
  padding: 24px 32px;
  /* Единый стандарт: у ВСЕХ кнопок (и зеркалящей их drag-пиллы)
     бордер 1px на всех брейкпойнтах. */
  border: 1px solid rgba(var(--works-drag-pill-color), 1);
  border-radius: 999px;
  overflow: hidden;
  white-space: nowrap;
  font-size: 20px;
  font-weight: 500;
  line-height: 24px;
  letter-spacing: 0.4px;
  color: rgba(var(--works-drag-pill-color), 1);
  animation: worksDragBtn 3s cubic-bezier(0.55, 0, 0.1, 1) infinite;
}

@keyframes worksDragBall {
  0% {
    transform: translateX(calc(var(--works-drag-ball-travel) * -1)) scale(0);
    opacity: 0;
  }
  20%, 70% {
    opacity: 1;
  }
  50% {
    transform: translateX(0) scale(1);
    opacity: 0;
  }
  100% {
    transform: translateX(var(--works-drag-ball-travel)) scale(0);
    opacity: 0;
  }
}

@keyframes worksDragBtn {
  0%, 100% {
    transform: translateY(0);
    color: rgba(var(--works-drag-pill-color), 1);
    width: 100%;
  }
  50% {
    transform: translateY(0);
    color: rgba(var(--works-drag-pill-color), 0);
    width: var(--works-drag-pill-collapsed-width);
  }
  15%, 65% {
    color: rgba(var(--works-drag-pill-color), 0);
  }
}

.works-label {
  font-size: 40px;
  font-weight: 500;
  line-height: 48px;
  letter-spacing: 0;
}

.works-scroll-container {
  overflow: hidden;
  padding: 0 var(--page-gutter-fluid);
  cursor: grab;
  overscroll-behavior: contain;
  touch-action: pan-y;
}

.works-scroll-container.is-dragging {
  cursor: grabbing;
}

.works-scroll-container.is-dragging .card-work {
  pointer-events: none;
}

/* Touch-режим карусели: НАТИВНЫЙ горизонтальный скролл (физика компоузера
   1:1 с вертикальной). Ставится в initDragScroll при coarse pointer.
   touch-action перекрывает базовый pan-y — иначе браузер не отдаст
   горизонтальный пан нативному скроллеру. */
.works-scroll-container.is-native-scroll {
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -ms-overflow-style: none;
  touch-action: pan-x pan-y;
  overscroll-behavior-x: contain;
  cursor: default;
}

.works-scroll-container.is-native-scroll::-webkit-scrollbar {
  display: none;
}

.works-scroll-container::-webkit-scrollbar {
  display: none;
}

.works-track {
  display: flex;
  gap: 24px;
  width: max-content;
  align-items: flex-start;
  will-change: transform;
}

.card-work {
  width: 848px;
  flex-shrink: 0;
  display: block;
}

.section-works .card-work.anim-fade,
.section-works .card-work.anim-fade.is-visible {
  opacity: 1;
  transform: none;
  transition: none;
}

.card-work-image {
  width: 100%;
  height: 630px;
  border-radius: var(--radius-card);
  overflow: hidden;
  background: var(--gray);
  margin-bottom: 40px;
  position: relative;
}

.card-work-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
}

.card-work-placeholder {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.card-work-title {
  font-size: 40px;
  font-weight: 500;
  line-height: 48px;
  letter-spacing: 0;
  margin-bottom: 12px;
}

.card-work-type {
  font-size: 28px;
  color: var(--black);
  font-weight: 500;
  line-height: 38px;
  letter-spacing: 0.2px;
}

/* =============================================
   CARD BADGE (Figma 690:22244 — «Coming Soon» / «NDA»)
   ─────────────────────────────────────────────
   Белая пилюля в левом нижнем углу картинки карточки. Живёт ТОЛЬКО на
   locked-карточках (проекты без кейс-страницы): на desktop появляется по
   hover'у (вместо Explore-курсора), на touch/mobile — видна ПОСТОЯННО,
   чтобы было ясно, что провалиться внутрь нельзя.
   Разметка: <span class="card-badge">NDA</span> внутри .card-work-image /
   .work-card-image (у обоих контейнеров position: relative).
   ============================================= */
.card-badge {
  position: absolute;
  left: 24px;
  bottom: 24px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 24px 32px;
  background: var(--white);
  -webkit-backdrop-filter: blur(20px);
  backdrop-filter: blur(20px);
  border-radius: 20px;
  /* Body 3: 24/32/0.4 */
  font-size: 24px;
  line-height: 32px;
  letter-spacing: 0.4px;
  font-weight: 500;
  color: var(--black);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transform: translateY(10px) scale(0.94);
  transition:
    opacity 0.4s var(--ease-viscous),
    transform 0.5s var(--ease-viscous);
}

/* Locked-карточка — не ссылка: обычный системный курсор, кастомная точка
   НЕ трансформируется в Explore (data-cursor-explore на них не ставится). */
.card-work--locked,
.work-card--locked {
  cursor: default;
}

.card-work--locked:hover .card-badge,
.work-card--locked:hover .card-badge {
  opacity: 1;
  transform: none;
}

/* Touch-девайсы (ховера нет) — бейдж виден постоянно. */
@media (hover: none) {
  .card-badge {
    opacity: 1;
    transform: none;
  }
}

.works-btn-wrap {
  display: flex;
  justify-content: center;
  margin-top: 80px;
}

.works-btn-wrap .btn-large {
  width: 312px;
  min-height: 102px;
  padding: 0 40px;
  font-size: 28px;
  line-height: 38px;
  letter-spacing: 0.2px;
}

/* =============================================
   FOOTER
   ============================================= */
.footer {
  background: var(--black);
  color: var(--white);
  padding: 160px 0 48px;
  overflow: hidden;
  position: relative;
  box-shadow: 0 3px 0 0 var(--black);
}

.footer-inner {
  padding: 0 var(--page-gutter-fluid);
}

.footer-top {
  display: flex;
  flex-direction: column;
  gap: 160px;
  margin-bottom: 160px;
}

.footer-heading {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.footer-heading-line {
  display: flex;
  align-items: center;
  gap: 40px;
  font-size: 162px;
  font-weight: 500;
  line-height: 140px;
  letter-spacing: -8px;
  color: var(--white);
  white-space: nowrap;
}

.footer-heading-line--bottom {
  display: block;
}

.footer-gif {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 182px;
  height: 112px;
  border-radius: 100px;
  background: rgba(255,255,255,0.1);
  overflow: hidden;
  flex-shrink: 0;
}

.footer-gif img,
.footer-gif video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}


.footer-gif-placeholder {
  width: 100%;
  height: 100%;
  background: linear-gradient(135deg, #ff6fd8, #3813c2, #00d2ff);
  background-size: 400% 400%;
  animation: gradientShift 3s ease infinite;
  border-radius: 100px;
}

.footer-contacts {
  display: grid;
  grid-template-columns: minmax(0, 843px) max-content;
  align-items: start;
  justify-content: space-between;
  gap: 48px 40px;
}

.footer-contacts-group {
  min-width: 0;
  display: block;
}

.footer-contacts-group--email {
  justify-self: end;
}

.footer-contacts-label {
  font-size: 28px;
  font-weight: 500;
  line-height: 38px;
  letter-spacing: 0.2px;
  color: var(--white);
  margin-bottom: 40px;
  text-transform: none;
}

.footer .btn {
  min-height: 112px;
  padding: 0 48px;
  font-size: 40px;
  line-height: 48px;
  letter-spacing: 0;
}

.footer-contacts-btns {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
}

.footer-contacts-group--social .footer-contacts-btns {
  flex-wrap: nowrap;
}

/* =============================================
   RUNNING LINE
   ============================================= */
.running-line {
  width: 100%;
  overflow: hidden;
  margin-bottom: 104px;
}

.running-line-track {
  display: flex;
  width: max-content;
  white-space: nowrap;
  will-change: transform;
  animation: footerMarquee var(--running-line-duration, 24s) linear infinite;
}

@keyframes footerMarquee {
  0% { transform: translateX(0); }
  100% { transform: translateX(-50%); }
}

.running-line-sequence {
  display: flex;
  align-items: center;
  gap: 24px;
  flex-shrink: 0;
  padding-right: 24px;
}

.running-line-text {
  font-size: 354px;
  font-weight: 500;
  letter-spacing: -14.64px;
  color: var(--white);
  line-height: 319px;
}

.running-line-card {
  width: 248px;
  height: 248px;
  border-radius: var(--radius-card);
  overflow: hidden;
  background: rgba(255,255,255,0.1);
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* —— Image sequence в карточках бегущей строки (fix.studio-style) ——
   Кадры лежат стопкой (absolute), виден только активный — жёсткая смена
   через visibility каждые 330ms (initRunningLineSequence), БЕЗ fade.
   Без JS виден первый кадр. data-seq-offset сдвигает фазу карточки, чтобы
   соседние не мигали одинаковыми кадрами; у клон-sequence офсеты те же —
   бесшовный loop сохраняется. Референс: image-sequence на fix.studio. */
.running-line-card {
  position: relative;
}

.running-line-card img {
  position: absolute;
  inset: 0;
  visibility: hidden;
}

.running-line-card img:first-child {
  visibility: visible; /* no-JS fallback */
}

.running-line-card img.is-active {
  visibility: visible;
}

.running-line-card.is-sequencing img:first-child:not(.is-active) {
  visibility: hidden;
}

.running-line-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* =============================================
   FOOTER BOTTOM
   ============================================= */
.footer-bottom {
  border-top: 1px solid rgba(255,255,255,0.14);
}

.footer-bottom-inner {
  padding: 24px var(--page-gutter-fluid) 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.footer-bottom-left {
  display: flex;
  align-items: center;
  gap: 24px;
}

.footer-bottom,
.footer-bottom a,
.footer-bottom span {
  font-size: 13.5px;
  font-weight: 500;
  line-height: 1.3333333333;
  letter-spacing: 0.0267em;
  color: var(--white);
}

.footer-bottom-left span,
.footer-bottom a {
  width: 194px;
}

.footer-bottom a {
  text-align: right;
  transition: opacity 0.3s;
}

.footer-bottom a:hover {
  opacity: 0.68;
}

/* =============================================
   LINKS — Cuberto «Launch project» (контент-ссылки, не меню/кнопки)
   ─────────────────────────────────────────────
   Ссылка подчёркнута; на hover линия УХОДИТ (втягивается вправо), а курсор
   превращается в большой инверс-кружок (-opaque, exclusion — навешивается в
   initCursor). Хук — класс `.cb-link`. На touch (no hover) — статичное
   подчёркивание. Подробно см. CLAUDE.md (инвариант 22).
   ============================================= */
.cb-link,
.nav-social-list a {
  text-decoration: none;
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-size: 100% 1px;
  /* центр → на hover линия втягивается к центру с обоих концов */
  background-position: 50% 100%;
  transition: background-size 0.45s cubic-bezier(0.16, 1, 0.3, 1);
}

@media (hover: hover) {
  .cb-link:hover,
  .nav-social-list a:hover {
    background-size: 0 1px;
  }
}

/* =============================================
   WORK PLACEHOLDER COLORS
   ============================================= */
.card-placeholder-1 {
  background: linear-gradient(135deg, #e8f4f8, #c3e0f0);
}
.card-placeholder-2 {
  background: #1a1a1a;
}
.card-placeholder-3 {
  background: #2a2a3e;
}
.card-placeholder-4 {
  background: linear-gradient(135deg, #f0e8f8, #d0c0f0);
}

/* =============================================
   PAGE-SPECIFIC: WORK, ABOUT, CONTACT
   ============================================= */
.page-hero {
  min-height: 800px;
  padding: 200px var(--page-gutter-fluid) 90px;
  display: flex;
  align-items: flex-end;
}

.page-hero-title {
  font-size: 354px;
  font-weight: 500;
  line-height: 0.9;
  letter-spacing: -14.64px;
  white-space: nowrap;
}

/* Work grid */
.work-grid {
  padding: 0 var(--page-gutter-fluid) 160px;
  display: flex;
  flex-direction: column;
  gap: 80px;
}

.work-section {
  display: flex;
  gap: 24px;
  align-items: flex-start;
}

.work-card {
  display: flex;
  flex-direction: column;
  gap: 40px;
  min-width: 0;
  position: relative;
}

/* Figma 336:614 / 336:603 — wide заполняет ряд (936), narrow фикс 552. */
.work-card--wide {
  flex: 1 0 0;
}

.work-card--narrow {
  width: 552px;
  flex-shrink: 0;
}

.work-card--full {
  flex: 1 0 0;
}

.work-card-image {
  width: 100%;
  /* Figma 336:616 etc. — высота карточки-изображения 552 (wide 936×552,
     narrow 552×552 квадрат, full 1512×552). */
  height: 552px;
  overflow: hidden;
  border-radius: var(--radius-card);
  background: var(--gray);
  /* Якорь для .card-badge */
  position: relative;
}

.work-card-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* =============================================
   PROJECT CARD HOVER — Cuberto-style subtle scale-down
   ─────────────────────────────────────────────
   Reference: https://hkdevelopers.vercel.app/projects.html
   На hover карточка-изображение плавно ужимается до 0.97 с expo.out.
   Featured-карточки (`.card-big` / `.card-special`) скейлят сами себя
   (они и есть image-блок). Карусельные/grid-карточки скейлят только
   `<image>`-вложение — заголовок/мета снизу остаются на месте.
   Под `@media (hover: hover)` — на touch hover'а нет, иначе после
   тапа карточка зависнет в уменьшенном состоянии.
   ============================================= */
@media (hover: hover) {
  .card-big,
  .card-special,
  .card-work-image,
  .work-card-image {
    transition: transform 0.6s cubic-bezier(0.16, 1, 0.3, 1);
    will-change: transform;
  }

  .card-big:hover,
  .card-special:hover,
  .card-work:hover .card-work-image,
  .work-card:hover .work-card-image {
    transform: scale(0.97);
  }
}

.work-card-info {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.work-card-title {
  font-size: 40px;
  font-weight: 500;
  line-height: 48px;
  letter-spacing: 0;
}

.work-card-meta {
  font-size: 28px;
  color: var(--black);
  font-weight: 500;
  line-height: 38px;
  letter-spacing: 0.2px;
}

/* =============================================
   ABOUT PAGE (Figma 354:662 / 355:1808 / 355:2064)
   ─────────────────────────────────────────────
   3 sections:
     1. .page-hero.page-hero--about — "About" Display 1 title
     2. .about-photo-band            — full-width portrait (Me_1), Section_2
     3. .about-content               — Intro text + inline photo (Me_2)
                                       + Experience list, Section_3
   ============================================= */

/* —— Section_2_Animation: фото-бэнды (portrait Me_11 + group Me_2) ————————
   Portrait — full-bleed во всю ширину вьюпорта на ВСЕХ брейкпойнтах
   (как showreel-видео на главной: edge-to-edge, 16:9, без радиуса).
   Group (Me_2) — внутри гаттера, rounded 40 (Figma 540:15182 = 1512×756). */
.about-photo-band {
  width: 100%;
  padding: 0 var(--page-gutter-fluid);
}

.about-photo-band-inner {
  width: 100%;
  overflow: hidden;
  background: var(--gray);
  border-radius: var(--radius-card);
}

.about-photo-band--portrait {
  padding: 0;
}

.about-photo-band--portrait .about-photo-band-inner {
  aspect-ratio: 1920 / 1080;
  border-radius: 0;
}

.about-photo-band--group .about-photo-band-inner {
  aspect-ratio: 1512 / 756;
}

.about-photo-band-inner img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  /* Parallax allowance: картинка отскейлена 1.15 — JS-scrub в
     initAboutParallax двигает yPercent в диапазоне ±8, и эта «припуск» по
     обеим сторонам не даёт обнажиться серому фону контейнера. */
  transform: scale(1.15);
  transform-origin: center;
  will-change: transform;
}

/* —— Section 3: Intro paragraphs + CV / Experience ———————————————————— */
.about-content {
  padding: 160px var(--page-gutter-fluid);
}

/* Контент центрирован, max 1128px (Figma Div px-192 внутри 1512). */
.about-intro {
  max-width: 1128px;
  width: 100%;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 64px;
  align-items: flex-start;
}

.about-intro-text {
  display: flex;
  flex-direction: column;
  gap: 40px;
}

.about-intro-text p {
  /* Body 1: 40/48/0 */
  font-size: 40px;
  line-height: 48px;
  letter-spacing: 0;
  font-weight: 500;
  color: var(--black);
}

.about-intro-cv {
  align-self: flex-start;
  /* Body 2 в design-pixels (override базового .btn clamp(vw) — ловушка 14.9). */
  font-size: 28px;
  line-height: 38px;
  letter-spacing: 0.2px;
}

/* Experience list — rows of 98px content separated by 1px hairlines */
.about-experience {
  list-style: none;
  margin: 0 auto;
  padding: 0;
  max-width: 1128px;
  width: 100%;
  display: flex;
  flex-direction: column;
}

.about-experience-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 40px 0;
  /* Hairline-разделители раньше жили здесь как border-top + border-bottom.
     Теперь их рисует JS (initLineStrings → <li class="experience-line">),
     чтобы каждая линия могла «играть как струна» — Cuberto-стайл. */
}

/* ===== Cuberto-style «string» hairline =====
   Вставляется JS'ом перед каждой `.about-experience-row` + одна после
   последнего ряда. Снаружи 60px высокий «hit-зона», layout-нейтральная
   (margin: -30px 0 → итоговая высота 0). SVG-path растягивается через
   preserveAspectRatio="none" и сидит на y=30 в viewBox = идеально по центру
   зоны = ровно на границе двух рядов (там, где раньше был border). На
   hover path морфится в Q-Bezier через GSAP. */
.experience-line {
  list-style: none;
  position: relative;
  z-index: 1;
  width: 100%;
  height: 60px;
  margin: -30px 0;
}

.experience-line-svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  overflow: visible;
  pointer-events: none;
}

.experience-line-path {
  stroke: var(--black-a55);
  /* non-scaling-stroke — толщина 1px в screen-space независимо от того, что
     viewBox растягивается через preserveAspectRatio="none". */
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
  fill: none;
}

.about-experience-left {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
}

.about-experience-title {
  /* Body 1 */
  font-size: 40px;
  line-height: 48px;
  letter-spacing: 0;
  font-weight: 500;
  color: var(--black);
}

.about-experience-role,
.about-experience-date {
  /* Body 2 */
  font-size: 28px;
  line-height: 38px;
  letter-spacing: 0.2px;
  font-weight: 500;
  color: var(--black);
}

.about-experience-date {
  flex-shrink: 0;
}

/* =============================================
   CONTACT PAGE (Figma 355:3079 — Desktop / Tablet / Phone)
   ─────────────────────────────────────────────
   Page layout мirrors the global footer (heading + contacts + running line +
   bottom). Header & menu auto-invert because `.footer` is in
   initScrollEffects' dark-section list.
   ============================================= */

/* Фон страницы Contact — чёрный по дефолту: страница целиком тёмная, и
   при любой высоте вьюпорта/шелла под контентом никогда не мелькнёт
   белый body (класс на <body> в contact.html). */
body.page-contact {
  background: var(--black);
}

.contact-main {
  /* Override `.footer { padding-top: 160px }` — on Contact, the heading
     sits below the fixed header per Figma's Top group:
       padding-top (Figma 48) + header height (~36) + gap-300 = 384.
     On tablet:  43.2 + 32.4 + 200 ≈ 276; on phone: 20 + 28 + 200 = 248. */
  padding-top: 384px;
  /* Страница короче вьюпорта (после удаления видео-бэнда) оставляла бы
     белую полосу body под чёрным блоком. Тянем main минимум на высоту
     экрана (svh/scale — design-координаты, см. инвариант 18) и прижимаем
     footer-bottom к низу. */
  min-height: calc(100svh / var(--composition-scale));
  display: flex;
  flex-direction: column;
}

.contact-main .footer-bottom {
  margin-top: auto;
}

/* =============================================
   VKUI CASE STUDY (Figma 592:40228 — Desktop / Tablet / Phone)
   ============================================= */
/* —— Section 1: Hero — Display 2, 2 lines, bottom-aligned —— */
.vkui-hero {
  min-height: 800px;
  padding: 0 var(--page-gutter-fluid) 90px;
  display: flex;
  align-items: flex-end;
}

.vkui-hero-title {
  /* Display 2: 162/140/-8 */
  font-size: 162px;
  font-weight: 500;
  line-height: 140px;
  letter-spacing: -8px;
  color: var(--black);
}

.vkui-hero-title .hero-title-line {
  padding-bottom: 0.16em;
  margin-bottom: -0.16em;
}

/* "VK" short variant only shows on phone */
.vkui-hero-short {
  display: none;
}

/* —— Photo / gallery bands (gutter, rounded 40) —— */
.vkui-band--hero {
  padding: 0 var(--page-gutter-fluid);
}

.vkui-gallery {
  padding: 0 var(--page-gutter-fluid);
  display: flex;
  flex-direction: column;
  gap: 24px;
}

/* Mobile-only вариант галереи (особый порядок картинок) — скрыт на
   desktop/tablet, показывается в phone-медиазапросе. */
.vkui-gallery--narrow {
  display: none;
}

.vkui-band-row {
  display: flex;
  gap: 24px;
}

.vkui-band-inner {
  width: 100%;
  overflow: hidden;
  background: var(--gray);
  border-radius: var(--radius-card);
  /* Full band: 1512×756 (2:1). */
  aspect-ratio: 1512 / 756;
}

.vkui-band--hero .vkui-band-inner {
  aspect-ratio: 1512 / 850;
}

.vkui-band-row .vkui-band-inner {
  flex: 1 0 0;
  min-width: 0;
  /* 2-up: 744×756. */
  aspect-ratio: 744 / 756;
}

.vkui-band-inner img,
.vkui-band-inner video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Band, существующий ТОЛЬКО на мобилке (например, широкая картинка с тремя
   телефонами на desktop разбивается на 3 отдельных мобильных бэнда —
   IMG_1 → IMG_1_1..1_3_Mobile на VK ID). Показывается в phone-медиа. */
.vkui-band--mobile-only {
  display: none;
}

/* —— Hairline — Cuberto-«струна» (JS: wireStringLine). 60px hit-зона,
   layout-нейтральная (margin -30 → итог 0), SVG-path по центру. —— */
.vkui-line {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 60px;
  margin: -30px 0;
}

/* —— Info / text sections —— */
.vkui-info,
.vkui-section {
  padding: 160px var(--page-gutter-fluid);
}

.vkui-section {
  display: flex;
  flex-direction: column;
  gap: 48px;
}

.vkui-section-title {
  /* Label 1: 90/90/-0.8 */
  font-size: 90px;
  font-weight: 500;
  line-height: 90px;
  letter-spacing: -0.8px;
  color: var(--black);
}

/* 2-col: label (360) + content (flex-1), gap 24 */
.vkui-cols {
  display: flex;
  gap: 24px;
  align-items: flex-start;
}

.vkui-col-label {
  /* Body 2: 28/38/0.2 */
  width: 360px;
  flex-shrink: 0;
  font-size: 28px;
  font-weight: 500;
  line-height: 38px;
  letter-spacing: 0.2px;
  color: var(--black);
}

.vkui-col-body {
  flex: 1 0 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 48px;
}

.vkui-body-text {
  /* Body 1: 40/48/0 */
  font-size: 40px;
  font-weight: 500;
  line-height: 48px;
  letter-spacing: 0;
  color: var(--black);
}

/* —— Meta (Dates / Role / Links) —— */
.vkui-meta {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.vkui-meta-row {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.vkui-meta-row dt {
  font-size: 28px;
  font-weight: 500;
  line-height: 38px;
  letter-spacing: 0.2px;
  color: var(--black-a55);
}

.vkui-meta-row dd {
  margin: 0;
  font-size: 28px;
  font-weight: 500;
  line-height: 38px;
  letter-spacing: 0.2px;
  color: var(--black);
}

.vkui-meta-row dd a {
  color: inherit;
}

/* —— Result + stats —— */
.vkui-col-body--result {
  gap: 64px;
}

.vkui-stats {
  display: flex;
  gap: 32px;
}

.vkui-stat {
  flex: 1 0 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.vkui-stat-num {
  /* Label 1: 90/90/-0.8 */
  font-size: 90px;
  font-weight: 500;
  line-height: 90px;
  letter-spacing: -0.8px;
  color: var(--black);
}

.vkui-stat-label {
  /* Body 2 */
  font-size: 28px;
  font-weight: 500;
  line-height: 38px;
  letter-spacing: 0.2px;
  color: var(--black);
}

/* —— "More projects" carousel —— */
.section-works--vkui {
  padding-top: 160px;
}

.section-works--vkui .card-work {
  width: 744px;
}

/* =============================================
   RESPONSIVE
   ============================================= */
/* Web: 1280px+ */
@media (min-width: 1280px) {
  :root {
    --page-gutter-fluid: 204px;
  }

  .header {
    padding: 48px var(--page-gutter-visible);
  }
}

/* Tablet: 768px - 1279px
   Source of truth: Figma "Home / Tablet" 201:466 (1024 design width).
   Numbers below are in the 1024 design space — composition scale handles
   visual scaling for actual viewport widths 768–1279px. */
@media (min-width: 768px) and (max-width: 1279px) {
  :root {
    --page-gutter-fluid: 60px;
    --radius-card: 36px;
  }

  /* —— Nav overlay ————————————————————————— */
  .nav-panel,
  .nav-panel-fill {
    width: min(100vw, 500px);
  }
  .nav-panel-inner {
    padding: 80px;
    gap: 48px;
  }
  .nav-panel-body {
    gap: 36px;
  }
  .nav-list {
    gap: 14.4px;
  }
  .nav-list a {
    font-size: 81px;
    line-height: 81px;
    letter-spacing: -0.72px;
  }
  .nav-socials {
    gap: 28px;
  }
  .nav-social-list {
    gap: 28.8px;
  }
  .nav-social-list a {
    font-size: 18px;
    line-height: 21.6px;
    letter-spacing: 0.36px;
  }
  .nav-panel-title {
    font-size: 13.5px;
    line-height: 18px;
    letter-spacing: 0.36px;
  }

  /* —— Header ——————————————————————————————— */
  .header {
    padding: 40px var(--page-gutter-visible);
  }

  /* —— Section 1: Hero (Figma 201:467) ———————
     3 visual lines: "Product" / "[gif] Designer" / "& Engineer".
     Title typography: 143.163 / 123.721 / -7.0698, row gap 8.837.
     Inline gif slot (line-1) hidden; leading slot (line-2) shown.   */
  .section-hero {
    min-height: calc(700px / var(--composition-scale));
    height: calc(700px / var(--composition-scale));
    padding: 0 var(--page-gutter-fluid) 40px;
    align-items: flex-end;
    /* Hard clip any horizontal overshoot of the title (e.g. during the brief
       frame between a CSS media-query flip and the JS composition-scale
       update). Without this, large hero glyphs can momentarily extend past
       the right edge on viewport transitions. */
    overflow-x: clip;
  }

  .hero-title {
    font-size: 143.163px;
    line-height: 123.721px;
    letter-spacing: -7.0698px;
  }

  .hero-title-line {
    gap: 0;
    /* Keep descender clearance so "g" in Designer/Engineer isn't clipped by
       overflow:hidden (line-height < font-size). Mirrors the desktop rule. */
    padding-bottom: 0.16em;
    margin-bottom: -0.16em;
    max-width: 100%;
  }
  .hero-title-line-inner {
    gap: 35.349px;
    max-width: 100%;
    min-width: 0;
  }
  /* Horizontal overflow is already clipped by .hero-title-line (overflow:hidden
     + max-width:100%). Don't clip here — that would also chop descenders ("g"
     in Designer/Engineer) since vertical overflow can't be excluded. */
  .hero-line-2-text {
    min-width: 0;
  }
  .line-3 span {
    min-width: 0;
    display: inline-block;
    max-width: 100%;
  }
  .hero-title-line + .hero-title-line {
    margin-top: 8.837px;
  }
  /* Reveal the 3rd line ("& Engineer"), hide engineer span on line-2.   */
  .hero-title-line--mobile-only {
    display: flex;
  }
  .hero-word-engineer {
    display: none;
  }
  /* Toggle gif slot homes — JS moves the <video> into the leading slot. */
  .hero-gif-slot--inline {
    display: none;
  }
  .hero-gif-slot--leading {
    display: inline-flex;
  }
  .hero-gif-slot {
    width: 160.837px;
    padding-top: 15.023px;
    padding-bottom: 9.721px;
  }
  .hero-gif {
    width: 160.837px;
    height: 98.977px;
    border-radius: 88.372px;
    top: 0;
  }
  .hero-gif img,
  .hero-gif-video {
    border-radius: 88.372px;
  }

  /* —— Section 2: Video ——————————————————— */
  .section-video {
    height: 576px;
    max-height: 576px;
  }

  /* —— Section 3: About (Figma 201:483) ——— */
  .section-about {
    padding: 120px var(--page-gutter-fluid);
  }
  .section-about-inner {
    max-width: none;
    margin-left: 0;
    padding: 0;
  }
  .section-about-text {
    font-size: 36px;
    line-height: 43.2px;
    letter-spacing: 0.36px;
    margin-bottom: 40px;
  }

  /* —— Buttons —————————————————————————————
     About Me (default .btn-large) — padding 28.8/36, Body 2 25.2/34.2.
     Specific overrides below for View All Works and footer btns.    */
  .btn,
  .btn-large {
    min-height: 92.6px;
    padding: 28.8px 36px;
    font-size: 25.2px;
    line-height: 34.2px;
    letter-spacing: 0.2px;
    border-width: 1px;
  }

  /* —— Section 4: Featured (Figma 201:487) — */
  .section-featured {
    padding: 0 var(--page-gutter-fluid) 80px;
  }
  .section-label {
    font-size: 81px;
    line-height: 81px;
    letter-spacing: -0.72px;
    margin-bottom: 40px;
  }
  .featured-grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 24px;
    height: 440px;
    align-items: stretch;
  }
  .card-big {
    height: 440px;
  }
  .card-special {
    width: auto;
    height: 440px;
  }
  .card-info {
    padding: 28.8px 36px;
  }
  .card-info-top {
    font-size: 36px;
    line-height: 43.2px;
    letter-spacing: 0;
  }
  .card-info-bottom {
    font-size: 64.8px;
    line-height: 77.4px;
    letter-spacing: -0.8px;
  }

  /* —— Section 5: Works (Figma 201:492) ——— */
  .section-works {
    padding: 0 0 100px;
  }
  .section-works-header {
    padding: 0 var(--page-gutter-fluid);
    margin-bottom: 40px;
  }
  .works-drag-pill {
    --works-drag-pill-expanded-width: 174.6px;
    --works-drag-pill-expanded-height: 64.8px;
    --works-drag-pill-collapsed-width: 87px;
    --works-drag-ball-travel: 30px;
    width: var(--works-drag-pill-expanded-width);
    height: var(--works-drag-pill-expanded-height);
  }
  .works-drag-pill::before {
    top: calc(50% - 3px);
    left: calc(50% - 3px);
    width: 6px;
    height: 6px;
  }
  .works-drag-pill-text {
    font-size: 18px;
    line-height: 21.6px;
    letter-spacing: 0.4px;
    width: var(--works-drag-pill-expanded-width);
    height: var(--works-drag-pill-expanded-height);
    padding: 0 28.8px;
    /* Match the View All Works button stroke (1px on tablet — see
       .works-btn-wrap .btn-large override below). */
    border-width: 1px;
  }
  .works-label {
    font-size: 36px;
    line-height: 43.2px;
    letter-spacing: 0.36px;
  }
  .works-scroll-container {
    padding: 0 var(--page-gutter-fluid);
  }
  .works-track {
    gap: 24px;
  }
  .card-work {
    /* Figma 592:19538 — квадратные карточки 440×440. */
    width: 440px;
  }
  .card-work-image {
    height: 440px;
    margin-bottom: 36px;
  }
  .card-work-title {
    font-size: 36px;
    line-height: 43.2px;
    letter-spacing: 0;
    margin-bottom: 10.8px;
  }
  .card-work-type {
    font-size: 25.2px;
    line-height: 34.2px;
    letter-spacing: 0.2px;
  }
  .works-btn-wrap {
    margin-top: 80px;
    padding: 0 var(--page-gutter-fluid);
    display: flex;
    justify-content: center;
  }
  .works-btn-wrap .btn-large {
    width: 312px;
    min-height: 102px;
    padding: 32px 40px;
    font-size: 28px;
    line-height: 38px;
    letter-spacing: 0.2px;
    border-width: 1px;
  }

  /* —— Footer (Figma 345:1587) ——————————— */
  .footer {
    padding: 160px 0 48px;
  }
  .footer-inner {
    padding: 0 var(--page-gutter-fluid);
  }
  .footer-top {
    gap: 160px;
    margin-bottom: 160px;
  }
  .footer-heading {
    gap: 10px;
  }
  .footer-heading-line {
    gap: 40px;
    font-size: 162px;
    line-height: 140px;
    letter-spacing: -8px;
  }
  .footer-gif {
    width: 182px;
    height: 112px;
    border-radius: 100px;
  }
  /* Per Figma node 345:1513 (tablet) — Follow Me and Get In Touch stack
     vertically in a single left-aligned column, NOT side by side. The
     desktop two-column grid would push the email pill off the right edge
     at this width. */
  .footer-contacts {
    grid-template-columns: 1fr;
    gap: 40px;
    justify-content: start;
  }
  .footer-contacts-group {
    display: flex;
    flex-direction: column;
    gap: 40px;
  }
  .footer-contacts-group--email {
    justify-self: start;
  }
  .footer-contacts-label {
    font-size: 28px;
    line-height: 38px;
    letter-spacing: 0.2px;
    margin-bottom: 0;
  }
  .footer .btn {
    min-height: 112px;
    padding: 32px 48px;
    font-size: 40px;
    line-height: 48px;
    letter-spacing: 0;
    border-width: 1px;
  }
  .footer-contacts-btns {
    gap: 24px;
  }
  .running-line {
    margin-bottom: 0;
    height: 319px;
  }
  .running-line-sequence {
    gap: 24px;
    padding-right: 24px;
  }
  .running-line-text {
    font-size: 354px;
    line-height: 319px;
    letter-spacing: -14.64px;
  }
  .running-line-card {
    width: 248px;
    height: 248px;
  }
  .footer-bottom-inner {
    padding: 0 var(--page-gutter-fluid);
  }
  .footer-bottom-left {
    gap: 24px;
  }
  .footer-bottom,
  .footer-bottom a,
  .footer-bottom span {
    font-size: 15px;
    line-height: 20px;
    letter-spacing: 0.4px;
  }

  .page-hero {
    /* Figma 343:760 (Work) / 355:1808 (About) — tablet hero h720, bottom 60. */
    min-height: 720px;
    padding: 140px var(--page-gutter-fluid) 60px;
  }

  /* Display 1 × 0.9 — token scale used by Work / Tablet (Figma 343:769). */
  .page-hero-title {
    font-size: 318.6px;
    line-height: 287.1px;
    letter-spacing: -13.176px;
  }

  .work-grid {
    padding: 0 var(--page-gutter-fluid) 100px;
    gap: 60px;
  }

  .work-card {
    gap: 36px;
  }

  /* On tablet all pair sections collapse to a 50/50 split per Figma 343:772 /
     343:907 / 343:930. The desktop wide+narrow asymmetry is dropped. */
  .work-card--wide,
  .work-card--narrow {
    width: auto;
    flex: 1 0 0;
  }

  .work-card-image {
    /* Figma 343:774 — квадрат 440×440 (full-карточка 904×440). */
    height: 440px;
  }

  .work-card-info {
    gap: 10.8px;
  }

  /* Body 1 × 0.9 (Figma 343:776) */
  .work-card-title {
    font-size: 36px;
    line-height: 43.2px;
  }

  /* Body 2 × 0.9 (Figma 343:777) */
  .work-card-meta {
    font-size: 25.2px;
    line-height: 34.2px;
    letter-spacing: 0.18px;
  }

  /* —— About / Tablet (Figma 355:1808) ———————————————————————————————
     Hero 720; portrait band full-bleed 1024×576; group band в гаттере
     904×450; intro/experience — одна центрированная колонка. */
  .page-hero--about {
    min-height: 720px;
  }

  .about-photo-band--portrait {
    padding: 0;
  }
  .about-photo-band--portrait .about-photo-band-inner {
    aspect-ratio: 1024 / 576;
    border-radius: 0;
  }
  .about-photo-band--group .about-photo-band-inner {
    aspect-ratio: 904 / 450;
  }

  .about-content {
    padding: 100px var(--page-gutter-fluid);
  }

  .about-intro {
    gap: 40px;
  }

  .about-intro-text {
    gap: 40px;
  }

  /* Tablet body para — 36 / 43.2 / 0 (Body 1 × 0.9) */
  .about-intro-text p {
    font-size: 36px;
    line-height: 43.2px;
  }

  /* Experience rows on tablet — Body 1 × 0.9 / Body 2 × 0.9 */
  .about-experience-row {
    padding: 36px 0;
  }

  .about-experience-left {
    gap: 10.8px;
  }

  .about-experience-title {
    font-size: 36px;
    line-height: 43.2px;
  }

  .about-experience-role,
  .about-experience-date {
    font-size: 25.2px;
    line-height: 34.2px;
    letter-spacing: 0.18px;
  }

  /* —— Contact / Tablet (Figma 355:3105) ——————————————————————————————
     Outer pad-top 43.2 + header 32.4 + gap-200 ≈ 276; video radius 36
     matches Card Radius token at this breakpoint. */
  .contact-main {
    padding-top: 276px;
  }

  /* —— VKUI / Tablet (Figma 592:26959) ———————————————————————————————— */
  .vkui-hero {
    min-height: 720px;
    padding: 0 var(--page-gutter-fluid) 60px;
  }
  .vkui-hero-title {
    font-size: 143.163px;
    line-height: 123.721px;
    letter-spacing: -7.0698px;
  }

  /* Hero band 904×450 (2:1) on tablet. */
  .vkui-band--hero .vkui-band-inner {
    aspect-ratio: 904 / 450;
  }

  .vkui-info,
  .vkui-section {
    padding: 100px var(--page-gutter-fluid);
  }
  .vkui-section {
    gap: 36px;
  }
  .vkui-section-title {
    font-size: 81px;
    line-height: 81px;
    letter-spacing: -0.72px;
  }

  /* Stack label above content on tablet. */
  .vkui-cols {
    flex-direction: column;
    gap: 24px;
  }
  .vkui-col-label {
    width: auto;
    font-size: 25.2px;
    line-height: 34.2px;
    letter-spacing: 0.18px;
  }
  .vkui-col-body {
    gap: 36px;
  }
  .vkui-col-body--result {
    gap: 48px;
  }
  .vkui-body-text {
    font-size: 36px;
    line-height: 43.2px;
  }
  .vkui-meta {
    gap: 24px;
  }
  .vkui-meta-row {
    gap: 4px;
  }
  .vkui-meta-row dt,
  .vkui-meta-row dd {
    font-size: 25.2px;
    line-height: 34.2px;
    letter-spacing: 0.18px;
  }
  .vkui-stats {
    gap: 28px;
  }
  .vkui-stat {
    gap: 20px;
  }
  .vkui-stat-num {
    font-size: 81px;
    line-height: 81px;
    letter-spacing: -0.72px;
  }
  .vkui-stat-label {
    font-size: 25.2px;
    line-height: 34.2px;
    letter-spacing: 0.18px;
  }
  .section-works--vkui {
    padding-top: 100px;
  }
  /* Carousel cards 440 on tablet (override desktop 744). */
  .section-works--vkui .card-work {
    width: 440px;
  }

}

/* Phone: 320px - 767px */
@media (max-width: 767px) {
  :root {
    --page-gutter-fluid: 20px;
    --radius-card: 20px;
  }

  .nav-panel,
  .nav-panel-fill {
    width: 100%;
  }

  .nav-panel-inner {
    padding: 88px 20px 32px;
    gap: 48px;
    /* Override default justify-content: space-between. Header lives outside
       the overlay (it's a global fixed component), so a 2-child layout with
       space-between would just pin Menu to top + Socials to bottom. Figma's
       phone layout (node 408:1761) wants Menu in the upper-middle third, as
       if there were a virtual header slot above. Both children get
       margin-top: auto so the remaining vertical space splits evenly into
       a top-spacer and a mid-spacer — same visual rhythm as Figma's
       3-slot justify-between. */
    justify-content: flex-start;
  }

  .nav-panel-body {
    gap: 32px;
    margin-top: auto;
  }

  .nav-panel-title {
    font-size: 14px;
    line-height: 19px;
    letter-spacing: 0.2px;
  }

  .nav-list {
    gap: 24px;
  }

  .nav-list a {
    font-size: 64px;
    line-height: 56px;
    letter-spacing: -3.24px;
  }

  /* Точка текущей страницы: слева она вылезала бы за full-width панель
     (padding-inner всего 20px) и клипалась. На мобиле — справа, центр
     на вертикали крестика: центр кнопки 24px от правого края viewport =
     var(--page-gutter-visible) + 12px; правый паддинг panel-inner = 20px,
     точка 10px → right = pgv + 12 − 20 − 5 = pgv − 13px. */
  .nav-list a.is-current::before {
    display: none;
  }

  .nav-list li:has(.is-current) {
    width: 100%;
    position: relative;
  }

  .nav-list li:has(.is-current)::after {
    content: '';
    position: absolute;
    right: calc(var(--page-gutter-visible) - 13px);
    top: 50%;
    transform: translateY(-50%);
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: currentColor;
  }

  .nav-socials {
    gap: 24px;
    margin-top: auto;
  }

  .nav-social-list {
    flex-direction: row;
    flex-wrap: wrap;
    gap: 16px;
  }

  .nav-social-list a {
    font-size: 15px;
    line-height: 20px;
    letter-spacing: 0.4px;
  }

  .header {
    padding: 20px var(--page-gutter-visible);
  }

  /* Logo shrinks to 28×28 on mobile per Figma frame 345:1891 */
  .header-logo {
    width: 28px;
    height: 28px;
  }

  .header-menu-text {
    display: none;
  }

  .section-hero {
    /* Исключение из дефолтных 400px: главной нужно больше воздуха (510). */
    min-height: calc(510px / var(--composition-scale));
    height: calc(510px / var(--composition-scale));
    padding:
      var(--page-gutter-fluid)
      var(--page-gutter-fluid)
      32px;
    align-items: flex-end;
    /* Same safety clip as tablet — see comment above. */
    overflow-x: clip;
  }

  /* 3 visual lines per Figma 201:528:
       line-1: "Product"
       line-2: [gif] "Designer"
       line-3: "& Engineer"
     Inline gif slot (line-1) hidden; leading slot (line-2) shown.   */
  .hero-title-line {
    gap: 0;
    /* Keep descender clearance so "g" in Designer/Engineer isn't clipped by
       overflow:hidden (line-height < font-size). Mirrors the desktop rule. */
    padding-bottom: 0.16em;
    margin-bottom: -0.16em;
    /* Hard cap line container to viewport width — prevents wrapper text
       (with fallback fonts wider than Uncut Sans) from pushing past padding. */
    max-width: 100%;
  }
  .hero-title-line-inner {
    gap: 16px;
    max-width: 100%;
    min-width: 0;
  }
  /* Allow flex children to shrink when fallback fonts render text wider
     than the design (Uncut Sans Variable not yet loaded, e.g. on iOS Safari
     during the FOIT window). Horizontal overflow is clipped by the parent
     .hero-title-line (overflow:hidden + max-width:100%) — clipping here too
     would also chop descenders ("g" in Designer/Engineer). */
  .hero-line-2-text {
    min-width: 0;
  }
  .line-3 span {
    min-width: 0;
    display: inline-block;
    max-width: 100%;
  }
  .hero-title-line + .hero-title-line {
    margin-top: 4px;
  }
  .hero-title-line--mobile-only {
    display: flex;
  }
  .hero-word-engineer {
    display: none;
  }
  .hero-gif-slot--inline {
    display: none;
  }
  .hero-gif-slot--leading {
    display: inline-flex;
  }
  .hero-gif-slot {
    width: 75px;
    padding-top: 0;
    padding-bottom: 0;
  }
  .hero-gif {
    width: 75px;
    height: 46px;
    border-radius: 40.5px;
    top: 0;
  }
  .hero-gif img,
  .hero-gif-video {
    border-radius: 40.5px;
  }

  .hero-title {
    font-size: 64px;
    line-height: 56px;
    letter-spacing: -3.24px;
  }

  .section-video {
    height: 375px;
    max-height: none;
  }

  .section-about {
    padding:
      64px
      var(--page-gutter-fluid);
  }

  .section-about-inner {
    max-width: none;
    margin-left: 0;
    padding: 0;
  }

  /* Section-about text: Body 1 (phone tokens) = 20/24/0.2, gap 20 to btn */
  .section-about-text {
    font-size: 20px;
    line-height: 24px;
    letter-spacing: 0.2px;
    margin-bottom: 20px;
  }

  .btn,
  .btn-large,
  .footer .btn {
    min-height: 56px;
    padding-left: 24px;
    padding-right: 24px;
    font-size: 20px;
    line-height: 24px;
    border-width: 1px;
  }

  .section-featured {
    padding:
      0
      var(--page-gutter-fluid)
      64px;
  }

  .section-label {
    font-size: 45px;
    line-height: 45px;
    margin-bottom: 32px;
  }

  .featured-grid {
    grid-template-columns: 1fr;
    gap: 20px;
  }

  .card-big {
    height: 350px;
    aspect-ratio: auto;
  }

  .card-special {
    width: 100%;
    height: 175px;
    aspect-ratio: auto;
  }

  .card-info {
    padding:
      16px
      20px;
  }

  .card-info-top {
    font-size: 20px;
    line-height: 24px;
  }

  .card-info-bottom {
    font-size: 36px;
    line-height: 43px;
    letter-spacing: -0.8px;
  }

  /* Section spans full viewport width — gutter lives inside the carousel
     container instead of on the section. This way the carousel's
     overflow:hidden clips at the viewport edges, not the gutter, so cards
     remain visible all the way to the screen edge during drag (matches the
     tablet behaviour). */
  .section-works {
    padding: 0 0 64px;
  }

  /* Per Figma 201:552 — there is no Drag pill / Works label on phone.
     Only cards + View All Works button. */
  .section-works-header {
    display: none;
  }

  .works-scroll-container {
    padding: 0 var(--page-gutter-fluid);
  }

  .works-track {
    gap: 20px;
  }

  .card-work {
    width: 276px;
  }

  .card-work-image {
    /* Square image 276×276 per Figma 201:556 */
    height: 276px;
    margin-bottom: 20px;
  }

  .card-work-title {
    font-size: 20px;
    line-height: 24px;
    margin-bottom: 6px;
  }

  .card-work-type {
    font-size: 14px;
    line-height: 19px;
  }

  .works-btn-wrap {
    width: 100%;
    margin-top: 32px;
    /* Section padding moved off — restore gutter so the button doesn't
       run edge-to-edge. */
    padding: 0 var(--page-gutter-fluid);
  }

  /* Override desktop `.works-btn-wrap .btn-large` (specificity 2) which would
     otherwise force 312px / 102h / 28px font on phone. Phone btn = 56h, 20px,
     full width — same shape as the rest of the buttons on phone. */
  .works-btn-wrap .btn-large {
    width: 100%;
    min-height: 56px;
    padding: 16px 24px;
    font-size: 20px;
    line-height: 24px;
    letter-spacing: 0.2px;
    border-width: 1px;
  }

  /* JS-driven drag-loop is used on phone (per Figma 201:552 — no visible
     start/end edges). Base `touch-action: pan-y` applies and lets vertical
     page scroll pass through while horizontal gestures are captured by the
     `pointerdown`/`pointermove` handlers in initDragScroll. */

  .works-drag-pill {
    --works-drag-pill-expanded-width: 118px;
    --works-drag-pill-expanded-height: 48px;
    --works-drag-pill-collapsed-width: 59px;
    --works-drag-ball-travel: 22px;
    width: var(--works-drag-pill-expanded-width);
    height: var(--works-drag-pill-expanded-height);
  }

  .works-drag-pill::before {
    top: calc(50% - 3px);
    left: calc(50% - 3px);
    width: 6px;
    height: 6px;
  }

  .works-drag-pill-text {
    font-size: 14px;
    line-height: 19px;
    letter-spacing: 0.2px;
    width: var(--works-drag-pill-expanded-width);
    height: var(--works-drag-pill-expanded-height);
    padding: 0 18px;
  }

  .works-label {
    font-size: 20px;
    line-height: 24px;
  }

  .works-btn-wrap .btn-large {
    width: 100%;
  }

  /* Explore cursor pill must not be taller than the View All Works button
     (mobile btn-large = 56px). Mirror the button's font/padding so the
     pill never visually overpowers the button it's emulating. */
  .cb-cursor.-explore .cb-cursor-text {
    font-size: 20px;
    line-height: 24px;
    padding: 16px 24px;
  }

  /* Badge на мобилке: виден ПОСТОЯННО (ховера нет — пользователь должен
     сразу понимать, что в карточку нельзя провалиться) + компактные
     размеры под 335px-карточку. */
  .card-badge {
    left: 16px;
    bottom: 16px;
    padding: 12px 20px;
    border-radius: 14px;
    font-size: 16px;
    line-height: 22px;
    letter-spacing: 0.3px;
    opacity: 1;
    transform: none;
  }

  /* Mobile footer — matches Figma node 345:1514 (mobile column).
     Tokens taken directly from get_design_context:
       • container px-20px, pt-64px, pb-24px, gap-64px
       • heading: gif 75×46 ABOVE the text (column), then 64/56 -3.24px lines
       • contacts stack vertically: Follow Me (label 14/19) + 3 round social
         buttons 56×56, then Get In Touch + email pill (width by content)
       • bottom: Moscow / © / Back To Top stacked, 15/20 body-5 */
  .footer {
    padding: 64px 0 24px;
  }

  .footer-inner {
    padding: 0 var(--page-gutter-fluid);
  }

  .footer-top {
    gap: 64px;
    margin-bottom: 64px;
  }

  .footer-heading {
    gap: 4px;
  }

  /* GIF lives above the heading text on mobile, not beside it */
  .footer-heading-line--top {
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
  }

  .footer-heading-line {
    font-size: 64px;
    line-height: 56px;
    letter-spacing: -3.24px;
    white-space: nowrap;
  }

  .footer-gif {
    width: 75px;
    height: 46px;
    border-radius: 40.5px;
  }

  .footer-contacts {
    gap: 32px;
    flex-direction: column;
    display: flex;
  }

  .footer-contacts-group {
    display: block;
    width: 100%;
  }

  .footer-contacts-group--email {
    justify-self: auto;
  }

  .footer-contacts-label {
    font-size: 14px;
    line-height: 19px;
    letter-spacing: 0.2px;
    margin-bottom: 12px;
  }

  /* Base footer btn — body-1 sized, slim 0.5px border, square padding */
  .footer .btn {
    min-height: 56px;
    padding: 16px 24px;
    font-size: 20px;
    line-height: 24px;
    letter-spacing: 0;
    border-width: 1px;
  }

  /* Social row — three 56×56 round-pill icons with short labels */
  .footer-contacts-group--social .footer-contacts-btns {
    gap: 12px;
    flex-wrap: nowrap;
  }
  .footer-contacts-group--social .btn {
    width: 56px;
    height: 56px;
    min-height: 56px;
    padding: 0;
    flex-shrink: 0;
  }
  .footer-contacts-group--social .btn-text-full {
    display: none;
  }
  .footer-contacts-group--social .btn-text-short {
    display: inline;
  }

  /* Email pill — width hugs the address (NOT full width per the Figma frame) */
  .footer-contacts-group--email .footer-contacts-btns {
    width: auto;
  }
  .footer-contacts-group--email .btn {
    width: auto;
  }

  /* Running line is hidden on mobile per Figma frame 345:1514 */
  .running-line {
    display: none;
  }

  .footer-bottom {
    border-top: 0;
  }

  /* footer-bottom lives OUTSIDE .footer-inner, so we apply the gutter here
     directly — otherwise Moscow / © / Back To Top stick to the viewport edge */
  .footer-bottom-inner {
    padding: 0 var(--page-gutter-fluid);
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
  }

  .footer-bottom-left {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
  }

  .footer-bottom,
  .footer-bottom a,
  .footer-bottom span {
    font-size: 15px;
    line-height: 20px;
  }

  .footer-bottom a,
  .footer-bottom-left span {
    width: auto;
    text-align: left;
  }

  /* Cap hero height to one viewport (after composition-scale) so на широком
     "phablet" viewport (например 767×812, scale ≈2.04) hero не растягивается
     и не уводит заголовок «Work» / «About» / «Get In Touch» под фолд.
     На реальном телефоне 375×812 (scale ≈1) min() выбирает 400px. */
  .page-hero {
    min-height: min(
      400px,
      calc(100svh / var(--composition-scale))
    );
    padding:
      120px
      var(--page-gutter-fluid)
      40px;
    align-items: flex-end;
  }

  /* Display 1 × 0.25 — token scale used by Work / Phone (Figma 344:1041). */
  .page-hero-title {
    font-size: 88.5px;
    line-height: 79.75px;
    letter-spacing: -3.66px;
  }

  .work-grid {
    padding:
      0
      var(--page-gutter-fluid)
      64px;
    gap: 40px;
  }

  .work-section {
    flex-direction: column;
    gap: 40px;
  }

  .work-card {
    gap: 20px;
  }

  .work-card--wide,
  .work-card--narrow,
  .work-card--full {
    width: 100%;
    flex: none;
  }

  .work-card-image {
    /* Figma 344:1046 — квадрат 335×335 (карточка на всю ширину). */
    aspect-ratio: 1 / 1;
    height: auto;
  }

  .work-card-info {
    gap: 6px;
  }

  .work-card-title {
    font-size: 20px;
    line-height: 24px;
  }

  /* Phone meta — Figma 344:1049: 14 / 19 / 0.1 (NOT base Body 5 15/20/0.4). */
  .work-card-meta {
    font-size: 14px;
    line-height: 19px;
    letter-spacing: 0.1px;
  }

  /* —— About / Phone (Figma 355:2064) ————————————————————————————————
     Portrait band full-bleed square (375×375); group band в гаттере
     square (335×335); intro/experience — одна колонка. */
  .about-photo-band--portrait {
    padding: 0;
  }
  .about-photo-band--portrait .about-photo-band-inner {
    aspect-ratio: 1 / 1;
    border-radius: 0;
  }
  .about-photo-band--group .about-photo-band-inner {
    aspect-ratio: 1 / 1;
  }

  .about-content {
    padding: 64px var(--page-gutter-fluid) 64px;
  }

  .about-intro {
    gap: 20px;
  }

  .about-intro-text {
    gap: 20px;
  }

  /* Phone body para — Body 4: 20 / 24 / 0 */
  .about-intro-text p {
    font-size: 20px;
    line-height: 24px;
    letter-spacing: 0;
  }

  /* Experience rows on phone — Body 4 / Body 5 */
  .about-experience-row {
    padding: 20px 0;
    gap: 12px;
  }

  .about-experience-left {
    gap: 6px;
  }

  .about-experience-title {
    font-size: 20px;
    line-height: 24px;
  }

  .about-experience-role,
  .about-experience-date {
    font-size: 14px;
    line-height: 19px;
    letter-spacing: 0.1px;
  }

  /* —— Contact / Phone (Figma 355:3130) ———————————————————————————————
     Outer pad-top 20 + header 28 + gap-200 = 248; video radius 20
     matches Card Radius token. */
  .contact-main {
    padding-top: 248px;
  }

  /* —— VKUI / Phone (Figma 592:39111) ———————————————————————————————— */
  .vkui-hero {
    min-height: min(400px, calc(100svh / var(--composition-scale)));
    padding: 0 var(--page-gutter-fluid) 40px;
  }
  /* Исключение из дефолтных 400px: hero страницы VKUI выше (560) —
     модификатор стоит в разметке vkui.html (vkid остаётся на 400). */
  .vkui-hero--tall {
    min-height: min(560px, calc(100svh / var(--composition-scale)));
  }
  .vkui-hero-title {
    font-size: 88.5px;
    line-height: 79.75px;
    letter-spacing: -3.66px;
  }
  /* Phone shows "VK", hides "VKontakte". */
  .vkui-hero-full {
    display: none;
  }
  .vkui-hero-short {
    display: inline;
  }

  /* Hero band square on phone. */
  .vkui-band--hero .vkui-band-inner {
    aspect-ratio: 1 / 1;
  }

  /* Galleries: stack everything, square bands, gap 12. */
  .vkui-gallery {
    gap: 12px;
  }
  .vkui-band-row {
    flex-direction: column;
    gap: 12px;
  }
  .vkui-band-inner,
  .vkui-band-row .vkui-band-inner {
    aspect-ratio: 1 / 1;
  }
  /* Reset the desktop 2-up flex grow — in a column it would collapse height. */
  .vkui-band-row .vkui-band-inner {
    flex: none;
    width: 100%;
  }

  .vkui-info,
  .vkui-section {
    padding: 64px var(--page-gutter-fluid) 40px;
  }
  .vkui-section {
    gap: 20px;
  }
  .vkui-section-title {
    font-size: 45px;
    line-height: 45px;
    letter-spacing: -0.4px;
  }
  .vkui-cols {
    flex-direction: column;
    gap: 20px;
  }
  .vkui-col-label {
    width: auto;
    font-size: 14px;
    line-height: 19px;
    letter-spacing: 0.1px;
  }
  .vkui-col-body {
    gap: 20px;
  }
  .vkui-col-body--result {
    gap: 36px;
  }
  .vkui-body-text {
    font-size: 20px;
    line-height: 24px;
  }
  .vkui-meta {
    gap: 16px;
  }
  .vkui-meta-row {
    gap: 2px;
  }
  .vkui-meta-row dt,
  .vkui-meta-row dd {
    font-size: 14px;
    line-height: 19px;
    letter-spacing: 0.1px;
  }
  /* Stats stack on phone. */
  .vkui-stats {
    flex-direction: column;
    gap: 20px;
  }
  .vkui-stat {
    gap: 8px;
  }
  .vkui-stat-num {
    font-size: 45px;
    line-height: 45px;
    letter-spacing: -0.4px;
  }
  .vkui-stat-label {
    font-size: 14px;
    line-height: 19px;
    letter-spacing: 0.1px;
  }

  /* Gallery 3: показываем mobile-вариант (особый порядок), прячем wide. */
  .vkui-gallery--wide {
    display: none;
  }
  .vkui-gallery--narrow {
    display: flex;
  }

  /* Отдельные картинки, которых нет в мобильной версии (например IMG_13). */
  .vkui-band--hide-mobile {
    display: none;
  }

  /* Мобильные сплиты широких картинок (VK ID: IMG_1_x / IMG_8_x). */
  .vkui-band--mobile-only {
    display: block;
  }

  /* VK ID hero: на phone строка «VKontakte» скрывается целиком —
     остаётся одна строка «Auth VK» (short-вариант line-1). */
  .vkui-hero-line--hide-mobile {
    display: none;
  }

  /* Carousel = как на home (276-карточки, drag) + заголовок «More projects»
     сверху, без кнопки View All. */
  .section-works--vkui {
    padding-top: 64px;
  }
  .section-works--vkui .section-works-header {
    display: flex;
    justify-content: flex-start;
    margin-bottom: 32px;
  }
  .section-works--vkui .works-drag-pill {
    display: none;
  }
  .section-works--vkui .works-label {
    font-size: 45px;
    line-height: 45px;
    letter-spacing: -0.4px;
  }
  /* Override desktop `.section-works--vkui .card-work { width: 744px }` —
     на мобилке карточки 276 (как на home). */
  .section-works--vkui .card-work {
    width: 276px;
  }

}

/* =============================================
   LOADER
   ============================================= */
.loader {
  position: fixed;
  inset: 0;
  background: var(--black);
  z-index: 10000;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

.loader-logo {
  width: 48px;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  animation: loaderSpin 1s linear infinite;
  will-change: transform;
  /* Вращение обязано жить целиком на компоузере: без drop-shadow на
     дочернем лого (заставлял пере-растеризовывать слой каждый кадр — во
     время загрузки, когда поток занят декодом медиа, лого «дёргалось»)
     и с явным translateZ в кейфреймах (стабильный GPU-слой). */
}

.loader-logo .site-logo {
  backface-visibility: hidden;
}

@keyframes loaderSpin {
  from { transform: rotate(0deg) translateZ(0); }
  to { transform: rotate(360deg) translateZ(0); }
}

.loader.hidden {
  display: none;
}

/* =============================================
   SELECTION & SCROLLBAR
   ============================================= */
::selection {
  background: var(--black);
  color: var(--white);
}

/* =============================================
   A11Y & PRESS FEEDBACK
   ============================================= */
/* Видимый фокус ТОЛЬКО с клавиатуры (Tab) — при кликах мышью не появляется.
   currentColor: на тёмных секциях рамка автоматически белая. */
a:focus-visible,
button:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 4px;
}

/* Press-реакция кнопок на touch. На hover-девайсах transform кнопки
   принадлежит GSAP (jelly squash + press в initCursor), поэтому CSS :active —
   только там, где курсорный трекер выключен (coarse pointer). */
@media (hover: none) {
  .btn {
    transition:
      color 0.4s cubic-bezier(0.16, 1, 0.3, 1),
      transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
  }
  .btn:active {
    transform: scale(0.96);
  }
  .header-menu-btn:active {
    transform: scale(0.88);
    transition: transform 0.2s cubic-bezier(0.22, 1, 0.36, 1);
  }
}

/* Reduced motion: декоративные бесконечные анимации останавливаются.
   JS-часть (Lenis, reveal'ы, флип кадров) гейтится флагом REDUCED_MOTION
   в main.js — здесь только чистый CSS. Спиннер лоадера НЕ трогаем:
   индикаторы прогресса под reduced motion допустимы (Apple HIG). */
@media (prefers-reduced-motion: reduce) {
  .running-line-track {
    animation: none;
  }
  /* Drag-пилла: пролетающий шарик прячем, текст оставляем статичным. */
  .works-drag-pill::before {
    animation: none;
    display: none;
  }
  .works-drag-pill-text {
    animation: none;
  }
}

/* =============================================
   404 PAGE
   ============================================= */
.notfound-body {
  padding: 24px var(--page-gutter-fluid) 200px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 48px;
}

/* Body 2 (28/38/0.2) — design-px, адаптивом занимается composition scale. */
.notfound-text {
  font-size: 28px;
  line-height: 38px;
  letter-spacing: 0.2px;
  max-width: 760px;
}

/* Против двойного шринка базового .btn (clamp с vw — см. ловушку 14.9). */
.notfound-body .btn-large {
  font-size: 28px;
}

/* =============================================
   MOBILE: декоративные видео скрыты (решение Vadim)
   Гиф-плашка в footer-заголовке (все страницы; большое видео Contact
   удалено из проекта совсем). JS дополнительно снимает src
   (initMobileMediaTrim в main.js), чтобы скрытый ролик не качался
   на мобильном трафике.
   ============================================= */
@media (max-width: 767px) {
  .footer-gif {
    display: none;
  }
}
