/* Флипбук, перелистывающийся по скроллу.
   По мотивам пера Jhey (MIT): https://codepen.io/jh3y/pen/ExPVzBY
   Рисунки из оригинала убраны — страницы пустые, в линейку.
   Все селекторы вложены в .flipbook, чтобы общие имена (.book, .page)
   не пересекались с остальной вёрсткой сайта. */

.flipbook {
  /* Книга — первый экран страницы, поэтому она крупная. 70vh: по центру экрана
     это 15–85% высоты, то есть низ не заезжает под нижнюю навигацию (она с 86%).
     Разворот шире книги в 1.88 раза, поэтому ограничиваем высоту ещё и по ширине
     экрана — иначе на узких экранах он вылезет за края.
     Объявлено на всей секции, а не на .book: от высоты книги считается ещё
     и трава (.flipbook__grass) */
  --book-h: min(70vh, 66vw);
  /* множитель размера книги. На телефоне им скрипт уменьшает её к раскрытию
     (см. медиазапрос ниже); объявлен здесь, чтобы у свойства всегда было
     валидное значение — GSAP читает его при обратной прокрутке */
  --book-k: 1;
  /* столько блоков .book__page в разметке: обложка + 3 листа + задняя обложка */
  --page-count: 5;
  /* сколько vh прокрутки уходит на один переворот: больше значение — медленнее
     листается. Скрипт читает эту же переменную, менять только здесь */
  --page-scroll: 80;
  /* во сколько шагов листается первая страница. Сразу после раскрытия книги
     разворот иначе пролетает слишком быстро — первой странице даём больше
     прокрутки, чем остальным. Скрипт читает эту же переменную */
  --first-turn: 2;
  --underline: #40404066;
  --spine: #000;
  /* в оригинале обложка была темнее фона (#1a1a1a на сером); на почти чёрном
     фоне about.html закрытая книга так пропадала, поэтому обложка светлее фона */
  --cover: #333;
  --insert: #d9d9d9;
  --page: #e6e6e6;

  /* 100vh уходит на сам экран, на котором книга залипает, а остальное — путь
     прокрутки: шаг на разворот с раскрытием обложки, по шагу на каждый
     внутренний лист (их --page-count минус обе обложки), добавка на первую
     страницу и шаг в хвост, иначе последний разворот покажется ровно в момент,
     когда книга отлипает.
     Если не заложить эти 100vh, книга «отлипнет» и уедет вверх, не долиставшись */
  height: calc(100vh + (var(--page-count) + var(--first-turn) - 1) * var(--page-scroll) * 1vh);
  position: relative;
}

/* книга держится по центру экрана, пока секция прокручивается */
.flipbook__stage {
  position: sticky;
  top: 0;
  height: 100vh;
}

/* --- трава -----------------------------------------------------------------

   Из макета (Figma, кадр 1709x1833): поверх скриншота первого экрана лежат
   картинка травы и тёмный градиент. Скриншот там 1615x1013 — это и есть
   «экран», от него и считаны все доли ниже.

   Трава: 1765x650 при x=-28 (кадр начинается на 47) — то есть по горизонтали
   по центру экрана и шире его на 9.3%; низ картинки совпадает с низом экрана,
   высота — 64.2% от него. Сама картинка 1024x572, в этот бокс она в макете
   растянута, а не вписана, — поэтому object-fit: fill.

   Подложка нужна только чтобы обрезать: трава шире экрана, и без неё
   появлялась бы горизонтальная прокрутка. */
.flipbook__ground {
  inset: 0;
  overflow: hidden;
  /* Закрытая книга стоит В траве: передние склоны перекрывают её низ.
     Раскрытая выходит вперёд — ей скрипт поднимает z-index до 6
     (см. assets/js/flipbook.js) */
  z-index: 3;
  /* наклейки на обложке кликабельны — трава не должна перехватывать курсор */
  pointer-events: none;
  position: absolute;
}

.flipbook__grass {
  width: 109.3%;
  height: 64.2%;
  /* в общем CSS у всех картинок max-width: 100% — он срезал бы траву
     до ширины экрана */
  max-width: none;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  /* в макете картинка растянута по боксу, пропорции исходника не сохранены */
  object-fit: fill;
  position: absolute;
}

/* На вертикальном экране бокс травы сам становится вертикальным, и картинка,
   растянутая по нему, смазывается в длинные полосы. Растягиваем сам бокс:
   на всю высоту экрана и почти втрое шире него — холмы уходят за края,
   в кадре остаётся ложбина со склонами, ровно то место, где стоит книга.

   Снять растяжение совсем не выйдет: при натуральных пропорциях картинки
   (3418x1411) бокс был бы шире экрана в пять раз, и в кадр попадал бы
   только размытый передний план со дна ложбины — зелень пропала бы совсем.
   280% — предел, за которым склоны уходят из кадра; растяжение при этом
   падает с 2.6 до 1.9.

   Завязано на пропорции экрана, а не на ширину: на планшете в портрете
   картинка плющится ровно так же, как на телефоне. */
@media (max-aspect-ratio: 1 / 1) {
  .flipbook__grass {
    width: 280%;
    height: 100%;
  }

  /* Закрытая книга на телефоне крупнее: в ложбине она иначе теряется.
     Ограничение в 66vw никуда не делось, но относится теперь к раскрытому
     развороту — он шире книги в 1.88 раза и в экран целиком не помещается.
     К раскрытию скрипт уводит множитель в 0.75 (88 * 0.75 = 66), и разворот
     выходит прежнего размера; подмена приходится на кадр, где книга
     повёрнута к зрителю ребром. */
  .flipbook {
    --book-h: calc(min(70vh, 88vw) * var(--book-k, 1));
  }
}

/* Тёмный градиент поверх всей сцены — им в макете низ уводится в фон
   страницы. В кадре это прямоугольник 1709x477 от y=584, то есть от 57.6%
   высоты экрана и ниже; цвет — ровно фон body (#101010).

   Лежит отдельным слоем, а не внутри травы: закрытая книга стоит в сцене
   и затемняется вместе с ней, а раскрытая выходит вперёд и градиент уже
   не трогает — иначе на развороте остаётся тень поверх страниц. */
.flipbook__fade {
  background-image: linear-gradient(to top, #101010 8.9%, #101010b5 50.5%, #10101000);
  height: 47.1%;
  top: 57.6%;
  left: 0;
  right: 0;
  z-index: 5;
  pointer-events: none;
  position: absolute;
}

.flipbook .book {
  /* ниже травы (у неё 3) и затемнения (5). Скрипт поднимает книгу
     до 6 в середине раскрытия */
  z-index: 1;

  /* 0 — книга закрыта и стоит по центру экрана, 1 — раскрыта.
     Страницы отворачиваются влево от левого края книги, поэтому у раскрытой
     книги середина разворота приходится ровно на этот край: его и ставим
     в центр экрана. Закрытую же книгу надо сдвинуть на половину её ширины,
     иначе она висела бы в правой половине. Значение крутит скрипт. */
  --open: 0;

  /* шаг линовки. От него же считается интерлиньяж текста на страницах,
     иначе строки не лягут на линии */
  --rule: calc(var(--book-h) / 26);

  height: var(--book-h);
  width: calc(var(--book-h) * .75);
  min-width: 150px;
  min-height: 200px;
  position: absolute;
  /* не ровно по центру экрана, а чуть выше: наклонённая сцена визуально
     тяжелее книзу, да и подписи страниц читаются лучше повыше */
  top: 45%;
  left: 50%;
  transform: translate(calc((var(--open) - 1) * 50%), -50%);
  /* перспектива пропорциональна книге, иначе на большом размере излом страниц уехал бы */
  perspective: calc(var(--book-h) * 2.8);
}

/* Книга разворачивается к зрителю целиком: закрытая стоит лицом, по ходу
   прокрутки уходит на ребро и возвращается обратно уже раскрытой.
   Поворот живёт здесь, а не на .book, чтобы не спорить со сдвигом по --open. */
.flipbook .book__turn {
  height: 100%;
  width: 100%;
  position: absolute;
  top: 0;
  left: 0;
  transform-style: preserve-3d;
}

.flipbook .page {
  height: 100%;
  width: 100%;
  position: relative;
  transform-style: preserve-3d;
}

.flipbook .page__number {
  color: #808080;
  font-size: 1vmin;
  position: absolute;
  bottom: 1rem;
}

.flipbook .page__half--front .page__number {
  right: 1rem;
}

.flipbook .page__half--back .page__number {
  left: 1rem;
}

.flipbook .page__half {
  height: 100%;
  width: 100%;
  justify-content: center;
  align-items: center;
  display: flex;
  position: absolute;
  top: 0;
  left: 0;
  transform: rotateY(calc(var(--rotation) * 1deg)) translate3d(0, 0, calc(.5 * var(--coefficient) * 1px));
  clip-path: inset(0 .5% 0 .5%);
}

.flipbook .page__half--front {
  --rotation: 0;
  --coefficient: 0;
  backface-visibility: hidden;
  border-radius: 0 5% 5% 0;
}

.flipbook .page__half--back {
  --rotation: 180;
  --coefficient: 2;
  border-radius: 5% 0 0 5%;
}

.flipbook .book__insert {
  height: 94%;
  width: 94%;
  background: var(--insert);
  border-radius: 5% 0 0 5%;
  position: absolute;
  top: 50%;
  right: -1rem;
  transform: translate(0, -50%);
}

.flipbook .book__spine {
  height: 100%;
  width: 12px;
  background: var(--spine);
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: 0 50%;
  transform: translate3d(0, 0, -13px);
}

.flipbook .book__page {
  height: 94%;
  width: 94%;
  border-radius: 0 5% 5% 0;
  position: absolute;
  top: 50%;
  left: 2%;
  transform: translate(0, -50%);
  transform-origin: 0% 50%;
  z-index: calc((var(--page-count) + 2 - var(--page-index)) * 2);
}

.flipbook .book__cover {
  height: 100%;
  width: 100%;
  background: var(--cover);
  border-radius: 0 5% 5% 0;
  position: absolute;
  top: 50%;
  left: 0;
  transform-origin: 0 50%;
}

/* лицо передней обложки — картинка; пропорции файла (0.743) почти совпадают
   с пропорцией страницы (0.75), так что cover ничего заметного не срезает */
.flipbook .book__cover--front .page__half--front {
  background: url("../images/book-cover.jpg") 50% / cover no-repeat;
}

/* Наклейки поверх обложки. Позиции и размеры — в процентах от страницы,
   поэтому держатся при любом размере книги. */
.flipbook .cover-sticker {
  position: absolute;
  transform: translate(-50%, -50%);
}

.flipbook .cover-sticker--avatar {
  /* скругление не только ради вида: по нему же считается область наведения,
     иначе качаться начинало бы и от прозрачных углов квадратной картинки */
  border-radius: 50%;
  width: 14.5%;
  top: 22%;
  left: 40%;
}

.flipbook .cover-sticker--eyes {
  width: 21%;
  top: 64.5%;
  left: 82%;
}

/* Каждая наклейка качается сама по себе — по наведению на неё, а не на всю
   обложку. Курсор ушёл — замерла ровно, без наклона. */
@keyframes cover-sticker-wobble {
  0% {
    transform: translate(-50%, -50%) rotate(-7deg);
  }
  100% {
    transform: translate(-50%, -50%) rotate(7deg);
  }
}

.flipbook .cover-sticker:hover {
  animation: 0.3s ease-in-out infinite alternate cover-sticker-wobble;
}

@media (prefers-reduced-motion: reduce) {
  .flipbook .cover-sticker:hover {
    animation: none;
  }
}

.flipbook .book__cover--front .page__half--back {
  border-right: 1rem solid var(--spine);
}

.flipbook .book__cover--back .page__half--front {
  border-left: 1rem solid var(--spine);
}

.flipbook .book__cover--back .book__insert {
  left: 0;
  border-radius: 0 5% 5% 0;
}

/* линейка на внутренних страницах */
.flipbook .book__page:not(.book__cover) .page__half {
  background:
    repeating-linear-gradient(0deg, transparent 0 var(--rule), var(--underline) var(--rule), transparent calc(var(--rule) + 1px)) 0 var(--rule) / 100% 100% no-repeat,
    var(--page);
}

/* --- готовые развороты ------------------------------------------------------

   Страница целиком — картинка из макета: линовка, текст и номер нарисованы
   прямо в ней. Поэтому у таких половин гасим свою линовку, а изображение
   кладём во всю площадь. Пропорция файла 0.743 против 0.75 у страницы —
   разница меньше процента, cover срезает её незаметно. */

/* специфичность в два класса не случайна: линовку задаёт
   .book__page:not(.book__cover) .page__half, и правило слабее её не перебьёт */
.flipbook .book__page:not(.book__cover) .page__half--sheet {
  background: var(--page);
}

.flipbook .page__sheet {
  position: absolute;
  inset: 0;
  /* радиус берём у самой половины: у передней и задней страниц он зеркальный */
  border-radius: inherit;
  overflow: hidden;
}

.flipbook .page__sheet img {
  object-fit: cover;
  width: 100%;
  height: 100%;
  display: block;
}

/* --- содержимое страниц ---------------------------------------------------- */

/* .page__half центрирует содержимое флексом, а текст должен идти от верха —
   поэтому кладём его абсолютом. Интерлиньяж равен шагу линовки, а верхний
   отступ кратен ему: так строки попадают ровно на линии */
.flipbook .page__text {
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  margin: 0;
  padding: calc(var(--rule) * 2) 9% 0;
  box-sizing: border-box;
  color: #2f2f33;
  font-family: inherit;
  font-size: calc(var(--rule) * .62);
  line-height: var(--rule);
  text-align: left;
}

/* итоговая фраза на последнем развороте — крупнее, но в том же ритме */
.flipbook .page__text--lead {
  font-size: calc(var(--rule) * .78);
  font-weight: 500;
}

.flipbook .page__photos {
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  padding: 8%;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 5%;
  display: flex;
}

.flipbook .page__photos img {
  max-width: 82%;
  max-height: 74%;
  object-fit: contain;
  border-radius: 3px;
  box-shadow: 0 2px 10px #0000002e;
  /* лёгкий наклон — как фотографии, вклеенные в блокнот */
  transform: rotate(-2deg);
}

.flipbook .page__photos--pair img {
  max-height: 42%;
}

.flipbook .page__photos--pair img:last-child {
  transform: rotate(2.5deg);
}
