/* ==========================================================================
   motion.css — «живой» слой интерфейса: нажатия, наведение, появление,
   микровзаимодействия. Подключается ПОСЛЕ main.css и app.css.
   Правила:
   — анимируются только transform и opacity (тени — через opacity псевдоэлемента);
   — классы и разметка не меняются, только добавляются: .is-in, .is-pop, .is-bump,
     .motion-enter, .motion-collapse, .ripple (их ставит motion.js);
   — prefers-reduced-motion: reduce отключает всё движение, остаётся смена цвета.
   ========================================================================== */

:root {
  --spring: cubic-bezier(.34, 1.56, .64, 1);   /* отскок при отпускании */
  --press-ease: cubic-bezier(.2, 0, .3, 1);    /* быстрое вдавливание */
  --dur-press: 90ms;
  --dur-release: 220ms;
  --dur-enter: 420ms;
}

/* 1. Переходы между страницами (Chrome/Edge 126+, Safari 18.2+) ------------- */
@view-transition { navigation: auto; }
.site-header { view-transition-name: site-header; }
.tabbar { view-transition-name: tabbar; }
.panel-sidebar { view-transition-name: panel-sidebar; }
::view-transition-old(root) { animation: vt-out 160ms var(--press-ease) both; }
::view-transition-new(root) { animation: vt-in 260ms cubic-bezier(.2, .7, .2, 1) both; }
@keyframes vt-out { to { opacity: 0; } }
@keyframes vt-in { from { opacity: 0; transform: translateY(8px); } }
/* смена темы — мягкий кроссфейд всей страницы (только opacity) */
html.is-theme-switching::view-transition-old(root),
html.is-theme-switching::view-transition-new(root) { animation: none; mix-blend-mode: normal; }
html.is-theme-switching::view-transition-new(root) { animation: vt-fade 320ms ease both; }
@keyframes vt-fade { from { opacity: 0; } }

/* 2. Нажатие: вдавливание и пружинный возврат ------------------------------- */
.btn, .chip, .site-nav__link, .tabbar__item, .icon-btn, .share-btn, .social-card,
.dialog-item, .pagination__link, .tabs__link, .tag, .composer__send, .panel-nav__link,
.status-tabs a, .segmented span, .mini-item, .menu__item, .toast__close, .soc-link,
.drawer__nav a, .header-user, .brand, .file-preview__remove span, .news-card {
  transition-property: background-color, border-color, color, opacity, transform;
  transition-duration: var(--dur), var(--dur), var(--dur), var(--dur), var(--dur-release);
  transition-timing-function: var(--ease), var(--ease), var(--ease), var(--ease), var(--spring);
  -webkit-tap-highlight-color: transparent;
}
.btn:active, .chip:active, .site-nav__link:active, .icon-btn:active, .share-btn:active,
.pagination__link:active, .tabs__link:active, .tag:active, .composer__send:active,
.panel-nav__link:active, .status-tabs a:active, .segmented label:active span,
.menu__item:active, .toast__close:active, .soc-link:active, .drawer__nav a:active,
.header-user:active, .brand:active, .file-preview__remove:active span {
  transform: translateY(1px) scale(.96);
  transition-duration: var(--dur), var(--dur), var(--dur), var(--dur), var(--dur-press);
  transition-timing-function: var(--ease), var(--ease), var(--ease), var(--ease), var(--press-ease);
}
/* крупные поверхности сжимаются меньше, чтобы не «прыгал» текст */
.social-card:active, .dialog-item:active, .mini-item:active, .news-card:active {
  transform: translateY(1px) scale(.985);
  transition-duration: var(--dur), var(--dur), var(--dur), var(--dur), var(--dur-press);
  transition-timing-function: var(--ease), var(--ease), var(--ease), var(--ease), var(--press-ease);
}
/* нажатие по ссылке-заголовку карточки: :active у карточки срабатывает через ::after ссылки,
   а кнопка «Поделиться» внутри — нажимается сама по себе */
.news-card:has(.news-card__actions :active) { transform: none; }

/* Нижняя навигация: «вдавливается» иконка, а не вся ячейка */
.tabbar__item > .icon, .tabbar__plus { transition: transform var(--dur-release) var(--spring); }
.tabbar__item:active > .icon, .tabbar__item:active .tabbar__plus { transform: translateY(1px) scale(.88); transition-duration: var(--dur-press); transition-timing-function: var(--press-ease); }

/* Тень кнопки, которая «уходит» при нажатии (только opacity) */
.btn--primary, .btn--accent, .btn--vk, .btn--max, .composer__send { position: relative; isolation: isolate; }
.btn--primary::before, .btn--accent::before, .btn--vk::before, .btn--max::before, .composer__send::before {
  content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none;
  box-shadow: 0 6px 14px -6px rgba(62, 19, 90, .55), 0 1px 2px rgba(62, 19, 90, .2);
  opacity: .8; transition: opacity var(--dur-release) var(--ease);
}
.btn--primary:active::before, .btn--accent:active::before, .btn--vk:active::before, .btn--max:active::before, .composer__send:active::before { opacity: 0; transition-duration: var(--dur-press); }
.btn[disabled]::before, .composer__send:disabled::before { opacity: 0; }

/* 3. Волна (ripple) от точки касания — ставит motion.js ---------------------- */
.btn--primary, .btn--accent, .composer__send, .tabbar__plus { overflow: hidden; }
.tabbar__plus { position: relative; }
.ripple {
  position: absolute; left: var(--rx, 50%); top: var(--ry, 50%);
  width: var(--rs, 120px); height: var(--rs, 120px); margin: calc(var(--rs, 120px) / -2) 0 0 calc(var(--rs, 120px) / -2);
  border-radius: 50%; background: currentColor; pointer-events: none;
  opacity: .28; transform: scale(0);
  animation: ripple 520ms cubic-bezier(.2, .7, .2, 1) forwards;
}
@keyframes ripple { to { transform: scale(1); opacity: 0; } }

/* 4. Наведение (только устройства с мышью) ---------------------------------- */
@media (hover: hover) and (pointer: fine) {
  .news-card::after {
    content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none;
    box-shadow: 0 14px 30px -14px rgba(45, 15, 70, .35), 0 3px 8px -4px rgba(45, 15, 70, .12);
    opacity: 0; transition: opacity 260ms var(--ease);
  }
  .news-card:hover { transform: translateY(-2px); }
  .news-card:hover::after { opacity: 1; }
  .news-card:active::after { opacity: .4; }
  .news-card__media img { transition: transform 600ms cubic-bezier(.2, .7, .2, 1); }
  .news-card:hover .news-card__media img { transform: scale(1.04); }
  .social-card:hover, .mini-item:hover .mini-item__thumb { transform: translateY(-1px); }
  .mini-item__thumb { transition: transform 300ms var(--spring); }
  /* кнопки слегка светлеют: белый слой поверх (opacity) */
  .btn--primary::after, .btn--accent::after, .btn--vk::after, .btn--max::after, .composer__send::after {
    content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
    background: #fff; opacity: 0; transition: opacity var(--dur) var(--ease);
  }
  .btn--primary:hover::after, .btn--accent:hover::after, .btn--vk:hover::after, .btn--max:hover::after, .composer__send:hover::after { opacity: .08; }
  .btn--primary:active::after, .btn--accent:active::after, .composer__send:active::after { opacity: 0; }
}
:root[data-theme="dark"] .news-card::after { box-shadow: 0 14px 30px -12px rgba(0, 0, 0, .75); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .news-card::after { box-shadow: 0 14px 30px -12px rgba(0, 0, 0, .75); } }
/* у загружающейся кнопки слой наведения не нужен: там спиннер */
.btn.is-loading::after { background: none; opacity: 1; inset: auto; top: 50%; left: 50%; margin: -9px 0 0 -9px; }

/* 5. Появление при прокрутке ------------------------------------------------- */
/* Скрываем только то, что motion.js пометил .reveal (ниже первого экрана), иначе контент виден сразу */
.reveal { opacity: 0; transform: translateY(10px); }
.reveal.is-in {
  opacity: 1; transform: none;
  transition: opacity 480ms cubic-bezier(.2, .7, .2, 1), transform 480ms cubic-bezier(.2, .7, .2, 1);
  transition-delay: var(--reveal-delay, 0ms);
}
/* Новые элементы (HTMX, WebSocket): карточки «Показать ещё», сообщения, диалоги */
.motion-enter { animation: enter-up var(--dur-enter) cubic-bezier(.2, .7, .2, 1) both; animation-delay: var(--enter-delay, 0ms); }
@keyframes enter-up { from { opacity: 0; transform: translateY(12px); } }
.msg.motion-enter { animation-name: msg-in; transform-origin: bottom left; }
.msg--own.motion-enter { transform-origin: bottom right; }
@keyframes msg-in { from { opacity: 0; transform: translateY(10px) scale(.94); } }
/* удалённое сообщение: пузырь схлопывается до плашки */
.msg.motion-collapse .msg__bubble { animation: collapse 360ms cubic-bezier(.2, .7, .2, 1) both; transform-origin: center left; }
@keyframes collapse { 0% { opacity: .2; transform: scaleY(.4) scaleX(.96); } 100% { opacity: 1; transform: none; } }

/* 6. Микровзаимодействия ---------------------------------------------------- */
/* Переключатель темы: иконка поворачивается */
.theme-toggle .icon { transition: transform 420ms var(--spring); }
.theme-toggle.is-pop .icon { animation: spin-pop 480ms var(--spring); }
@keyframes spin-pop { from { transform: rotate(-90deg) scale(.6); opacity: .3; } }

/* Бейджи непрочитанных: «пульс» при новом значении */
.is-bump { animation: bump 560ms var(--spring); }
@keyframes bump { 0% { transform: scale(1); } 30% { transform: scale(1.35); } 100% { transform: scale(1); } }
.tabbar__badge.is-bump, .site-nav__count.is-bump, .counter.is-bump, [data-unread-badge].is-bump { position: relative; }
.tabbar__badge.is-bump::after, .site-nav__count.is-bump::after, [data-unread-badge].is-bump::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; background: var(--c-accent);
  animation: halo 700ms ease-out forwards; z-index: -1;
}
@keyframes halo { from { opacity: .55; transform: scale(1); } to { opacity: 0; transform: scale(2.2); } }

/* «Скопировать ссылку»: иконка сменяется галочкой с прыжком */
.share-btn.is-done .icon { animation: check-pop 420ms var(--spring); }
@keyframes check-pop { 0% { transform: scale(.3) rotate(-20deg); opacity: 0; } 100% { transform: none; opacity: 1; } }

/* Toast: выезжают снизу с пружиной и уезжают вниз */
.toast { animation: toast-spring 420ms var(--spring) both; }
@keyframes toast-spring { from { opacity: 0; transform: translateY(24px) scale(.96); } }
.toast.is-leaving { animation: toast-away 220ms var(--press-ease) forwards; }
@keyframes toast-away { to { opacity: 0; transform: translateY(16px) scale(.98); } }

/* Ячейки кода: подпрыгивают при вводе, трясутся при ошибке (shake из main.css) */
.code-input__cell { transition: transform var(--dur-release) var(--spring); }
.code-input__cell.is-pop { animation: cell-pop 260ms var(--spring); }
@keyframes cell-pop { 0% { transform: translateY(0) scale(1); } 40% { transform: translateY(-5px) scale(1.06); } 100% { transform: none; } }
.code-input.is-invalid .code-input__cell { animation: shake-strong 420ms cubic-bezier(.36, .07, .19, .97) both; }
@keyframes shake-strong { 10%, 90% { transform: translateX(-1px); } 20%, 80% { transform: translateX(3px); } 30%, 50%, 70% { transform: translateX(-5px); } 40%, 60% { transform: translateX(5px); } }

/* Спиннер на кнопке во время HTMX-запроса (htmx ставит .htmx-request на элемент запроса) */
.btn.htmx-request, form.htmx-request .btn[type="submit"], form.htmx-request .composer__send,
.composer.is-sending .composer__send { color: transparent !important; pointer-events: none; }
.btn.htmx-request::after, form.htmx-request .btn[type="submit"]::after,
form.htmx-request .composer__send::after, .composer.is-sending .composer__send::after {
  content: ""; position: absolute; top: 50%; left: 50%; width: 18px; height: 18px; margin: -9px 0 0 -9px;
  border-radius: 50%; border: 2px solid var(--c-on-primary); border-right-color: transparent; background: none; opacity: 1;
  animation: spin .7s linear infinite;
}
.btn--secondary.htmx-request::after, .btn:not(.btn--primary):not(.btn--accent):not(.btn--danger).htmx-request::after { border-color: var(--c-primary); border-right-color: transparent; }
.btn.htmx-request, form.htmx-request .btn[type="submit"] { position: relative; }

/* Нижняя навигация: индикатор активного раздела «вырастает», иконка подпрыгивает */
.tabbar__item[aria-current="page"]::before { animation: indicator-in 420ms var(--spring) both; }
@keyframes indicator-in { from { transform: scaleX(0); opacity: 0; } }
.tabbar__item[aria-current="page"] > .icon { animation: tab-hop 460ms var(--spring) both; }
@keyframes tab-hop { 0% { transform: translateY(3px) scale(.9); } 100% { transform: none; } }
.tabbar__item.is-tapped > .icon, .tabbar__item.is-tapped .tabbar__plus { animation: tab-hop 360ms var(--spring); }
.tabbar__badge { transition: transform var(--dur-release) var(--spring); }

/* Чипы и сегменты: выбранный «встаёт» на место */
.chip[aria-current="true"], .chip.is-active { animation: chip-set 300ms var(--spring); }
@keyframes chip-set { from { transform: scale(.94); } }

/* Шторка и модальные окна — пружинистее */
.drawer__panel { animation: drawer-in 320ms cubic-bezier(.2, .9, .3, 1.05); }
@keyframes drawer-in { from { transform: translateX(32px); opacity: 0; } }
.modal__dialog { animation-timing-function: var(--spring); }

/* 7. Скелетоны подгрузки (motion.js вставляет их на время запроса) ---------- */
.skeleton-card.motion-skeleton { animation: enter-up 260ms ease both; }
.skeleton::after { animation-duration: 1.2s; }

/* Фокус с клавиатуры всегда виден, даже во время анимаций */
:focus-visible { outline-offset: 2px; }
.reveal:focus-within { opacity: 1; transform: none; }

/* Статья: при чтении ничего не двигается */
.prose *, .article__figure img { animation: none !important; }

/* 8. Уменьшение движения ---------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
  *, *::before, *::after { animation: none !important; }
  .reveal { opacity: 1; transform: none; }
  [class]:active, [class]:hover, .news-card:hover, .news-card:hover .news-card__media img,
  .tabbar__item:active > .icon, .tabbar__item:active .tabbar__plus, .segmented label:active span,
  .file-preview__remove:active span { transform: none !important; }
  .ripple { display: none; }
  /* цвет меняется, но мгновенно-плавно */
  .btn, .chip, .icon-btn, .news-card, .site-nav__link, .tabbar__item { transition: background-color 120ms linear, border-color 120ms linear, color 120ms linear !important; }
  /* спиннер загрузки нужен для понимания состояния — оставляем, но медленно */
  .btn.htmx-request::after, form.htmx-request .btn[type="submit"]::after, .btn.is-loading::after,
  form.htmx-request .composer__send::after { animation: spin 1.6s linear infinite !important; }
}
