/* ═══════════════════════════════════════════════════════
   Кейс Газпромбанк — скелет и механика по мотивам
   unseen.co/projects/organimo (без WebGL).
   Токены сняты с оригинала: контейнер 80rem, rem тянется
   за вьюпортом, вертикальный ритм 5/10rem, дисплей 6rem,
   антиква-италик в паре с гротеском.
   ═══════════════════════════════════════════════════════ */

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

:root {
  /* Обе схемы: страница следует системной теме пользователя.
     «light dark» также говорит браузеру не перекрашивать её самому. */
  color-scheme: light dark;

  font-size: clamp(14px, .95vw, 21px);          /* оригинал: clamp(14px,1vw,38px) */

  /* светлая — прохладный, чуть голубоватый нейтральный */
  --bg:      #e9f0fd;                            /* голубоватый — по присланному образцу */
  --ink:     #0f141d;
  --ink-2:   rgba(15, 20, 29, .55);
  --line:    rgba(15, 20, 29, .18);
  --accent:  #3a5bf5;
  --next-bg: #191c23;
  --grain:     .5;                               /* фон: ослаблен в 1.5 раза */
  --grain-top: .2;                               /* плёнка поверх контента */
  --glow:   255, 255, 255;                       /* светлая тема: белое свечение */
  --glow-a: .30;                                 /* пиковая прозрачность */
  --cur:      15, 20, 29;                        /* курсор тёмный на светлой теме */
  --cur-edge: 255, 255, 255;                     /* обводка обратного цвета — чтобы
                                                    курсор читался и поверх тёмных экранов */
  --noise-a: url(img/noise-d.png);               /* на светлом фоне зерно тёмное — */
  --noise-b: url(img/noise-d2.png);              /* белое там физически не видно */
  --vignette: .045;
  --logo-invert: 0;

  --pad: 1rem;
  --gap-s: 5rem;
  --gap-l: 10rem;

  --e-io:  cubic-bezier(.76, 0, .24, 1);   /* ≈ expo.inOut */
  --e-out: cubic-bezier(.16, 1, .3, 1);    /* ≈ expo.out   */
}

/* Тёмная — тот же холодный тон, что и у экранов интерфейса.
   Два одинаковых набора значений: по системной теме (если пользователь
   не выбирал вручную) и по атрибуту data-theme от переключателя. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg:      #191c23;
    --ink:     #e9ecf3;
    --ink-2:   rgba(233, 236, 243, .58);
    --line:    rgba(233, 236, 243, .22);
    --accent:  #7f96ff;
    --next-bg: #0e1015;
    --grain:     .57;                            /* фон: ослаблен в 1.5 раза */
    --grain-top: .2;
    --glow:   150, 172, 255;                     /* холодный голубой — дополнение
                                                    к серо-синему фону #191c23 */
    --glow-a: .20;                               /* в 1.5 раза деликатнее светлой */
    --cur:      255, 255, 255;
    --cur-edge: 12, 14, 22;
    --noise-a: url(img/noise.png);
    --noise-b: url(img/noise2.png);
    --vignette: .10;
    --logo-invert: 1;                            /* запасной плоский логотип чёрный — инвертируем */
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg:      #191c23;
  --ink:     #e9ecf3;
  --ink-2:   rgba(233, 236, 243, .58);
  --line:    rgba(233, 236, 243, .22);
  --accent:  #7f96ff;
  --next-bg: #0e1015;
  --grain:     .57;
  --grain-top: .2;
  --glow:   150, 172, 255;
  --glow-a: .20;
  --cur:      255, 255, 255;
  --cur-edge: 12, 14, 22;
  --noise-a: url(img/noise.png);
  --noise-b: url(img/noise2.png);
  --vignette: .10;
  --logo-invert: 1;
}
:root[data-theme="light"] { color-scheme: only light; }   /* «only» не даёт Chrome снова затемнить страницу */

@media (min-width: 48rem) { :root { --pad: 2rem; } }

html { -webkit-text-size-adjust: 100%; }
html.is-loading, html.is-menu { overflow: hidden; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: "Neue Haas Grotesk Text", Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial,
               "PingFang SC", "Hiragino Sans GB", "Noto Sans SC", "Microsoft YaHei", sans-serif;
  font-size: 1rem;
  line-height: 1.4;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  transition: background-color 1.1s var(--e-out), color 1.1s var(--e-out);
}
body.is-next { background: var(--next-bg); --ink: #fff; --ink-2: rgba(255,255,255,.6); --line: rgba(255,255,255,.25); color: #fff; }

img { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
h1, h2, h3, p, ul, figure, figcaption { margin: 0; }
ul { padding: 0; list-style: none; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }

.serif {
  font-family: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, "Times New Roman", serif;
  font-style: italic; font-weight: 400; letter-spacing: -.02em;
}
/* у иероглифов нет курсива — браузер наклонил бы их искусственно, поэтому
   в китайском акцент даёт не наклон, а шрифт с засечками */
html[lang^="zh"] .serif {
  font-family: "Songti SC", "Noto Serif SC", "Source Han Serif SC", STSong, serif;
  font-style: normal; letter-spacing: 0;
}

.wrap { width: 100%; max-width: 80rem; margin: 0 auto; padding: 0 var(--pad); }
.block { margin-bottom: var(--gap-s); }
@media (min-width: 48rem) { .block { margin-bottom: var(--gap-l); } }

/* ─── Типографика ─────────────────────────────────── */

.dspl {
  font-size: 3rem; line-height: 1; letter-spacing: -.05rem;
  font-weight: 400; text-transform: uppercase;
}
@media (min-width: 64rem) { .dspl { font-size: 6rem; letter-spacing: -.1rem; } }

/* четвёртая строка героя — длинная, поэтому идёт подзаголовком */
.dspl--sub { font-size: 1.5rem; letter-spacing: -.02rem; }
@media (min-width: 64rem) { .dspl--sub { font-size: 2.4rem; letter-spacing: -.03rem; } }

.dspl-sm { font-size: 1.6rem; line-height: 1.15; letter-spacing: -.02em; font-weight: 400; }
@media (min-width: 48rem) { .dspl-sm { font-size: 2.25rem; } }

.lbl { font-size: .8rem; text-transform: uppercase; font-weight: 500; letter-spacing: .02em; }
.lbl--lg { font-size: 1.3rem; }
@media (min-width: 48rem) { .lbl--lg { font-size: 2rem; } }

.cap { margin-top: 1.2rem; font-size: .8rem; text-transform: uppercase; color: var(--ink-2); }

/* ─── Прелоадер ───────────────────────────────────── */

.loader {
  position: fixed; inset: 0; z-index: 90;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2rem; background: var(--bg);
  transition: opacity .8s var(--e-out), visibility .8s;
}
.loader.is-done { opacity: 0; visibility: hidden; }
.loader__word { display: flex; gap: .1em; font-size: 1.1rem; text-transform: uppercase; letter-spacing: .3em; }
.loader__word span {
  opacity: .12; animation: blink 1.6s var(--e-io) infinite;
  animation-delay: calc(var(--i, 0) * .07s);
}
@keyframes blink { 0%, 100% { opacity: .12; } 45% { opacity: 1; } }
.loader__bar { width: 8rem; height: 1px; background: var(--line); overflow: hidden; }
.loader__bar i { display: block; height: 100%; background: var(--ink); transform: scaleX(0); transform-origin: 0 50%; transition: transform .4s linear; }
.loader__enter {
  display: inline-flex; align-items: center; gap: .5rem;
  padding: .7rem 1.6rem; border: 1px solid var(--line); border-radius: 3rem;
  opacity: 0; transform: translateY(.6rem); pointer-events: none;
  transition: opacity .6s var(--e-out), transform .6s var(--e-out), background-color .4s, color .4s;
}
.loader__enter.is-on { opacity: 1; transform: none; pointer-events: auto; }
.loader__enter:hover { background: var(--ink); color: var(--bg); }

/* ─── Курсор ──────────────────────────────────────── */
/* Один в один со структурой оригинала: внешний узел получает только
   translate3d, вложенный круг — rotate + scale («сквиш»). Никаких
   дополнительных слоёв и режимов наложения. */

html.has-cursor, html.has-cursor a, html.has-cursor button, html.has-cursor .btn { cursor: none; }

/* Свечение по следу движения — отдельный слой, как fluidPass в оригинале.
   Масштаб только равномерный: неравномерный сплющивал градиент в пилюлю
   с жёсткой кромкой — это и был артефакт. Наложения нет: цвет берётся
   по теме, поэтому обычной отрисовки достаточно и ничего не выжигается. */
.glow { position: fixed; inset: 0; z-index: 68; pointer-events: none; }
.glow__b {
  position: absolute; top: 0; left: 0;
  width: 15rem; height: 15rem; margin: -7.5rem 0 0 -7.5rem;
  border-radius: 50%; opacity: 0;
  background: radial-gradient(closest-side,
              rgba(var(--glow), var(--glow-a)) 0%,
              rgba(var(--glow), calc(var(--glow-a) * .5)) 38%,
              rgba(var(--glow), calc(var(--glow-a) * .17)) 66%,
              rgba(var(--glow), 0) 100%);
  will-change: transform, opacity;
}
@media (hover: none) { .glow { display: none; } }

.cursor {
  /* ⚠️ Курсор обязан лежать выше всего. На 81 он уходил под прелоадер и под
     модалку с QR (обе на 90) — указатель просто пропадал, хотя мышь работала.
     Слой декоративный и с pointer-events: none, перекрывать им нечего. */
  position: fixed; top: 0; left: 0; z-index: 200; pointer-events: none;
  opacity: 0; transition: opacity .45s var(--e-out);
  will-change: transform;
}
html.has-cursor.is-pointing .cursor { opacity: 1; }

.cursor__circle {
  display: block; width: 2.2rem; height: 2.2rem; margin: -1.1rem 0 0 -1.1rem;
  border: 1.5px solid rgba(var(--cur), .96); border-radius: 50%;
  box-shadow: 0 0 5px rgba(var(--cur-edge), .32);   /* мягкое гало вместо жёсткой линии */
  transition: width .45s var(--e-out), height .45s var(--e-out), margin .45s var(--e-out);
}
.cursor__dot {
  position: absolute; top: 0; left: 0;
  width: .5rem; height: .5rem; margin: -.25rem 0 0 -.25rem;
  background: rgb(var(--cur)); border-radius: 50%;
  box-shadow: 0 0 4px rgba(var(--cur-edge), .32);
  transition: opacity .3s var(--e-out);
}

/* состояния по data-cursor */
html.cur-link .cursor__circle { width: 3.4rem; height: 3.4rem; margin: -1.7rem 0 0 -1.7rem; }
html.cur-link .cursor__dot { opacity: 0; }
html.cur-hide .cursor { opacity: 0; }

@media (hover: none) { .cursor { display: none; } }

/* ─── Зерно и виньетка ────────────────────────────── */

/* Порт screenFxPass.
   В оригинале: f = hash12(gl_FragCoord.xy + u_time) — шум пересчитывается
   КАЖДЫЙ кадр (несвязанный «телевизионный» снег), амплитуда f * 0.07,
   только осветление; виньетка pow(vig, .05) — почти невидима.
   Здесь: две текстуры белого шума, тексель = 1 px устройства, сдвиг
   быстрыми steps-шагами на разной частоте → кадры не коррелируют. */
/* Слой лежит ПОД контентом (z-index: -1): зерно остаётся на фоне страницы,
   а скриншоты интерфейса перекрывают его и остаются чистыми. В оригинале
   свечение маскируется тем же принципом — «* (1. - sceneColor.a)». */
.fx { position: fixed; inset: 0; z-index: -1; pointer-events: none; overflow: hidden;
      background: radial-gradient(118% 94% at 50% 50%, transparent 76%, rgba(0,0,0,var(--vignette)) 100%); }
.fx::before, .fx::after {
  content: ""; position: absolute; inset: -80px;
  background-repeat: repeat;
  background-size: 240px 240px;        /* масштаб зерна ×3 к прежнему */
  image-rendering: pixelated;
}
.fx::before { background-image: var(--noise-a); animation: grainA .36s steps(12) infinite; opacity: var(--grain); }
.fx::after  { background-image: var(--noise-b); animation: grainB .29s steps(9)  infinite; opacity: var(--grain); }

/* Тот же слой, но поверх контента и очень слабый — объединяет
   страницу и скриншоты в общую плёнку, не пачкая их. */
.fx--top { z-index: 70; background: none; }
.fx--top::before, .fx--top::after { opacity: var(--grain-top); }

@keyframes grainA {
  0%   { transform: translate3d(0, 0, 0); }
  8%   { transform: translate3d(-27px, 13px, 0); }
  17%  { transform: translate3d(19px, -31px, 0); }
  25%  { transform: translate3d(-11px, 37px, 0); }
  33%  { transform: translate3d(41px, 7px, 0); }
  42%  { transform: translate3d(-35px, -23px, 0); }
  50%  { transform: translate3d(9px, 29px, 0); }
  58%  { transform: translate3d(-43px, 17px, 0); }
  67%  { transform: translate3d(23px, -39px, 0); }
  75%  { transform: translate3d(-17px, -11px, 0); }
  83%  { transform: translate3d(37px, 33px, 0); }
  92%  { transform: translate3d(-29px, -37px, 0); }
  100% { transform: translate3d(0, 0, 0); }
}
@keyframes grainB {
  0%   { transform: translate3d(0, 0, 0); }
  11%  { transform: translate3d(31px, -19px, 0); }
  22%  { transform: translate3d(-39px, 27px, 0); }
  33%  { transform: translate3d(13px, 41px, 0); }
  44%  { transform: translate3d(-25px, -33px, 0); }
  56%  { transform: translate3d(43px, 11px, 0); }
  67%  { transform: translate3d(-15px, 35px, 0); }
  78%  { transform: translate3d(27px, -43px, 0); }
  89%  { transform: translate3d(-37px, -15px, 0); }
  100% { transform: translate3d(0, 0, 0); }
}

/* ─── Шапка ───────────────────────────────────────── */

.head {
  position: fixed; inset: 0 0 auto 0; z-index: 60;
  display: flex; align-items: center; gap: 1.5rem;
  padding: 1.6rem var(--pad);
  transition: transform .7s var(--e-io);
}
.head.is-off { transform: translateY(-120%); }
.head__logo { margin-right: auto; font-size: .95rem; text-transform: uppercase; letter-spacing: .02em; }
.head__logo span { opacity: .45; margin-left: .35em; }
.head__logo sup { font-size: .6em; }
.head__nav { display: none; gap: 1.6rem; font-size: .95rem; }
@media (min-width: 48rem) { .head__nav { display: flex; } }

.roll { position: relative; display: inline-block; overflow: hidden; vertical-align: bottom; }
.roll__a, .roll__b { display: block; transition: transform .55s var(--e-io); }
.roll__b { position: absolute; inset: 0; transform: translateY(105%); }
.roll:hover .roll__a { transform: translateY(-105%); }
.roll:hover .roll__b { transform: translateY(0); }

/* переключатель языка в шапке: пилюля в тон круглым кнопкам,
   разметку кнопок создаёт i18n.js */
.lang {
  display: flex; align-items: center; gap: .1rem;
  height: 2.6rem; padding: 0 .25rem;
  border: 1px solid var(--line); border-radius: 2rem;
  transition: border-color .4s var(--e-out);
}
.lang:hover { border-color: currentColor; }
.lang__b {
  font-size: .78rem; text-transform: uppercase; letter-spacing: .02em;
  padding: .35rem .55rem; border-radius: 2rem;
  color: var(--ink-2);
  transition: color .45s var(--e-out), background-color .45s var(--e-out);
}
.lang__b:hover { color: var(--ink); }
.lang__b.is-on { color: var(--bg); background: var(--ink); }
@media (max-width: 30rem) {                      /* на узких экранах шапка тесная */
  .head { gap: .8rem; }
  .lang { height: 2.2rem; padding: 0 .15rem; }
  .lang__b { font-size: .7rem; padding: .3rem .38rem; }
}

.burger, .theme-btn {
  width: 2.6rem; height: 2.6rem; border-radius: 50%; border: 1px solid var(--line);
  display: grid; place-content: center; gap: .28rem;
  transition: border-color .4s var(--e-out), background-color .4s var(--e-out);
}
.burger:hover, .theme-btn:hover { border-color: currentColor; }

/* ─── Подсказки на кнопках шапки ──────────────────── */
/* Текст живёт в атрибуте, поэтому переводится обычным data-t-attrs и не требует
   ни строчки JS. У кнопки темы атрибута два, и CSS выбирает нужный — тем же
   приёмом, что и сами иконки: подсказка называет тему, НА которую переключит
   нажатие, а не текущую. */
.tip { position: relative; }
.tip::after {
  content: attr(data-tip);
  position: absolute; top: calc(100% + .55rem); left: 50%;
  transform: translate(-50%, .2rem);
  padding: .34rem .6rem; border-radius: .45rem;
  background: var(--ink); color: var(--bg);
  font-size: .62rem; line-height: 1; letter-spacing: .01em;
  white-space: nowrap; pointer-events: none; z-index: 60;
  opacity: 0;
  transition: opacity .25s var(--e-out), transform .25s var(--e-out);
}
.tip:hover::after, .tip:focus-visible::after,
.tip:focus-within::after { opacity: 1; transform: translate(-50%, 0); }

.theme-btn::after { content: attr(data-tip-dark); }
:root[data-theme="dark"] .theme-btn::after { content: attr(data-tip-light); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-btn::after { content: attr(data-tip-light); }
}
:root[data-theme="light"] .theme-btn::after { content: attr(data-tip-dark); }

@media (hover: none) { .tip::after { display: none; } }   /* на тач наведения нет */

/* две линии внутри бургера; при открытом меню складываются в крестик */
.burger i {
  display: block; width: .8rem; height: 1px; background: currentColor;
  transition: transform .5s var(--e-io);
}
html.is-menu .burger i:first-child { transform: translateY(.145rem) rotate(45deg); }
html.is-menu .burger i:last-child  { transform: translateY(-.145rem) rotate(-45deg); }

/* иконка: солнце ↔ половина круга, простой кроссфейд с поворотом.
   Никаких перекрывающих дисков — раньше именно они срезали рамку кнопки.

   ⚠️ Показывается не текущая тема, а та, на которую переключит нажатие:
   на светлой висит половина круга, на тёмной — солнце. Выглядит как ошибка,
   но так задумано. Вернуть привычное «иконка = текущее состояние» — поменять
   местами .theme-btn__sun и .theme-btn__moon в трёх правилах ниже. */
.theme-btn__i { width: 1.05rem; height: 1.05rem; display: block; overflow: visible; }
.theme-btn__sun, .theme-btn__moon {
  transform-origin: 12px 12px;
  transition: opacity .4s var(--e-out), transform .6s var(--e-io);
}
.theme-btn__sun { opacity: 0; transform: rotate(70deg) scale(.5); }
:root[data-theme="dark"] .theme-btn__moon { opacity: 0; transform: rotate(-70deg) scale(.5); }
:root[data-theme="dark"] .theme-btn__sun  { opacity: 1; transform: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-btn__moon { opacity: 0; transform: rotate(-70deg) scale(.5); }
  :root:not([data-theme="light"]) .theme-btn__sun  { opacity: 1; transform: none; }
}

/* ─── Оверлей-меню ────────────────────────────────── */

.menu {
  position: fixed; inset: 0; z-index: 55; background: var(--bg);
  display: flex; flex-direction: column; justify-content: center; gap: 2.5rem;
  padding: 0 var(--pad);
  clip-path: inset(0 0 100% 0); transition: clip-path .9s var(--e-io);
  overflow-y: auto;                                   /* на низких экранах меню прокручивается */
}
.menu.is-open { clip-path: inset(0 0 0 0); }
.menu__list { display: grid; gap: .4rem; }
.menu__list li { display: flex; align-items: baseline; gap: 1rem; font-size: 2rem; text-transform: uppercase; }
@media (min-width: 48rem) {
  .menu { flex-direction: row; align-items: center; justify-content: flex-start; gap: 6rem; }
  .menu__list li { font-size: 3.4rem; }
}
.menu__n { font-size: .8rem; opacity: .4; }

/* Работы сгруппированы по типу: сейчас один раздел, дальше добавятся
   соседние — поэтому заголовок раздела отделён от списка ссылок. */
.menu__groups { display: grid; gap: 2.2rem; align-content: center; }
.menu__gt {
  margin-bottom: .7rem;
  font-size: .8rem; font-weight: 500; text-transform: uppercase; letter-spacing: .02em;
  color: var(--ink-2);
}
.menu__sub { display: grid; gap: .2rem; }
.menu__sub li { font-size: 1.2rem; text-transform: uppercase; }
@media (min-width: 48rem) { .menu__sub li { font-size: 1.6rem; } }
.menu__sub .is-current { color: var(--ink-2); }     /* текущая страница — приглушена */

/* ─── 1 · Титул ───────────────────────────────────── */

.caption-top {
  position: absolute; left: 50%; transform: translateX(-50%);
  top: 5rem; z-index: 2;
  font-size: .8rem; text-transform: uppercase; font-weight: 500; text-align: center;
}
.hero { position: relative; padding-top: 10rem; padding-bottom: var(--gap-s); }
@media (min-width: 48rem) { .hero { padding-top: 14rem; padding-bottom: var(--gap-l); } }

.hero__grid { position: relative; z-index: 2; }
.hero__head { text-align: center; }
.hero__desc { text-align: center; margin-top: .2em; }
@media (min-width: 48rem) {
  .hero__head { text-align: left; padding-left: .75rem; }
  .hero__desc { text-align: left; margin-left: 47%; }   /* смещение вправо, как offset-7/12 в оригинале */
}
.hero__head .serif, .hero__desc .serif { display: inline-block; }

.hero__object {                       /* на узких экранах — отдельным блоком под заголовком */
  position: relative; z-index: 1;
  width: 74%; max-width: 20rem; margin: 2.5rem auto 0;
  pointer-events: none;
}
@media (min-width: 48rem) {
  .hero__object {
    position: absolute; left: 30%; top: 66%; margin: 0;
    width: 46vw; max-width: 27rem;
    transform: perspective(1600px)
               rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg))
               translate3d(calc(-50% + var(--mx, 0px)), calc(-50% + var(--my, 0px)), 0);
  }
}
.hero__object picture { display: block; transform: translate3d(0, var(--py, 0px), 0); }

[data-float] { animation: float 9s ease-in-out infinite; }
@keyframes float { 0%, 100% { translate: 0 0; } 50% { translate: 0 -1.2rem; } }

/* ─── 3D-объект героя ─────────────────────────────── */

.obj { position: relative; aspect-ratio: 1000 / 693; }
.obj canvas { display: block; width: 100%; height: 100%; }
.obj__fallback {                 /* плоский логотип до/вместо WebGL */
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: contain; opacity: .85;
  filter: invert(var(--logo-invert)) saturate(1.02);
  transition: opacity .6s var(--e-out);
}
.obj.is-ready .obj__fallback { opacity: 0; }

/* ─── 2 · Мета-панель ─────────────────────────────── */

.meta { display: block; margin-bottom: var(--gap-s); }
@media (min-width: 48rem) {
  .meta { display: flex; gap: 8.333%; margin-bottom: var(--gap-l); }
  .meta__l { width: 50%; }
  .meta__r { width: 41.666%; display: flex; gap: 2rem; }
}
.meta__lead { font-size: 1.3rem; line-height: 1.3; font-weight: 300; margin-top: 1rem; }
@media (min-width: 48rem) { .meta__lead { font-size: 2rem; } }
.meta__r { margin-top: 2.5rem; display: flex; gap: 2rem; }
@media (min-width: 48rem) { .meta__r { margin-top: 0; } }
.meta__col { flex: 1; }
.meta__list { margin-top: .5rem; font-size: 1.2rem; font-weight: 500; line-height: 1.3; }
.meta__i { margin-bottom: 1.2rem; }
.meta__i p { font-size: 1.2rem; font-weight: 500; line-height: 1.1; margin-top: .25rem; }
.meta__col .btn { margin-top: 1.2rem; }

/* ─── О компании ──────────────────────────────────── */

.company { display: block; }
@media (min-width: 48rem) {
  .company { display: flex; gap: 8.333%; }
  .company__l { width: 50%; }
  .company__text { width: 41.666%; }
}
.company__name { margin-top: 1rem; font-size: 1.3rem; font-weight: 500; line-height: 1.2; }
@media (min-width: 48rem) { .company__name { font-size: 1.6rem; } }
.company__years { color: var(--ink-2); font-weight: 400; }
.company__link {
  display: inline-block; margin-top: .6rem;
  font-size: .95rem; color: var(--ink-2);
  border-bottom: 1px solid var(--line);
}
.company__link:hover { color: var(--ink); }
.company__text {
  margin-top: 1.5rem; font-size: 1rem; line-height: 1.5; color: var(--ink-2);
}
@media (min-width: 48rem) { .company__text { margin-top: 0; } }

/* ─── Задачи ──────────────────────────────────────── */

.tasks__lbl { display: block; margin-bottom: 1.6rem; }
.tasks__list { display: grid; gap: 0; }
@media (min-width: 48rem) { .tasks__list { grid-template-columns: 1fr 1fr; column-gap: 8.333%; } }
.tasks__list li {
  border-top: 1px solid var(--line);
  padding: .9rem 0 .9rem 1.6rem;
  position: relative;
  font-size: 1rem; line-height: 1.4;
}
.tasks__list li::before {
  content: counter(taskn, decimal-leading-zero);
  counter-increment: taskn;
  position: absolute; left: 0; top: .95rem;
  font-size: .75rem; color: var(--ink-2);
}
.tasks__list { counter-reset: taskn; }

/* ─── Кнопки (заливка снизу + перекатка подписи) ──── */

.btn {
  position: relative; display: inline-flex; align-items: center; gap: .5rem;
  padding: .75rem 1.3rem; border-radius: 3rem; overflow: hidden;
  border: 1px solid var(--line); font-size: .9rem; z-index: 0;
}
.btn::after {
  content: ""; position: absolute; inset: 0; z-index: -1; background: var(--ink);
  transform: translateY(101%); transition: transform .6s var(--e-io);
}
.btn:hover::after { transform: translateY(0); }
.btn:hover { color: var(--bg); border-color: transparent; }
.btn--fill { border-color: var(--ink); }
.btn__l { position: relative; display: block; overflow: hidden; }
.btn__t { display: block; transition: transform .6s var(--e-io); }
.btn__t:last-child { position: absolute; inset: 0; transform: translateY(110%); }
.btn:hover .btn__t:first-child { transform: translateY(-110%); }
.btn:hover .btn__t:last-child { transform: translateY(0); }
.btn__i { width: .8em; height: .8em; flex: none; transition: transform .55s var(--e-io); }
.btn:hover .btn__i { transform: translate(.2em, -.2em); }

/* ─── Медиа-блоки ─────────────────────────────────── */

.shot { position: relative; }
.shot + .shot { margin-top: 1.65rem; }     /* одинаковый вертикальный шаг */

/* Появление при въезде в кадр. Искажение у края экрана делает не CSS,
   а проход barrelDistortion в media-gl.js — как в оригинале. */
[data-scrub="peel"] picture,
[data-scrub="peel"] .vid {
  display: block;
  transform: translate3d(0, calc((1 - var(--p, 1)) * 2.5rem), 0);
  opacity: clamp(0, calc(var(--p, 1) * 3), 1);
  will-change: transform;
}

/* внутренний параллакс (аналог webglParallaxEffect)
   --k гасит смещение, пока курсор не вошёл в блок (см. 5a в main.js).
   Умолчание 1: одиночные картинки вне .grid/.compo двигаются как раньше. */
[data-scrub="parallax"] picture,
[data-scrub="parallax"] .vid {
  display: block;
  transform: translate3d(0, calc(var(--py, 0px) * var(--k, 1)), 0);
  will-change: transform;
}

/* В покое плитки стоят ровно по сетке — ноль ставится только блокам целиком,
   дальше значение наследуется плитками внутри. */
.grid, .compo { --k: 0; }

/* ─── Видео ───────────────────────────────────────── */
/* Длинные ролики: preload="none" — до нажатия с сервера тянется только постер.
   Короткие петли (data-loop) заводит main.js, когда они появляются в кадре. */
.vid { position: relative; }
.vid video,
.vid img {                 /* img — подменённая петля, см. toAnimation() в main.js */
  display: block; width: 100%; max-width: 100%; height: auto;
  /* ⚠️ Никакого своего цвета под медиа. Здесь стоял --bg-2 (#f4f5f8) — почти
     белый и в тёмной теме не переопределяемый, то есть под каждым роликом
     лежала белая подложка. Кадр не покрывает коробку элемента пиксель в пиксель
     (высота считается дробной, плюс сглаживание скруглённых углов), и подложка
     лезла наружу светлой каймой по краям. Подставлять вместо неё var(--bg) тоже
     не вариант: в светлой теме он на пару тонов расходится с фоном body.
     Прозрачный совпадает с любым фоном в любой теме — и это единственный
     вариант, который нельзя рассогласовать. */
  background: transparent;
}
/* ⚠️ Петлям нельзя pointer-events: none. Когда браузер блокирует автозапуск
   (Safari в энергосбережении — всегда), он рисует поверх видео свою кнопку play,
   и с отключёнными событиями мыши её невозможно нажать: пользователь кликает,
   ничего не происходит. Без controls клик по видео и так ничего не делает. */


/* реакция на мышь (аналог параллакса моделей от mouse.smooth)
   ⚠️ У соседних плиток data-mouse обязан различаться знаком: амплитуда идёт
   прямо из атрибута, и две соседки с близкими значениями одного знака смещаются
   на одни и те же пиксели — читаются как одна деталь, «прибитая» по месту. */
.compo__i[data-mouse],
.grid__i[data-mouse] {
  transform: perspective(1400px)
             rotateX(calc(var(--rx, 0deg) * var(--k, 1)))
             rotateY(calc(var(--ry, 0deg) * var(--k, 1)))
             translate3d(calc(var(--mx, 0px) * var(--k, 1)),
                         calc(var(--my, 0px) * var(--k, 1)), 0);
  transition: transform .1s linear;
}

/* ─── Композиции ──────────────────────────────────── */

.compo { position: relative; }
.compo__i { position: relative; }

/* А · Подписание: два окна + подсказка между ними */
.compo--sign { display: grid; gap: 2rem; align-items: center; }
@media (min-width: 48rem) {
  .compo--sign { grid-template-columns: 1fr .42fr 1fr; gap: 1rem; }
  .compo__i--a { margin-top: -3rem; }
  .compo__i--b { z-index: 3; }
  .compo__i--c { margin-top: 4rem; }
}

/* Б · Реестр + сертификаты внахлёст */
.compo--stack { display: grid; gap: 2rem; }
@media (min-width: 48rem) {
  .compo--stack { grid-template-columns: 1fr; padding-bottom: 10%; }
  .compo__i--list { width: 62%; }
  .compo__i--cert {
    position: absolute; right: 0; bottom: .85rem; width: 52%; z-index: 2;   /* поднято на ~12px */
  }
  .compo__i--card { position: absolute; right: 1.3%; top: -15px; width: 37.4%; z-index: 3; }   /* сдвинута влево на ~24px */
}

/* ─── Заголовок секции ────────────────────────────── */

.sec-head { margin-bottom: 3rem; }
@media (min-width: 48rem) {
  .sec-head { display: flex; gap: 2rem; align-items: flex-end; }
  .sec-head > * { width: 50%; }
}
.sec-head__n { color: var(--ink-2); font-size: 1rem; line-height: 1.4; margin-top: 1rem; }
.sec-head__n p + p { margin-top: .8rem; }
@media (min-width: 48rem) { .sec-head__n { margin-top: 0; } }

.split__t { max-width: 34rem; }
@media (min-width: 48rem) { .split__t { margin-left: 41.666%; } }
.split__p { margin-top: 1.2rem; font-size: 1.1rem; line-height: 1.45; color: var(--ink-2); }
.split__p + .split__p { margin-top: .9rem; }
.split__t .btn { margin-top: 1.8rem; }

/* ─── Этапы тестирования ─────────────────────────── */

.stages { display: grid; gap: 2rem; }
@media (min-width: 48rem) { .stages { grid-template-columns: repeat(3, 1fr); gap: 2.5rem; } }
.stage { border-top: 1px solid var(--line); padding-top: 1.1rem; }
.stage__n {
  display: block; font-size: clamp(2.2rem, 4.5vw, 3.4rem);
  line-height: 1; letter-spacing: -.04em;
}
.stage__t { display: block; margin-top: .7rem; font-size: 1.1rem; font-weight: 500; line-height: 1.25; }
.stage__d { display: block; margin-top: .5rem; color: var(--ink-2); font-size: .95rem; line-height: 1.4; }

/* ─── 7 · Отзыв ───────────────────────────────────── */

.testi .lbl { display: block; max-width: 46rem; line-height: 1.35; }
.testi__box { border-top: 1px solid var(--line); margin-top: 1.2rem; padding-top: 1.2rem; }
.testi__q { font-size: 2rem; line-height: 1.08; font-weight: 500; }
@media (min-width: 48rem) { .testi__q { font-size: 3rem; } }
.testi__a { margin-top: 1.5rem; font-size: 1rem; text-transform: uppercase; font-weight: 500; }
@media (min-width: 48rem) { .testi__a { font-size: 1.3rem; } }

/* ─── 8 · Награды ─────────────────────────────────── */

.awards { display: block; overflow: hidden; }
@media (min-width: 48rem) { .awards { display: flex; gap: 3rem; } }
.awards__l { position: relative; width: 100%; }
@media (min-width: 48rem) { .awards__l { width: 40%; } .awards__r { width: 60%; padding-top: 5rem; } }
.awards__title { font-size: 2rem; line-height: 1.16; font-weight: 500; }
@media (min-width: 48rem) { .awards__title { font-size: 3rem; } }

.awards__obj { width: 9rem; margin-top: 2.5rem; }   /* тот же .obj, только мельче */

.award { border-top: 1px solid var(--line); transition: transform 1s var(--e-out); }
.award > h3, .award > p { display: inline-block; width: 50%; vertical-align: top; }
.award h3 { position: relative; padding: 1.1rem 0; font-size: 1.15rem; text-transform: uppercase; font-weight: 400; }
.award p  { padding: 1.15rem 0; font-size: .85rem; text-transform: uppercase; color: var(--ink-2); }
.award__arr { position: absolute; left: -1.25rem; overflow: hidden; display: inline-block; width: 1.25rem; font-style: normal; }
.award__arr span { display: inline-block; transform: translateX(-140%); transition: transform 1s var(--e-out); font-size: .7em; }
.award.is-on { transform: translateX(1.25rem); }
.award.is-on .award__arr span { transform: translateX(0); }

/* ─── 9 · Следующий кейс ──────────────────────────── */

.next {
  position: relative; z-index: 1;
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  text-align: center; padding: var(--gap-s) var(--pad);
}
.next__lbl { display: block; font-size: 1.6rem; text-transform: uppercase; }
@media (min-width: 64rem) { .next__lbl { font-size: 3rem; } }
.next__title {
  font-size: 3rem; line-height: 1.2; letter-spacing: -.05rem; font-weight: 400;
  text-transform: uppercase; margin: .2em 0 .4em;
  transform: translate3d(0, calc(var(--nt, 0) * -6rem), 0);
}
@media (min-width: 64rem) { .next__title { font-size: 6rem; letter-spacing: -.1rem; } }
.next__hint { font-size: 1rem; text-transform: uppercase; }
/* Кнопка «Связаться» в подвале кейса: контакт должен быть виден с любой
   страницы, а не только через меню. Стоит перед полосой перехода, чтобы не
   спорить с ней за внимание. */
.next__cta {
  display: inline-flex; align-items: center;
  margin-top: 1.6rem; padding: .7rem 1.5rem;
  border: 1px solid var(--line); border-radius: 2rem;
  font-size: .78rem; text-transform: uppercase; letter-spacing: .08em;
  text-decoration: none; color: inherit;
  transition: border-color .4s var(--e-out), background-color .4s var(--e-out);
}
.next__cta:hover { border-color: currentColor; }

.next__line { display: block; width: 12rem; height: 2px; margin: .6rem auto 0; background: var(--line); overflow: hidden; }
.next__line i { display: block; height: 100%; background: currentColor; transform: scaleX(var(--np, 0)); transform-origin: 0 50%; }

/* плоскость перехода: поднимается снизу, край прогибается от скорости */
.veil { position: fixed; inset: 0; z-index: 65; pointer-events: none; overflow: hidden; visibility: hidden; }
.veil.is-on { visibility: visible; }
.veil i {
  position: absolute; left: -10%; width: 120%; height: 140%; bottom: 0;
  background: var(--next-bg);
  transform: translate3d(0, calc((1 - var(--vp, 0)) * 100%), 0);
  border-radius: 50% 50% 0 0 / calc(var(--vv, 0) * 14rem) calc(var(--vv, 0) * 14rem) 0 0;
}

/* ─── Углы экрана ─────────────────────────────────── */

.corner { position: fixed; z-index: 60; font-size: .8rem; text-transform: uppercase; }
.corner--up {
  left: var(--pad); bottom: 1.6rem; width: 2.6rem; height: 2.6rem; border-radius: 50%;
  border: 1px solid var(--line); display: grid; place-content: center;
  opacity: 0; transform: translateY(.5rem); transition: opacity .5s, transform .5s;
}
.corner--up.is-on { opacity: 1; transform: none; }
.corner--cr { right: var(--pad); bottom: 1.9rem; color: var(--ink-2); }

/* ─── Появление / вытирание ───────────────────────── */

[data-rev] { opacity: 0; transform: translate3d(0, 1.2rem, 0); transition: opacity .9s var(--e-out), transform .9s var(--e-out); }
[data-rev].is-in { opacity: 1; transform: none; }

/* шторка цвета фона над текстом — аналог шумового TextReveal.
   Маска закрашивается строго по боксу элемента, поэтому выносные
   элементы последней строки обрезались: добавляем запас и снимаем
   его отрицательным полем. */
[data-wipe] {
  padding-block: .1em .16em;
  padding-inline: .14em;           /* маска режет и по горизонтали */
  margin-block: -.1em -.16em;
  margin-inline: -.14em;
  -webkit-mask-image: linear-gradient(108deg, #000 0 var(--m1, 0%), rgba(0,0,0,.35) var(--m2, 4%), transparent var(--m3, 12%));
          mask-image: linear-gradient(108deg, #000 0 var(--m1, 0%), rgba(0,0,0,.35) var(--m2, 4%), transparent var(--m3, 12%));
}

/* буквы заголовка выезжают из собственной маски */
/* Область отсечения шире строки: сверху пускаем бреве «Й» и верхние
   выносные, снизу — хвосты курсива. Отрицательные поля возвращают
   исходный ритм, поэтому вёрстка не сдвигается. */
.ln {
  display: block; overflow: hidden;
  padding: .22em .18em .18em;      /* по горизонтали — под наклон курсива */
  margin: -.22em -.18em -.18em;
}
.wd { display: inline-block; white-space: nowrap; }
.ch { display: inline-block; transform: translateY(150%); transition: transform 1.1s var(--e-io); }
.ch--sp { display: inline-block; }
html.is-intro .ch { transform: translateY(0); }

/* ─── Настройки доступности ───────────────────────── */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; }
  [data-rev] { opacity: 1; transform: none; }
  .ch { transform: none; }
  [data-wipe] { -webkit-mask-image: none; mask-image: none; }
  [data-scrub] picture { transform: none !important; opacity: 1 !important; }
  .loader { display: none; }
  [data-float] { animation: none; }
  .fx::before { animation: none; }
}
