/* Движение сайта клуба.

   Все кейфреймы макетов собраны здесь под их собственными именами и с теми же
   числами. Один файл, потому что одно и то же движение встречается на разных
   экранах: `spinZ` крутит и ♠ в карточке турнира, и кольцо процента на плитке
   статистики, а `sweep` ходит и по ближайшему турниру, и по карте участника.

   Базовые значения взяты с «Главной» — она якорный экран. Там, где дизайнер
   на другом экране взял другое число (проявление блоков в профиле короче:
   20px/.5s против 24px/.55s), это записано в том экране, а не усреднено
   здесь. Разница видна глазом, и выравнивать её значило бы править макет. */

/* ── проявление по мере прокрутки ─────────────────────────────────────────
   Класс вешается разметкой, `on` добавляет IntersectionObserver (порог .12,
   корень — сам скроллер экрана). Без наблюдателя блок останется невидимым,
   поэтому вешать `.rv` можно только на то, что экран потом наблюдает. */
.rv { opacity: 0; transform: translateY(24px); transition: opacity .55s var(--ease), transform .55s var(--ease); }
.rv.on { opacity: 1; transform: none; }

/* Строка доски въезжает слева, а не снизу: таблицу читают построчно, и
   движение вдоль строки помогает читать, а поперёк — мешает. */
.sl { opacity: 0; transform: translateX(-26px); transition: opacity .38s ease, transform .45s var(--ease); }
.sl.on { opacity: 1; transform: none; }

/* Полоса счёта вырастает от левого края — оттуда, откуда её читают. */
.gr { transform: scaleX(0); transform-origin: left; transition: transform .85s var(--ease); }
.gr.on { transform: scaleX(1); }

/* ── отклик на палец ──────────────────────────────────────────────────────
   Ужать и подсветить. Это единственная обратная связь на нажатие во всём
   макете: подложек-«волн» и подсветок фокуса у дизайнера нет. */
.tap { transition: transform .16s var(--ease), filter .16s ease, border-color .3s ease; }
.tap:active { transform: scale(.966); filter: brightness(1.15); }

/* Приподнять под курсором — только там, где курсор есть. На телефоне hover
   залипает после тапа, поэтому правило закрыто медиа-запросом. */
@media (hover: hover) {
  .lift { transition: transform .3s var(--ease), box-shadow .3s ease; }
  .lift:hover { transform: translateY(-4px); box-shadow: 0 20px 40px rgba(0, 0, 0, .55); }
}

/* ── горизонтальные ленты ─────────────────────────────────────────────────
   Достижения и фильтры едут вбок с прилипанием. Полосу прокрутки убираем:
   у дизайнера её нет ни на одном экране, а на десктопе она съедала бы 15px
   у карточки и ломала её пропорции. */
.snap { scroll-snap-type: x mandatory; }
.snap > * { scroll-snap-align: start; }
.noscroll { scrollbar-width: none; -ms-overflow-style: none; }
.noscroll::-webkit-scrollbar { display: none; }

/* ── кейфреймы ────────────────────────────────────────────────────────────
   Порядок — как они появляются в макетах, от «Главной» к профилю. */

/* Точка «идёт сейчас» рядом с заголовком. */
@keyframes pulse { 0%, 100% { opacity: .45; transform: scale(1) } 50% { opacity: 1; transform: scale(1.45) } }

/* Блик, проходящий по карточке. Длинная пауза в конце (62% → 100%) — чтобы
   он не мелькал: это акцент раз в шесть секунд, а не мигалка. */
@keyframes sweep { 0% { transform: translateX(-130%) skewX(-18deg) } 62%, 100% { transform: translateX(260%) skewX(-18deg) } }
@keyframes glare { 0% { transform: translateX(-140%) skewX(-18deg) } 55%, 100% { transform: translateX(320%) skewX(-18deg) } }

/* Фишка по кругу радиусом 58px: внешний поворот ведёт, внутренний
   отматывает назад — так она едет по орбите, не вращаясь сама. */
@keyframes orbit { 0% { transform: rotate(0) translateX(58px) rotate(0) } 100% { transform: rotate(360deg) translateX(58px) rotate(-360deg) } }

@keyframes glide { 0% { transform: translateX(0) } 50% { transform: translateX(-18px) } 100% { transform: translateX(0) } }
@keyframes spinZ { 0% { transform: rotate(0) } 100% { transform: rotate(360deg) } }
@keyframes bob { 0%, 100% { transform: translateY(0) } 50% { transform: translateY(-7px) } }
@keyframes chipBob { 0%, 100% { transform: translateY(0) } 50% { transform: translateY(-3px) } }
@keyframes shine { 0% { opacity: .35 } 50% { opacity: .8 } 100% { opacity: .35 } }

/* Пунктирная линия отрыва билета: не сама линия едет, а её фон. */
@keyframes dash { to { background-position: 0 60px } }

/* Появление столбика и деления шкалы — от основания вверх. Обоим нужен
   `transform-origin: bottom` на самом элементе. */
@keyframes barIn { 0% { transform: scaleX(0) } 100% { transform: scaleX(1) } }
@keyframes growTick { 0% { transform: scaleY(.2); opacity: 0 } 100% { transform: scaleY(1); opacity: 1 } }

/* Строки списка въезжают по очереди — задержка ставится в разметке. */
@keyframes rowIn { 0% { opacity: 0; transform: translateY(14px) } 100% { opacity: 1; transform: none } }

/* Карта участника покачивается, как пластик в руке. */
@keyframes floaty { 0%, 100% { transform: translateY(0) rotate(-1.2deg) } 50% { transform: translateY(-6px) rotate(1.2deg) } }

/* Смена экрана и появление страницы. */
@keyframes fadeUp { 0% { opacity: 0; transform: translateY(14px) } 100% { opacity: 1; transform: none } }
@keyframes fadeIn { 0% { opacity: 0; transform: translateY(8px) } 100% { opacity: 1; transform: none } }

/* Подиум: тумба поднимается, фишка падает на место, аватар прилетает
   с поворотом — из макета «Клуб - Рейтинг». */
@keyframes riseUp { 0% { transform: scaleY(.05); opacity: 0 } 70% { transform: scaleY(1.04) } 100% { transform: scaleY(1); opacity: 1 } }
@keyframes chipIn { 0% { opacity: 0; transform: translateY(-16px) rotate(-90deg) scale(.7) } 70% { transform: translateY(2px) rotate(6deg) scale(1.04) } 100% { opacity: 1; transform: none } }
@keyframes chipDrop { 0% { opacity: 0; transform: translateY(-70px) scaleY(.6) } 62% { opacity: 1; transform: translateY(3px) scaleY(1.06) } 100% { opacity: 1; transform: none } }
@keyframes spinSlow { 0% { transform: rotate(0) } 100% { transform: rotate(360deg) } }
@keyframes glowPulse { 0%, 100% { opacity: .25 } 50% { opacity: .6 } }

@keyframes popIn { 0% { opacity: 0; transform: translateY(12px) scale(.94) } 100% { opacity: 1; transform: none } }

/* ── проявка билета ───────────────────────────────────────────────────────
   Карточка турнира появляется не как все: она ПРОЯВЛЯЕТСЯ — открывается слева
   направо из размытия, будто снимок в ванночке, и только потом на ней по
   одной проступают строки. Так в макете «Клуб - Турниры», и это не украшение:
   в столбце из семи одинаковых билетов взгляду нужно за что-то зацепиться, а
   волна слева направо сама ведёт его сверху вниз. */
@keyframes dev {
  0% { opacity: 0; clip-path: inset(0 100% 0 0); filter: blur(7px) }
  100% { opacity: 1; clip-path: inset(0 0 0 0); filter: blur(0) }
}
@keyframes ink { 0% { opacity: 0; transform: translateX(-10px) } 100% { opacity: 1; transform: none } }
