/* ============================================================
   flight.css — слои полёта в букву.

   Снизу вверх: страница направления (в рамке), белая пелена, канвас
   первого экрана (в нём полёт делает дыру), виньетка объектива,
   интерфейс первого экрана. Пока полёта нет, всё это невидимо и
   страница закрыта непрозрачным листом — первый экран выглядит ровно
   как в эталоне.
   ============================================================ */

/* Первый экран поверх страницы. */
.hero { z-index: 10; }

#flight {
  position: fixed;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  /* Рамка должна успеть отрисоваться заранее, поэтому она видима и лишь
     закрыта листом (#flight__sheet) — скрытая рамка не рисуется. */
}
#flight__portal {
  position: absolute;
  inset: 0;
  /* Цвет бумаги страницы: её собственный масштаб чуть меньше единицы,
     и по краям не должно просвечивать. */
  background: #fbfaf7;
  contain: paint;
}
#flight__grade {
  position: absolute;
  inset: 0;
}
/* Слои для видеокарты — только на время полёта: страницы теперь
   загружены заранее и лежат тут весь сеанс, и постоянный will-change
   держал бы полноэкранные слои в памяти телефона без дела. */
.is-flying #flight__portal { will-change: transform; }
.is-flying #flight__grade { will-change: filter; }
/* Рамки страниц направлений: загружены заранее все, отрисована одна —
   выбранная. Скрытые не рисуются и места на видеокарте не занимают. */
.flight__frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
  visibility: hidden;
}
.flight__frame.is-armed { visibility: visible; }
/* Пелена над самой страницей: скрывает её детали, пока мы далеко.
   Пелена и лист — только картинка. Прозрачный слой всё равно ловит
   касания, прокрутку и щелчки: без pointer-events: none страница после
   прилёта не прокручивалась бы и не нажималась — как снимок. */
#flight__haze {
  position: absolute;
  inset: 0;
  background: #fff;
  opacity: 0;
  pointer-events: none;
}
/* Лист, который держит прогретую страницу невидимой до полёта. */
#flight__sheet {
  position: absolute;
  inset: 0;
  background: var(--bg);
  pointer-events: none;
}
/* Засветка объектива поверх всего кадра: и страницы, и знака, и стены.
   Из темноты на свет слепит целиком, а не только в проёме — и именно
   это снимает разницу между светлым штрихом буквы и тёмной стеной. */
#flight__glow {
  position: fixed;
  inset: 0;
  z-index: 11;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(circle at var(--fx, 50%) var(--fy, 50%),
    #fff 0%, #fff 42%, rgba(255, 255, 255, 0.86) 72%, rgba(255, 255, 255, 0.62) 100%);
}

/* Виньетка объектива: тем сильнее, чем быстрее движение. */
#flight__vign {
  position: fixed;
  inset: 0;
  z-index: 12;
  pointer-events: none;
  opacity: 0;
  /* Широкая и слабая: объектив, а не пятно. Узкая тёмная кайма вокруг
     знака читалась как приклеенный кружок. */
  background: radial-gradient(circle at var(--fx, 50%) var(--fy, 50%),
    rgba(0, 0, 0, 0) 48%, rgba(0, 0, 0, 0.32) 86%, rgba(0, 0, 0, 0.6) 100%);
  /* Без mix-blend-mode: для чёрного градиента «умножение» и обычное
     наложение дают одно и то же (dst·(1 − a)), а режим наложения
     заставлял Safari пересчитывать весь кадр под виньеткой отдельно. */
}

/* Полёт идёт: стена первого экрана больше не рисуется средствами CSS
   (иначе дыра в канвасе показывала бы её), интерфейс уходит. */
.is-flying .hero { background: none; }
.is-flying .hero__stage,
.is-flying .services,
.is-flying .site-header {
  opacity: 0;
  transition: opacity 180ms linear;
  pointer-events: none;
}
.is-flying #flight { pointer-events: none; }
/* Первые кадры возврата со страницы: канвас спрятан, пока не показан его
   новый кадр (иначе мелькнул бы старый — знак на стене). В эти кадры он и
   так прозрачен: видна страница. */
.is-rewinding .hero__canvas { opacity: 0; }
/* Конец возврата: знак мягко оседает, интерфейс проявляется вместе с ним. */
.is-flying.is-settling .hero__stage,
.is-flying.is-settling .services,
.is-flying.is-settling .site-header {
  opacity: 1;
  transition: opacity 360ms ease-out;
}
/* Нажали, а полёт ещё готовится (доли секунды) — курсор ожидания. */
.is-waiting .hero { cursor: progress; }

/* Прилетели: первый экран не нужен, страница живая. */
.is-landed .hero { display: none; }
/* Шапка первого экрана лежит выше страницы (z-index 20): невидимая, она
   перехватывала бы касания верхней полосы страницы и вела не туда. */
.is-landed .site-header { display: none; }
.is-landed #flight { pointer-events: auto; }
.is-landed #flight__vign,
.is-landed #flight__glow { display: none; }

@media (prefers-reduced-motion: reduce) {
  /* Полёта нет: остаются обычные переходы по ссылкам. */
  .is-flying .hero__stage,
  .is-flying .services,
  .is-flying .site-header { transition: none; }
}

/* Safari 26 на iPhone: полосы у краёв экрана, по которым браузер красит
   свои панели (создаются только там, см. setChrome в js/flight/shell.js).
   Тоньше 11 px WebKit их цвет не учитывает. */
.flight__edge {
  position: fixed;
  left: 0;
  right: 0;
  height: 12px;
  z-index: 5;
  pointer-events: none;
}
.flight__edge--t { top: 0; }
.flight__edge--b { bottom: 0; }
