/* Движение. Правило: анимация объясняет, что произошло, и никогда не задерживает.
   Анимируем только transform и opacity — остальное на телефоне заикается. */

:root {
  --dur-fast: 140ms;
  --dur: 240ms;
  --dur-slow: 420ms;
  --ease-out: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-fast: 1ms;
    --dur: 1ms;
    --dur-slow: 1ms;
    --ease-spring: linear;
  }

  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }

  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) { animation: none !important; }
}

/* --- базовые отклики на касание ------------------------------------------- */

.icon-btn,
.btn,
.pill,
.day-card,
.tab,
.scale-btn,
.check {
  transition: transform var(--dur-fast) var(--ease-out),
              background-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              opacity var(--dur-fast) var(--ease-out),
              filter var(--dur-fast) var(--ease-out),
              box-shadow var(--dur) var(--ease-out);
}

.pill:active { transform: scale(0.96); }
.scale-btn:active { transform: scale(0.9); }
.check:active { transform: scale(0.88); }

/* Выбранный значок шкалы вырастает с лёгким перелётом — видно, что выбор принят. */
.scale-btn[aria-pressed='true'] {
  transform: scale(1.16);
  transition: transform var(--dur) var(--ease-spring),
              background-color var(--dur-fast) var(--ease-out),
              filter var(--dur-fast) var(--ease-out),
              opacity var(--dur-fast) var(--ease-out);
}

.scale:has(.scale-btn[aria-pressed='true']) .scale-btn:not([aria-pressed='true']) {
  transform: scale(0.92);
}

.tab[aria-current='page'] .tab-icon {
  animation: tab-pop var(--dur) var(--ease-spring);
}

@keyframes tab-pop {
  0% { transform: scale(0.8); }
  100% { transform: scale(1); }
}

/* --- появление содержимого ------------------------------------------------ */

.screen-body > * {
  animation: rise var(--dur) var(--ease-out) both;
}

@keyframes rise {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}

/* Ступенчатое появление списков: задаётся из JS через --i. */
.stagger > * {
  animation: rise var(--dur) var(--ease-out) both;
  animation-delay: calc(var(--i, 0) * 30ms);
}

/* --- солнышко ------------------------------------------------------------- */

.sun.is-lighting .sun-core {
  animation: sun-core var(--dur-slow) var(--ease-spring) both;
}

.sun.is-lighting .sun-rays {
  stroke-dasharray: 4 60;
  animation: sun-rays var(--dur-slow) var(--ease-out) both;
}

@keyframes sun-core {
  0% { transform: scale(0.4); }
  60% { transform: scale(1.18); }
  100% { transform: scale(1); }
}

@keyframes sun-rays {
  from { stroke-dashoffset: 60; opacity: 0; }
  to { stroke-dashoffset: 0; opacity: 1; }
}

/* Солнышко-награда, летящее в шапку к балансу. */
.sun-fly {
  position: fixed;
  z-index: 45;
  font-size: 26px;
  pointer-events: none;
  will-change: transform, opacity;
}

.stat-chip.is-bumped { animation: bump var(--dur) var(--ease-spring); }

@keyframes bump {
  0% { transform: scale(1); }
  45% { transform: scale(1.18); }
  100% { transform: scale(1); }
}

/* Сегодняшний день один раз мягко пульсирует — глаз находит его без чтения. */
.day-card.is-pulsing { animation: today-pulse 1.1s var(--ease-out) 1; }

@keyframes today-pulse {
  0%, 100% { box-shadow: var(--shadow-1), inset 0 0 0 2px var(--accent); }
  45% { box-shadow: var(--shadow-1), inset 0 0 0 2px var(--accent), 0 0 0 8px var(--accent-soft); }
}

/* --- задачи --------------------------------------------------------------- */

.check[aria-pressed='true'] path {
  stroke-dasharray: 22;
  animation: draw-check var(--dur) var(--ease-out) both;
}

@keyframes draw-check {
  from { stroke-dashoffset: 22; }
  to { stroke-dashoffset: 0; }
}

.task-row.is-done .task-text .strike::after {
  content: '';
  position: absolute;
  left: 0;
  top: 52%;
  height: 1.5px;
  width: 100%;
  background: currentColor;
  transform-origin: left center;
  animation: strike var(--dur) var(--ease-out) both;
}

@keyframes strike {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

/* --- аналитика ------------------------------------------------------------ */

.compare-bar, .bar-fill, .progress i {
  transition: transform var(--dur-slow) var(--ease-out);
  transform: scaleY(var(--grow, 1));
}

.bar-fill, .progress i {
  transform: scaleX(var(--grow, 1));
}

.chart-line {
  stroke-dasharray: var(--len, 0);
  stroke-dashoffset: var(--len, 0);
  animation: draw-line var(--dur-slow) var(--ease-out) forwards;
}

@keyframes draw-line {
  to { stroke-dashoffset: 0; }
}

.chart-dot { animation: dot-in var(--dur) var(--ease-spring) both; transform-origin: center; }

@keyframes dot-in {
  from { transform: scale(0); opacity: 0; }
  to { transform: scale(1); opacity: 1; }
}

/* --- разблокировка прошлого дня ------------------------------------------- */

.unlocking > * {
  animation: unlock var(--dur) var(--ease-out) both;
  animation-delay: calc(var(--i, 0) * 30ms);
}

@keyframes unlock {
  from { opacity: 0.55; transform: translateY(4px); }
  to { opacity: 1; transform: none; }
}

/* --- шит и уведомления ---------------------------------------------------- */

.sheet-backdrop { animation: fade var(--dur-fast) var(--ease-out) both; }
.sheet { animation: sheet-up var(--dur) var(--ease-out) both; }
.notice { animation: notice-in var(--dur) var(--ease-spring) both; }
.onboarding { animation: fade var(--dur) var(--ease-out) both; }

@keyframes fade { from { opacity: 0; } to { opacity: 1; } }

@keyframes sheet-up {
  from { transform: translateY(18px); opacity: 0; }
  to { transform: none; opacity: 1; }
}

@keyframes notice-in {
  from { transform: translateY(14px); opacity: 0; }
  to { transform: none; opacity: 1; }
}

/* --- переходы между экранами ---------------------------------------------- */

::view-transition-old(root) { animation: vt-out var(--dur) var(--ease-out) both; }
::view-transition-new(root) { animation: vt-in var(--dur) var(--ease-out) both; }

@keyframes vt-out { to { opacity: 0; transform: translateY(-6px); } }
@keyframes vt-in { from { opacity: 0; transform: translateY(6px); } }

/* Карточка дня морфится в заголовок дня и обратно. */
::view-transition-group(dayhero) { animation-duration: var(--dur); }

/* --- фото дня ------------------------------------------------------------- */

/* Наклон живёт на внешней рамке, а появление — на самой «бумаге»: анимация с
   fill: both удерживает свой transform и перебила бы и наклон, и перетаскивание. */
.photo-paper {
  animation: photo-drop var(--dur-slow) var(--ease-out) both;
  transition: box-shadow var(--dur) var(--ease-out);
}

@keyframes photo-drop {
  from { opacity: 0; transform: translateY(-10px) scale(1.03); }
  to { opacity: 1; transform: none; }
}

.photo { transition: transform var(--dur) var(--ease-spring); }

/* Карточка «в руке»: следует за пальцем без задержки и слегка приподнимается.
   Отпустили — класс снимается, и transition возвращает её на место. */
.photo.is-held {
  transition: none;
  position: relative;
  z-index: 5;
  transform: translate(var(--drag-x), var(--drag-y)) rotate(var(--tilt)) scale(1.04);
}

.photo.is-held .photo-paper { box-shadow: 0 22px 44px rgba(58, 45, 25, 0.28); }

/* --- просмотр во весь экран ------------------------------------------------ */

.viewer { animation: fade var(--dur) var(--ease-out) both; }
.viewer.is-leaving { animation: fade var(--dur-fast) var(--ease-out) reverse both; }
.viewer-img { animation: viewer-in var(--dur) var(--ease-out) both; }

@keyframes viewer-in {
  from { opacity: 0; transform: rotate(var(--turn, 0deg)) scale(0.94); }
  to { opacity: 1; transform: rotate(var(--turn, 0deg)); }
}
