/* ═══════════════════════════════════════════════════════════════
   Презентация «Будем знакомы» — отдельная страница, к сайту не привязана.
   Макет Figma: страница «preza», девять фреймов 1280×832.

   Единица вёрстки — --u: одна «проектная» точка макета в пикселях экрана.
   Все размеры пишутся как calc(N * var(--u)), где N — число из Figma.
   Так слайд тянется по окну целиком и не мылит текст (в отличие от
   transform: scale на контейнере).
   ═══════════════════════════════════════════════════════════════ */

:root{
  --bg:#F2F1ED;
  --ink:#2A2A2A;
  --accent:#F84E4E;
  --white:#FFFFFF;

  /* Кадр 1280×832 — это пропорция макбука (1,54). Тянем его по ширине: работы,
     которые в макете уходят за край, должны обрываться о край окна, а не
     посреди экрана. Расплата — подрезка сверху и снизу.

     Знаменатель 712, а не 832, и это предел подрезки: (832−712)/2 = 60 точек
     с каждой стороны. До 1280/712 = 1,80 (то есть включая 16:9) выигрывает
     ширина и кадр идёт во всю ширину; на более широких окнах включается
     ограничение и возвращаются поля по бокам — иначе на 21:9 срезало бы
     146 точек и съело заголовок с номером раздела.

     Запас проверен по вёрстке: при подрезке в 60 точек очко строки заголовка
     (кегль 16 в строке 40) начинается примерно на y=58, номера раздела — на 62. */
  --u: min(100vw / 1280, 100vh / 712);

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

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

/* Обычный сплошной скрол, без снапа. Снап здесь пробовали — он всё ломал:
   внутри прилипшего экрана скрол стоит, а значит параллаксу негде проявиться,
   он мелькал только в момент перелистывания. */
/* Скрол с привязкой к блокам. Без неё дальность прокрутки зависит от силы
   жеста: слабое движение оставляло экран на середине перехода, сильное
   перебрасывало через блок. Здесь любой жест доводит ровно до начала секции. */
html{
  background:var(--bg);
  scroll-snap-type:y mandatory;
  scroll-behavior:auto;
  -webkit-font-smoothing:antialiased;
}

body{
  font-family:'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  color:var(--ink);
  background:var(--bg);
  overflow-x:hidden;
}

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

/* ─────────────────────────── СЛАЙД ─────────────────────────── */

/* Секция — просто экран, встык со следующей. Здесь были шторки (sticky +
   z-index, как проекты на сайте), и от них пришлось отказаться: переезд одной
   секции поверх другой стоит ровно экран прокрутки, и всё это время либо едет
   пустой блок, либо содержимое ползёт снизу. До нужного раздела выходило три
   поворота колеса. Обычная лента предсказуемее и ведёт себя нативно. */
.slide{
  position:relative;
  height:100vh;
  background:var(--bg);
  display:block;
  scroll-snap-align:start;
  /* always, а не normal: иначе один резкий жест перепрыгивает через блок */
  scroll-snap-stop:always;
}

/* .pin остался от шторок и больше не липнет — просто держит кадр по центру */
.pin{
  position:relative;
  height:100vh;
  display:flex;
  align-items:center;
  justify-content:center;
  overflow:hidden;
}


/* кадр 1280×832 — система координат макета */
.stage{
  position:relative;
  width:calc(1280 * var(--u));
  height:calc(832 * var(--u));
  overflow:hidden;
}

/* ─────────────────────── СЛОИ КОЛЛАЖА ─────────────────────── */

/* Контейнер вокруг плиток. Перспективу сюда не класть: пробовали пускать слои
   на зрителя через translateZ — движение ломало композицию. */
.depth{
  position:absolute;
  inset:0;
}

/* Позиция и размер приходят из Figma в --x/--y/--w/--h.
   --d — глубина: множитель отклика на скрол и на мышь.
   JS двигает .tile, ховер-масштаб живёт на .tile__in — так две
   трансформации не дерутся за один узел. */

.tile{
  position:absolute;
  left:calc(var(--x) * var(--u));
  top:calc(var(--y) * var(--u));
  width:calc(var(--w) * var(--u));
  height:calc(var(--h) * var(--u));
  will-change:transform;
}

.tile__in{
  position:absolute;
  inset:0;
  transition:transform .55s var(--ease), filter .45s ease, opacity .45s ease;
}

/* видео ложится поверх кадра-постера, а не под ним в потоке */
.tile__in img,
.tile__in video{
  position:absolute;
  inset:0;
  display:block;
  width:100%;
  height:100%;
  object-fit:cover;
}

/* Появление слоёв: из блюра. Сдвиг по глубине навешивает JS в том же
   transform, что и параллакс, — поэтому здесь только opacity и filter,
   иначе inline-стиль затрёт стартовое положение. Правила спрятаны за
   html.js: без скрипта коллаж просто виден. */
html.js .tile{
  opacity:0;
  filter:blur(calc(9px * var(--d) * 4));
}
/* Очередь плиток задаёт время, а не скрол. Скролом это уже пробовали — у каждой
   плитки был свой порог по прокрутке, и при быстром пролистывании часть просто
   не успевала проявиться. Здесь же лесенка по --i задаёт старт, а длительность
   зависит от глубины: дальние слои набираются дольше ближних, поэтому коллаж
   приходит не монолитом. Та же лесенка продублирована в JS для подъёма. */
html.js .tile.is-vis{
  opacity:1;
  filter:blur(0);
  transition-property:opacity, filter;
  transition-timing-function:var(--ease);
  transition-duration:calc(650ms + var(--d, .1) * 2200ms);
  transition-delay:calc(var(--i, 0) * 90ms);
}

/* ── ховер по коллажу: наведённый слой просто подрастает ── */
/* Ни тени, ни притухания соседей, ни z-index: стопка слоёв остаётся ровно
   такой, как в макете, — иначе работы перескакивают друг через друга. */

.tile.is-hot .tile__in{ transform:scale(1.055); }

/* ────────────────────────── ТЕКСТ ────────────────────────── */

.t{
  position:absolute;
  left:calc(var(--x) * var(--u));
  top:calc(var(--y) * var(--u));
  width:calc(var(--w) * var(--u));
  z-index:30;
  white-space:pre-wrap;
}

/* размеры кегля и интерлиньяжа — из макета */
.t--16-26{ font-size:calc(16 * var(--u)); line-height:calc(26 * var(--u)); }
.t--16-40{ font-size:calc(16 * var(--u)); line-height:calc(40 * var(--u)); }
.t--16-25{ font-size:calc(16 * var(--u)); line-height:calc(25 * var(--u)); }
.t--12-23{ font-size:calc(12 * var(--u)); line-height:calc(23 * var(--u)); }
.t--12-44{ font-size:calc(12 * var(--u)); line-height:calc(44 * var(--u)); }
.t--16-16{ font-size:calc(16 * var(--u)); line-height:calc(16 * var(--u)); }

.t--accent{ color:var(--accent); }
.t--white{ color:var(--white); }
.t--up{ text-transform:uppercase; }
.a{ color:var(--accent); }

/* появление текста: блюр + подъём, построчно */
html.js .rv{
  opacity:0;
  filter:blur(9px);
  transform:translate3d(0, calc(16 * var(--u)), 0);
}
html.js .rv.is-vis{
  opacity:1;
  filter:blur(0);
  transform:none;
  transition:opacity .85s var(--ease), filter .85s var(--ease), transform .85s var(--ease);
  transition-delay:calc(var(--i, 0) * 80ms);
}

/* ───────────────── ОБЛОЖКА: портрет и бегущая строка ───────────────── */

/* четыре белые метки по углам портрета — тот же мотив, что у курсора */
.mark{
  position:absolute;
  left:calc(var(--x) * var(--u));
  top:calc(var(--y) * var(--u));
  width:calc(5 * var(--u));
  height:calc(5 * var(--u));
  background:var(--white);
  z-index:20;
}

.marquee{
  position:absolute;
  left:calc(494 * var(--u));
  top:calc(284 * var(--u));
  width:calc(257 * var(--u));
  height:calc(40 * var(--u));
  background:var(--accent);
  overflow:hidden;
  z-index:15;
  display:flex;
  align-items:center;
}

.marquee__track{
  display:flex;
  flex:none;
  white-space:nowrap;
  animation:marquee 22s linear infinite;
}

.marquee__track span{
  padding-right:calc(14 * var(--u));
  font-size:calc(14.95 * var(--u));
  line-height:1;
  color:var(--white);
  text-transform:uppercase;
}
.marquee__track b{ color:#DA2C2C; font-weight:400; padding-right:calc(14 * var(--u)); }

@keyframes marquee{ to{ transform:translateX(-50%); } }

/* ───────────── ЗАГОЛОВОК РАЗДЕЛА НА ЭКРАНЕ-РАЗБЕГЕ ───────────── */
/* Перед каждым разделом стоит .slide--intro с названием во весь экран. Оно
   выезжает буквами, уходит обратно под маску — и уже на самом разделе тем же
   движением появляется маленький заголовок на своём месте по макету.

   Кегль 95, а не фигмовские 102,3: там CS Genio Mono, здесь IBM Plex Mono —
   у Plex шире буква, и на 95 длина строки совпадает с макетом. */
.t--big{
  font-size:calc(95 * var(--u));
  line-height:calc(237.5 * var(--u));
  text-align:center;
}

/* Разбег высотой в два экрана. Первый — заголовок стоит один и уходит под
   маску; следующая секция начинает наезжать только со второго, когда её верх
   входит в окно. Липким тут должен быть не сам разбег, а внутренний .pin:
   у секции на 200vh sticky прижал бы к верху весь блок, и содержимое,
   отцентрованное по двум экранам, уехало бы вниз.

   overflow:hidden на разбеге тоже нельзя — он сделал бы секцию контейнером
   прокрутки, и .pin внутри перестал бы липнуть. Прячем через .pin. */
/* Заголовок стоит один 40 % экрана, дальше начинает приходить раздел. Пробовали
   и полтора экрана (тогда до контента приходилось листать в три приёма), и
   115vh — там заголовок уходил под маску почти сразу, не дав себя прочитать.
   Сам переезд шторки поверх этого занимает ещё экран прокрутки. */
.slide--intro{ height:100vh; }

/* без скрипта разбег не нужен: заголовок раздела и так стоит на своём месте */
.slide--intro{ display:none; }
html.js .slide--intro{ display:block; }

/* ───────────── ТЕКСТ АКЦЕНТНОГО ЦВЕТА: ВЫЕЗД БУКВАМИ ───────────── */
/* Каждая буква сидит в своей маске и выезжает снизу с задержкой по номеру.
   Слово при этом остаётся цельным (inline-flex) — иначе строка рвалась бы
   посреди слова, ведь каждая буква стала инлайн-блоком. */

.cut .w{ display:inline-flex; }

.cut .m{
  display:inline-block;
  overflow:hidden;
  vertical-align:bottom;
  padding-bottom:.14em;      /* запас под выносные элементы: у, р, д */
  margin-bottom:-.14em;
}

.cut .m > i{
  display:inline-block;
  font-style:normal;
  transform:translateY(115%);
}

html.js .cut.is-vis .m > i{
  transform:none;
  transition:transform .62s var(--ease);
  transition-delay:calc(var(--c, 0) * 18ms);
}

/* уход — тем же движением дальше вверх */
html.js .cut.is-out .m > i{
  transform:translateY(-115%);
  transition:transform .62s var(--ease);
  transition-delay:calc(var(--c, 0) * 12ms);
}

/* ──────────────── СЛАЙД 01: плашка про образование ──────────────── */

/* z-index не задаём намеренно: плашка стоит среди плиток на своём месте
   в разметке, и порядок отрисовки должен решать он. С z-index плашка
   перебивала слои, идущие после неё, — скриншот сертификата уезжал под неё. */
.plate{
  position:absolute;
  left:calc(var(--x) * var(--u));
  top:calc(var(--y) * var(--u));
  width:calc(var(--w) * var(--u));
  height:calc(var(--h) * var(--u));
  background:var(--accent);
}

/* ─────────────────────── СЧЁТЧИК СЛАЙДОВ ─────────────────────── */

.hud{
  position:fixed;
  right:calc(40 * var(--u));
  bottom:calc(34 * var(--u));
  z-index:60;
  font-size:calc(12 * var(--u));
  line-height:1;
  letter-spacing:.08em;
  color:var(--ink);
  opacity:.38;
  pointer-events:none;
  transition:opacity .3s ease;
}

/* ─────────────────────────── КУРСОР ─────────────────────────── */
/* Перенесён с портфолио без изменений: две независимые fixed-ноды,
   «чернила» с difference-блендом и цветной слой. Объединять нельзя —
   transform родителя изолирует mix-blend-mode. */

.cursor-ink,
.cursor-ui{
  position:fixed;
  left:0; top:0;
  z-index:95;
  pointer-events:none;
  visibility:hidden;
  will-change:transform;
}
html.has-cursor .cursor-ink,
html.has-cursor .cursor-ui{ visibility:visible; }

.cursor-ink{ mix-blend-mode:difference; }

.cursor-ink__dot,
.cursor-ink__side{
  position:absolute;
  left:0; top:0;
  width:3px; height:3px;
  margin:-1.5px 0 0 -1.5px;
  display:block;
  background:#fff;
  transform:translate(var(--dx), var(--dy)) rotate(0deg) scale(0);
  transition:transform .38s cubic-bezier(.22,.61,.36,1);
}
.cursor-ink__dot:nth-child(1){ --dx:-6.45px; --dy:-6.45px; }
.cursor-ink__dot:nth-child(2){ --dx: 6.45px; --dy:-6.45px; }
.cursor-ink__dot:nth-child(3){ --dx: 6.45px; --dy: 6.45px; }
.cursor-ink__dot:nth-child(4){ --dx:-6.45px; --dy: 6.45px; }
.cursor-ink__side:nth-child(5){ --dx:-12px; --dy:0px; }
.cursor-ink__side:nth-child(6){ --dx: 12px; --dy:0px; }

html.c-awake .cursor-ink__dot{
  transform:translate(var(--dx), var(--dy)) rotate(0deg) scale(.7);
}
html.c-awake.c-down .cursor-ink__dot{
  transform:translate(var(--dx), var(--dy)) rotate(0deg) scale(.55);
}
html.c-awake.c-link .cursor-ink__dot{
  transform:translate(var(--dx), var(--dy)) rotate(45deg) scale(1);
}
html.c-awake.c-link.c-down .cursor-ink__dot{
  transform:translate(var(--dx), var(--dy)) rotate(45deg) scale(.82);
}

/* над коллажем углы разъезжаются шире — «рассматриваю» */
html.c-awake.c-view .cursor-ink__dot{
  transform:translate(calc(var(--dx) * 1.9), calc(var(--dy) * 1.9)) rotate(45deg) scale(.9);
}
html.c-awake.c-view.c-down .cursor-ink__dot{
  transform:translate(calc(var(--dx) * 1.6), calc(var(--dy) * 1.6)) rotate(45deg) scale(.75);
}

.cursor-ui__accent{
  position:absolute;
  left:-4.5px; top:-4.5px;
  width:9px; height:9px;
  display:block;
  background:var(--accent);
  opacity:0;
  transform:rotate(45deg) scale(0);
  transition:transform .38s cubic-bezier(.22,.61,.36,1), opacity .28s ease;
}
html.c-awake.c-link .cursor-ui__accent,
html.c-awake.c-view .cursor-ui__accent{ opacity:1; transform:rotate(45deg) scale(1); }
html.c-awake.c-link.c-down .cursor-ui__accent,
html.c-awake.c-view.c-down .cursor-ui__accent{ transform:rotate(45deg) scale(.8); }

/* на красной плашке ромб того же цвета слился бы с фоном */
html.c-awake.c-onaccent .cursor-ui__accent{ background:#fff; }

html.has-cursor,
html.has-cursor body,
html.has-cursor *{ cursor:none; }

/* ───────────────────── БЕРЕЖНЫЙ РЕЖИМ ───────────────────── */

@media (prefers-reduced-motion:reduce){
  .marquee__track{ animation:none; }
  html.js .tile,
  html.js .rv{ opacity:1; filter:none; transform:none; }
  .cursor-ink__dot,
  .cursor-ink__side,
  .cursor-ui__accent{ transition-duration:.12s; }
}
