/* Дыхание кадра: параллакс при прокрутке и медленный наплыв.

   ЗАЧЕМ. Неподвижная фотография на экране - единственное, что в салоне
   не бывает неподвижным: пар, пламя, вода всегда чуть движутся. Кадр
   поэтому живёт двумя движениями. При прокрутке он едет медленнее
   страницы, и плоский экран получает глубину. Стоя на месте, он очень
   медленно приближается и отходит - сорок две секунды в одну сторону,
   темп, который глаз не ловит как движение, но чувствует как жизнь.

   ПОЧЕМУ ЭТО НЕ СТОИТ ПРОИЗВОДИТЕЛЬНОСТИ. Здесь три решения, и каждое
   отдельно принято ради скорости.

   1. Параллакс считает НЕ скрипт, а браузер: анимация привязана к
      положению кадра в окне (animation-timeline: view()) и идёт на
      видеокарте, минуя основной поток. Обработчик прокрутки на каждый
      кадр - самый дорогой из известных способов сделать то же самое,
      и его здесь нет. Браузер, который такой привязки не знает,
      получает кадр без параллакса, а не сломанный: этот блок стоит
      под @supports.

   2. Меняются только scale и translate - свойства, которые двигают
      готовый слой, не перерисовывая его. Раскладка не считается ни разу.
      Запас под движение сделан увеличением (scale), а не высотой
      элемента: высота - свойство раскладки, и она потянула бы за собой
      перерасчёт соседей.

   3. Наплыв идёт ТОЛЬКО у кадров в экране. Класс is-live ставит
      наблюдатель пересечения в скрипте; без класса анимация стоит на
      паузе, и десять кадров страницы не тикают вхолостую за экраном.
      Без скрипта, стало быть, наплыва нет вовсе - и это правильно:
      лучше кадр без дыхания, чем страница, дышащая целиком в никуда.

   Наплыв и параллакс - на разных свойствах (scale и translate), а не
   на общем transform: два движения с разными часами (время и прокрутка)
   на одном свойстве невозможны, побеждало бы одно. */

/* Запас в 14% - это по 7% с каждой стороны, ровно столько, сколько
   кадр смещается параллаксом. Меньше - и на краю движения показался бы
   фон; больше - лишняя мягкость от увеличения. */
/* Контейнер кадра обрезает через clip, а не hidden: hidden делает его
   прокручиваемым контейнером, и view() привязывается к нему вместо окна -
   параллакс замирает на нуле (см. .home-block в home.css). То же
   касается ВСЕХ предков до окна; их правки лежат в их файлах. */
[data-drift]{overflow:hidden;overflow:clip}
/* Увеличение идёт вокруг точки кадрирования, а не центра: у сертификата
   фокус сдвинут вправо (--focus в cinema.css), и увеличение от центра
   вытолкнуло бы край карты за обрез. Токен тот же, что у object-position. */
[data-drift]>img,[data-drift]>picture>img,[data-drift]>video{
  scale:1.14;transform-origin:var(--focus,50% 50%)}

/* Наплыв - только у фотографий. У видео своё движение, второе поверх
   него было бы суетой. */
[data-drift]>img,[data-drift]>picture>img{
  animation:breathe 42s var(--ease-breath) infinite alternate}
@keyframes breathe{from{scale:1.14}to{scale:1.21}}
/* Кадр под роликом плитки (.tile-poster) движется как ролик, а не как
   фотография: без наплыва. Иначе в момент, когда ролик проявляется
   поверх, масштабы разошлись бы и картинка дёрнулась. */
[data-drift]>img.tile-poster{animation:none}

@supports (animation-timeline:view()){
  [data-drift]>img,[data-drift]>picture>img{
    animation:drift linear both,breathe 42s var(--ease-breath) infinite alternate;
    animation-timeline:view(),auto;
    animation-range:cover,normal}
  [data-drift]>video{
    animation:drift linear both;animation-timeline:view();animation-range:cover}
  [data-drift]>img.tile-poster{
    animation:drift linear both;animation-timeline:view();animation-range:cover}
  /* Герой начинает уже в экране: у него есть только уход. Кадр отстаёт
     от страницы, пока та уносит его вверх; запас не нужен - открывшийся
     верх кадра к тому моменту за краем окна. */
  [data-drift="exit"]>video{
    scale:none;animation:sink linear both;animation-timeline:view();animation-range:exit}
}
/* Смещение в процентах собственной высоты: при увеличении 1.14 шесть
   процентов элемента дают 6.8% на экране - внутри семипроцентного запаса. */
@keyframes drift{from{translate:0 -6%}to{translate:0 6%}}
@keyframes sink{from{translate:0 0}to{translate:0 18%}}

/* Пауза за экраном. Параллакс от неё не страдает: он и так не движется,
   пока кадр не в окне. */
[data-drift]:not(.is-live)>img,[data-drift]:not(.is-live)>picture>img,
[data-drift]:not(.is-live)>video{animation-play-state:paused}


/* Свечение метки: та же волна, тот же ритм.

   Золотая метка над заголовком - единственная тёплая точка в начале
   каждой секции, и от неё исходит еле заметный свет, разгорающийся
   и угасающий за те же 5.6 секунды, что и всё остальное на странице.
   Заметить его нельзя, а убрать - можно: без него начало секции
   становится плоским.

   ПОЧЕМУ isolation, а не просто z-index:-1. Отрицательный номер слоя
   уводит псевдоэлемент за ближайший фон - а фон здесь у секции
   (чётные секции окрашены), и свечение просто пропало бы под ним.
   isolation заводит собственный порядок слоёв внутри самой метки:
   свечение уходит за её текст и не глубже.

   ПОЧЕМУ ГРАДИЕНТ, А НЕ РАЗМЫТИЕ. filter:blur пересчитывается на
   каждом кадре по всей площади пятна. Радиальный градиент рисуется
   один раз, а дальше меняется только прозрачность - это перекладывание
   готового слоя. */
.home-block>.wrap>.lbl,.cinema-copy>.lbl,.reviews-head .lbl{
  position:relative;isolation:isolate}
.home-block>.wrap>.lbl::before,.cinema-copy>.lbl::before,.reviews-head .lbl::before{
  content:'';position:absolute;z-index:-1;
  left:-90px;top:50%;width:340px;height:220px;translate:0 -50%;
  pointer-events:none;
  background:radial-gradient(ellipse at 38% 50%,
    color-mix(in srgb,var(--accent) 26%,transparent) 0%,
    color-mix(in srgb,var(--accent) 9%,transparent) 42%,
    transparent 72%);
  opacity:.34;
  animation:lbl-glow var(--breath) var(--ease-breath) infinite}
/* В кремовой теме то же пятно читается не как свет, а как грязь на
   бумаге - свет на светлом фоне не виден в принципе, видна только
   разница яркости. Проверено скриншотом: на тёмном фоне пятно легло
   светом, на кремовом - загрязнением листа.
   Поэтому здесь оно втрое слабее и заметно меньше: не свечение,
   а чуть более тёплый воздух вокруг метки. Убрать вовсе тоже было бы
   честно, но кремовая тема стоит по умолчанию, и вся страница осталась
   бы без этого дыхания. */
[data-temp="cream"] .home-block>.wrap>.lbl::before,
[data-temp="cream"] .cinema-copy>.lbl::before,
[data-temp="cream"] .reviews-head .lbl::before{
  left:-56px;width:250px;height:150px;
  background:radial-gradient(ellipse at 38% 50%,
    color-mix(in srgb,var(--gold) 22%,transparent) 0%,
    color-mix(in srgb,var(--gold) 7%,transparent) 40%,
    transparent 100%);
  animation-name:lbl-glow-soft}
@keyframes lbl-glow{0%,100%{opacity:.2}50%{opacity:.62}}
@keyframes lbl-glow-soft{0%,100%{opacity:.09}50%{opacity:.26}}
/* Как и кадры, свечение живёт только в экране.

   Селекторы перечислены полностью, а не сокращены до .lbl:not(.is-live).
   Короткая запись весит меньше, чем .home-block>.wrap>.lbl (три класса
   против двух), и у трёх меток из семи пауза просто не применялась -
   анимация шла за экраном. Замер это и показал: paused у четырёх
   из семи. Правило, которое отменяет другое, обязано весить не меньше
   его. */
.home-block>.wrap>.lbl:not(.is-live)::before,
.cinema-copy>.lbl:not(.is-live)::before,
.reviews-head .lbl:not(.is-live)::before{animation-play-state:paused}


