/* сарафан · движение (design/motion.css, доска «Движение · лёгкие анимации»). Только CSS, двигаем только
   transform и opacity. Классы — с префиксом sf-: свои .photo / .sheet / .toast у нас уже есть. */

:root {
  --dur-press: 120ms;   /* нажатие */
  --dur: 200ms;         /* чипы, переключатели, наведение */
  --dur-panel: 280ms;   /* шторки, панели */
  --dur-out: 170ms;     /* уход всегда быстрее появления */
  --ease-out: cubic-bezier(.2, .8, .2, 1);
  --ease-in: cubic-bezier(.4, 0, 1, 1);
  --stagger: 60ms;
  --skel: #E8EEF7;
  --skel-shine: rgba(255, 255, 255, .65);
}
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --skel: #1C2A45; --skel-shine: rgba(255, 255, 255, .06); } }
:root[data-theme="dark"] { --skel: #1C2A45; --skel-shine: rgba(255, 255, 255, .06); }

/* 1. Нажатие: мгновенный отклик до ответа сети — на кнопках и чипах (:where — не перебивает свои transition) */
:where(button, .btn, .c-btn, .c-chip, .st, .sf-press):not(:disabled) { transition: transform var(--dur-press) var(--ease-out); }
:where(button, .btn, .c-btn, .c-chip, .st, .sf-press):not(:disabled):active { transform: scale(.96); }

/* 2. Наведение на карточку (только мышь) */
@media (hover: hover) {
  .sf-lift { transition: transform var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out); }
  .sf-lift:hover { transform: translateY(-3px); box-shadow: 0 10px 24px rgba(15, 30, 58, .12); }
}

/* 3. Появление снизу: абзацы ответа (шаг 120 мс = --i через один), строки мест (шаг 60 мс), первые 6 */
@keyframes sf-up { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
.sf-enter { animation: sf-up 220ms var(--ease-out) both; animation-delay: calc(var(--i, 0) * var(--stagger)); }

/* 3а. Ответ гида: абзацы — шаг 120 мс, места — строками по 60 мс (задержка только у первых 6), без печати по буквам.
   Класс .sf-answer-in висит на блоке ответа первую секунду (chat.js, guide.js) */
.sf-answer-in :is(.c-text, .a-text) > *, .sf-answer-in :is(.c-pl, .ans-places) > * { animation: sf-up 220ms var(--ease-out) both; }
.sf-answer-in :is(.c-text, .a-text) > :nth-child(2) { animation-delay: 120ms; }
.sf-answer-in :is(.c-text, .a-text) > :nth-child(3) { animation-delay: 240ms; }
.sf-answer-in :is(.c-text, .a-text) > :nth-child(4) { animation-delay: 360ms; }
.sf-answer-in :is(.c-text, .a-text) > :nth-child(5) { animation-delay: 480ms; }
.sf-answer-in :is(.c-text, .a-text) > :nth-child(n+6) { animation-delay: 600ms; }
.sf-answer-in :is(.c-pl, .ans-places) > :nth-child(1) { animation-delay: 240ms; }
.sf-answer-in :is(.c-pl, .ans-places) > :nth-child(2) { animation-delay: 300ms; }
.sf-answer-in :is(.c-pl, .ans-places) > :nth-child(3) { animation-delay: 360ms; }
.sf-answer-in :is(.c-pl, .ans-places) > :nth-child(4) { animation-delay: 420ms; }
.sf-answer-in :is(.c-pl, .ans-places) > :nth-child(5) { animation-delay: 480ms; }
.sf-answer-in :is(.c-pl, .ans-places) > :nth-child(n+6) { animation-delay: 540ms; }

/* 4. Скелетон — только если ждём дольше 300 мс (иначе мигал бы): блок проявляется с задержкой */
@keyframes sf-shimmer { from { transform: translateX(-100%); } to { transform: translateX(100%); } }
@keyframes sf-appear { to { opacity: 1; } }
.sf-loading { display: flex; flex-direction: column; gap: 8px; padding: 4px 0; opacity: 0; animation: sf-appear 1ms 300ms forwards; }
.sf-skeleton { position: relative; display: block; height: 12px; overflow: hidden; background: var(--skel); border-radius: 8px; }
.sf-skeleton.short { width: 60%; }
.sf-skeleton::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, transparent, var(--skel-shine), transparent); animation: sf-shimmer 1.4s infinite; }

/* 5. Фото: до загрузки контейнер залит средним цветом фото (из данных), потом проявление за 400 мс */
.sf-photo { opacity: 0; transform: scale(1.03); transition: opacity 400ms var(--ease-out), transform 400ms var(--ease-out); }
.sf-photo.is-loaded { opacity: 1; transform: none; }

/* 6. Шторка чата на телефоне: появление 280 мс, уход быстрее — 170 мс (на десктопе это окно по центру — без выезда) */
@keyframes sf-sheet-in { from { transform: translateY(100%); } }
@keyframes sf-fade-in { from { opacity: 0; } }
.c-sheet-wrap.is-closing .c-overlay { opacity: 0; transition: opacity var(--dur-out) var(--ease-in); }
@media (max-width: 899px) {
  .c-sheet-wrap:not(.is-closing) .c-sheet { animation: sf-sheet-in var(--dur-panel) var(--ease-out); }
  .c-sheet-wrap:not(.is-closing) .c-overlay { animation: sf-fade-in var(--dur-panel) var(--ease-out); }
  .c-sheet-wrap.is-closing .c-sheet { transform: translateY(100%); transition: transform var(--dur-out) var(--ease-in); }
}
@media (min-width: 900px) {
  .c-sheet-wrap.is-closing .c-sheet { opacity: 0; transition: opacity var(--dur-out) var(--ease-in); }
}

/* 8. Смена линзы / экрана: короткий crossfade */
@keyframes sf-fade { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
.sf-view-enter { animation: sf-fade 160ms var(--ease-out) both; }

/* 9. Пины на карте: только при первом показе или смене линзы, шаг 40 мс, всего не больше 300 мс */
@keyframes sf-pop { 0% { opacity: 0; transform: scale(.4); } 70% { opacity: 1; transform: scale(1.12); } 100% { transform: scale(1); } }
.sf-pin-enter { animation: sf-pop 260ms var(--ease-out) both; animation-delay: min(calc(var(--i, 0) * 40ms), 300ms); }
/* маркеры MapLibre: их положение — в transform, поэтому прыгаем свойством scale (оно складывается с transform) */
@keyframes sf-pop-marker { 0% { opacity: 0; scale: .4; } 70% { opacity: 1; scale: 1.12; } 100% { scale: 1; } }
.sf-pin-pop { animation: sf-pop-marker 260ms var(--ease-out) both; animation-delay: min(calc(var(--i, 0) * 40ms), 300ms); }

/* 10. «Сохранено»: сердце прыгает */
@keyframes sf-bump { 0% { transform: scale(1); } 40% { transform: scale(1.25); } 100% { transform: scale(1); } }
.sf-bump { animation: sf-bump var(--dur) var(--ease-out); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 1ms !important; animation-iteration-count: 1 !important; transition-duration: 1ms !important; }
}
