@charset "utf-8";
/* ═══════════════════════════════════════════════════════════════════════════
   ВЕРАНДА · витрина · плавность.

   Шаг 26. Александр 29.08: «очень много лагов таких визуальных, плюс анимации
   нет, короче всё лагает и это очень неприятно».

   Две разные жалобы в одной фразе, и лечатся они врозь:
     • «анимации нет» — на витрине не двигалось ничего, кроме двух переходов
       цвета у кнопок. Появление разделов и отклик на нажатие — здесь;
     • «всё лагает» — это не анимация, а работа: 2,5 МБ на первый показ и
       слой зерна, который перекрашивался на каждый кадр прокрутки. Первое
       чинится в разметке (марки точек, ленивые кадры), второе — ниже.

   🔴 Отдельным файлом нарочно, как язык.css: цена плавности видна и
   снимается одной строкой из index.html, вместе с js/плавность.js.

   Правила, которых этот файл держится:
     1. ничего дольше 250 мс;
     2. двигаются только transform и opacity — ни top, ни left, ни width,
        ни height: всё остальное заставляет браузер пересчитывать вёрстку
        по 60 раз в секунду, и это и есть «лагает»;
     3. макет не прыгает: элемент занимает своё место до появления и после,
        меняется только его прозрачность и сдвиг на 12 px;
     4. prefers-reduced-motion выключает всё разом, а не «почти всё».
   ═══════════════════════════════════════════════════════════════════════════ */

:root{
  --v-t-in:  .22s;                        /* появление раздела */
  --v-t-tap: .12s;                        /* отклик на нажатие */
  --v-ease:  cubic-bezier(.22,.61,.36,1); /* быстро начал, мягко встал */
}

/* 🔴 Прячет содержимое не таблица стилей, а скрипт: класс `есть-появление`
   ставит js/плавность.js и только после того, как убедился, что умеет его
   снять. Без скрипта, со сломанным скриптом и в старом браузере страница
   остаётся просто видимой — прозрачность в ноль без того, кто её вернёт,
   это не анимация, а пустой экран. */
.есть-появление .появление{
  opacity:0;
  transform:translate3d(0,12px,0);
  transition:opacity var(--v-t-in) var(--v-ease),
             transform var(--v-t-in) var(--v-ease);
}
.есть-появление .появление.виден{ opacity:1; transform:none; }

/* Отклик на нажатие. Не «эффект», а ответ: гость на телефоне не видит
   наведения и без этого не понимает, попал он по карточке или нет. */
.pt, .otz, .tile, .dish .shot, .mast-nav a, .foot-links a, .row-link{
  transition:background var(--v-t) var(--v-ease),
             border-color var(--v-t) var(--v-ease),
             color var(--v-t) var(--v-ease),
             transform var(--v-t-tap) var(--v-ease);
}
.pt:hover{ background:var(--v-paper-3); }
.pt:active{ transform:scale(.99); }
.btn:active{ transform:scale(.98); }
.row-link:active{ transform:scale(.995); }

/* Кадр под пальцем чуть приближается — тот же приём, что был задуман
   токеном --v-t-2, но в 200 мс вместо 500: полсекунды на телефоне уже
   не отклик, а задержка. */
.dish .shot img, .pt-shot img{
  transition:transform .2s var(--v-ease);
}
.dish:hover .shot img, .pt:hover .pt-shot img{ transform:scale(1.03); }

/* ── зерно бумаги ───────────────────────────────────────────────────────
   🔴 Главная причина «визуальных лагов» на телефоне, и она не в анимации.
   Зерно лежит слоем `position:fixed` во весь экран с `mix-blend-mode:
   multiply`. Такой слой браузер обязан на каждом кадре прокрутки смешать
   с тем, что под ним, — то есть перечитать и перекрасить весь экран
   заново, шестьдесят раз в секунду, на встроенной графике телефона.

   Зерно остаётся: это бумага, а бумага и есть бренд. Убран только способ
   смешивания — вместо multiply обычная прозрачность на своём слое
   (`will-change:transform` уводит его в композитор, и прокрутка его больше
   не касается). На кремовом фоне тёмный шум под multiply и под альфой
   отличаются едва — разницу видно на сравнении снимков, и она меньше, чем
   разница между дёргающейся и ровной прокруткой.                          */
body::before{
  mix-blend-mode:normal;
  opacity:calc(var(--v-grain-op) * .7);
  will-change:transform;
}

/* ── уважение к настройке гостя ─────────────────────────────────────────
   🔴 Не «уменьшить», а выключить. Гость, который поставил себе «меньше
   движения», сделал это не ради красоты: у части людей от движущегося
   интерфейса кружится голова. Содержимое при этом обязано остаться
   видимым — поэтому здесь и opacity, и transform возвращаются в норму. */
@media (prefers-reduced-motion: reduce){
  .есть-появление .появление,
  .есть-появление .появление.виден{
    opacity:1; transform:none; transition:none;
  }
  .pt, .otz, .tile, .dish .shot, .mast-nav a, .foot-links a, .row-link,
  .btn, .dish .shot img, .pt-shot img{ transition:none; }
  .pt:active, .btn:active, .row-link:active,
  .dish:hover .shot img, .pt:hover .pt-shot img{ transform:none; }
}
