/* scrollcalm.css — плавный скролл ленты, часть вторая: убираем то, что пересчитывается на
   КАЖДОМ кадре инерционного свайпа.

   Прошлый заход (layout.css: свой слой скроллеру, corner-shape:round у мелочи, анимация только у
   живых сообщений) снял цену со СТИЛЯ и РАЗМЕТКИ. Осталась цена РАСТРА — и симптом ровно её:
   при быстром свайпе лента пустая, отпустил — прорисовалась. Это checkerboarding: Chrome двигает
   слой пальцем сразу, а тайлы под новым положением ещё не растеризованы, и вместо них рисуется
   фон страницы. Значит, растеризатору надо успевать — то есть каждый кадр должен стоить дешевле.

   Два источника пофреймовой цены в ленте, оба — backdrop-filter НАД ДВИЖУЩИМСЯ фоном. Правило
   проекта уже говорит «backdrop-filter не ставим там, где под элементом всегда своя же картинка»;
   здесь тот же принцип с другой стороны: под этими элементами при скролле КАЖДЫЙ КАДР другая
   картинка (обои и лента едут), поэтому blur не кешируется — он честно пересчитывается заново
   шестьдесят раз в секунду на каждый такой элемент.

   1) Пилюли реакций под кадрами (.rx-host) — их в переписке с медиа десятки.
   2) Чипы дней — по одному на каждый день истории, в длинной ленте всегда парочка на экране.
   Плюс две кнопки над лентой — «вниз» и «к новым»: они видимы РОВНО во время листания истории,
   то есть их blur платится именно тогда, когда каждый кадр на счету.

   Замена та же, что уже принята у плашек на кадрах (#150): плотнее подложка вместо размытия.
   --panel2 (белый .9 / тёмный .92) читается на любых обоях, а стоит ноль. */

.rx-host .reaction.rx-in,
.rx-host .reaction.rx-out{
  -webkit-backdrop-filter:none;backdrop-filter:none;
  background:var(--panel2);
}
#messages .day-chip button{
  -webkit-backdrop-filter:none;backdrop-filter:none;
  background:var(--panel2);
}
.scroll-down,
.jump-down{
  -webkit-backdrop-filter:none;backdrop-filter:none;
  background:var(--panel2);
}

/* ---- Слой-заглушка под фотографией ---- */
/* .media-blur — это filter:blur(14px) + transform:scale(1.15), то есть композитный слой. Пока
   фото не приехало, он честно отрабатывает заглушкой. Но после показа фото база лишь гасит его
   opacity — ЭЛЕМЕНТ ОСТАЁТСЯ, и остаётся слоем: каждый кадр в ленте таскает за собой невидимый
   блюр. Двадцать фотографий на экране и рядом — двадцать лишних слоёв в GPU-памяти, а вытесненная
   память тайлов и есть checkerboarding.
   Снимаем слой через visibility:hidden — непрорисовываемый элемент слоем не является. Задержка
   0.4с даёт кроссфейду заглушка→фото (.25с в базе) доиграть до конца: без неё под проявляющимся
   фото на миг открывался бы тёмный фон кадра. :has(...[src]) — «фото уже показано»: у ждущего
   кадра src пуст, и заглушка работает как раньше. */
.media-frame:has(.media-img[src]) .media-blur,
.media-frame:has(.media-vid[src]) .media-blur{
  visibility:hidden;
  transition:opacity .25s, visibility 0s .4s;
}

/* ---- Скроллер ---- */
/* Инерция ленты не должна дотягиваться до родителей: дошли до края — стоп, а не «поехала
   страница» и не жест обновления браузера поверх переписки. */
#messages{overscroll-behavior:contain}

/* ================= Заход второй: на телефоне облачка переписки — плотные ================= */
/* Первый заход снял blur с мелочи ВНУТРИ ленты — и не помог, а экономный режим (глушит
   backdrop-filter целиком) дал эталонную плавность. Эксперимент назвал виновника: на телефоне
   шапка и композер — плавающие стеклянные облачка ПОВЕРХ ленты (задумка владельца, мобильные
   блоки layout.css/components.css): #chathead и #composer сняты с потока, сообщения уезжают ПОД
   них, а .headseg, #closeness-badge, .composer-pill и кнопки несут blur(20px). Фон под таким
   стеклом при скролле МЕНЯЕТСЯ КАЖДЫЙ КАДР — blur пересчитывается 60–120 раз в секунду по всей
   ширине экрана, дважды (верх и низ), и съедает ровно тот бюджет, на который растеризатор не
   успевает готовить тайлы. Лента пустеет под пальцем.

   Здесь была попытка хитрее — «стекло отдыхает, пока лента едет» (класс body.feedcalm по
   scroll-событиям). Не сработала, и поучительно почему: события скролла доставляет ГЛАВНЫЙ
   ПОТОК, а он занят ровно тогда, когда деградация нужна, — события приходили рывками, пауза
   между ними превышала таймер снятия, класс слетал ПОСРЕДИ свайпа, и стекло с его ценой
   возвращалось. Механизм деградации не имеет права зависеть от живости того, от чьей смерти
   он защищает. Поэтому — статика.

   На телефоне облачка переписки плотные всегда: --panel2 (белый .9 / тёмный .92) — та же лёгкая
   полупрозрачность, читается на любых обоях, стоит ноль. Ровно этот вид владелец назвал эталоном,
   включив экономный режим. Всё остальное стекло живо: десктоп (там шапка в потоке, фон под ней
   статичен), меню, модалки, панели — их blur не пофреймовый.
   !important на самом фильтре — тем же приёмом, что у экономного режима: правил со стеклом
   несколько и в разных файлах, глушилка обязана перебивать их все. Контейнеры #chathead/#composer
   не трогаем: они прозрачные, стекло несут пилюли, а красить контейнеры — рисовать полосы во всю
   ширину, которых в дизайне нет. */
@media(max-width:760px){
  .headseg,
  #closeness-badge,
  .composer-pill,
  #send-btn,
  #rec-btn,
  #rec-bar,
  #pin-bar,
  #composer-banner,
  #cmd-hints{
    -webkit-backdrop-filter:none!important;backdrop-filter:none!important;
    background:var(--panel2)!important;
  }
}

/* ================= Заход третий, окончательный: на телефоне стекла нет ================= */
/* Решающий эксперимент поставил владелец, сам того не планируя: чекербордил СПИСОК ФАЙЛОВ в
   настройках — голый текст, без картинок, пузырей и суперэллипсов. Значит, содержимое невиновно
   вовсе, а платит то, что висит на экране целиком. И оно нашлось: лист настроек лежит на
   полноэкранном .modal-overlay с blur(5px), а ПОД ним — полноэкранный на телефоне #sidebar со
   своим blur(12px). Chromium применяет backdrop-filter при отрисовке КАЖДОГО кадра для каждой
   видимой области — даже когда фон под ней статичен и размывать заново нечего. Пока палец
   листает что угодно, телефон каждый кадр прогоняет два полноэкранных блюра — вот куда уходил
   бюджет растеризатора, и вот почему экономный режим (глушит backdrop-filter целиком) давал
   эталон, а точечные правки — нет: это была охота на гидру, у которой голов больше, чем патчей.

   Поэтому на телефоне (≤760px) стекла нет ВООБЩЕ — тем же залпом, что экономный режим, но
   только на этой ширине: десктопу его GPU-бюджета на стекло хватает, и там всё как было.
   Плотность взамен прозрачности: --panel поднимается до --panel2 (лёгкая полупрозрачность
   остаётся — .9 светлая / .92 тёмная, — но без блюра под ней ничего не «плывёт»). body.dark в
   селекторе обязателен: tokens.css задаёт тёмные панели правилом body.dark той же силы, и без
   него тёмная тема осталась бы на водянистой .6. Точечные правила выше не сняты — под общим
   залпом они безвредны, а если залп когда-нибудь ослабят, они снова станут страховкой. */
@media(max-width:760px){
  *{-webkit-backdrop-filter:none!important;backdrop-filter:none!important}
  body,body.dark{--panel:var(--panel2)}
}

/* Маркер версии этого файла для «Файлы на этом устройстве» (js/netdiag.js). После случая, когда
   плашка закрепа осталась стеклянной вопреки правилу выше, стало ясно: без маркера не отличить
   «правило перебито» от «файл не доехал» (кеш оболочки может отдать страницу на одну загрузку
   позади, и все ?v= в ней — прошлые). Число поднимать при каждой правке файла. */
:root{--cmsg-scrollcalm:4}
