/* ============================================================
   모션 시스템 - 재사용 가능한 애니메이션 클래스 모음.
   같은 클래스를 쓰면 앱 어디서나 같은 느낌의 모션이 적용된다.
   새 버튼/카드/체크박스를 추가할 때는 여기 정의된 클래스를 그대로
   재사용한다 (자세한 규칙은 today-todo/CLAUDE.md 참고).

   주의: 이 앱은 상태가 바뀔 때마다 화면 일부를 통째로 다시 그리는
   구조라(진짜 DOM이 아니라 매번 새로 만들어진 요소), "상태 클래스가
   붙어있다"는 것만으로 애니메이션을 걸면 원래 있던 요소도 다시 그려질
   때마다(예: 오늘 화면의 30초 자동 갱신) 계속 재생돼버린다. 그래서
   "방금 그 동작이 일어난 순간"에만 재생돼야 하는 모션(체크 팝, 흔들림
   등)은 JS가 그 순간에만 트리거 클래스를 붙였다가 떼는 방식(ui.js의
   popOnce/shakeInvalid)을 쓴다. 반대로 모달 등장·토스트 등장처럼 "새로
   열릴 때만 진짜로 새로 만들어지는" 요소는 클래스만으로도 안전하다.
   ============================================================ */

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

/* ---------- 눌림 피드백 (버튼/필/카드 공통) ----------
   scale를 줄이기만 하므로 원래 박스보다 커지지 않는다 - 화면 밖으로
   삐져나가거나 옆 요소와 겹칠 걱정 없이 어디에나 안전하게 쓸 수 있다. */
.btn, .iconbtn, .pill, .dchip, .date-strip-day, .card-tap {
  transition: transform 0.12s ease;
}
.btn:active, .pill:active, .dchip:active, .date-strip-day:active:not(:disabled), .card-tap:active {
  transform: scale(0.96);
}
.iconbtn:active {
  transform: scale(0.9);
}

/* 목록에서 누르면 다른 화면으로 이동하는 카드형 행에 붙인다
   (예: 할 일 목록 행). 커지는 방향이 아니라 줄어드는 방향이라 안전하다. */
.card-tap { cursor: pointer; }

/* ---------- 체크 팝 (BouncyCheckbox) ----------
   완료로 바뀌는 "순간"에만 ui.js의 popOnce(el)가 이 클래스를 붙였다가
   애니메이션이 끝나면 스스로 뗀다 - 상태 클래스(.is-done)에 직접 걸지
   않는 이유는 위쪽 설명 참고. */
@keyframes pop-bounce {
  0% { transform: scale(1) rotate(0deg); }
  40% { transform: scale(1.22) rotate(-6deg); }
  70% { transform: scale(0.92) rotate(3deg); }
  100% { transform: scale(1) rotate(0deg); }
}
.pop-once { animation: pop-bounce 0.4s cubic-bezier(0.34, 1.56, 0.64, 1); }

/* ---------- 입력 오류 흔들림 ----------
   ui.js의 shakeInvalid(el)가 순간적으로 붙였다 뗀다. 가로로만 흔들리고
   너비는 그대로라 입력칸이 옆으로 삐져나가지 않는다. */
@keyframes shake-x {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-6px); }
  40% { transform: translateX(5px); }
  60% { transform: translateX(-4px); }
  80% { transform: translateX(2px); }
}
.shake-once { animation: shake-x 0.4s ease; border-color: var(--accent) !important; }

/* ---------- 모달 등장 (바텀시트 느낌) ----------
   openModal()이 호출될 때마다 매번 새로 만들어지는 요소라 클래스만으로
   안전하게 매번 재생된다. 세로 이동만 있어서 배경(position:fixed;inset:0)
   범위 안에서만 움직이고 화면 밖으로 나가지 않는다. */
@keyframes modal-backdrop-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes modal-sheet-in { from { opacity: 0; transform: translateY(28px) scale(0.98); } to { opacity: 1; transform: translateY(0) scale(1); } }
.modal-backdrop { animation: modal-backdrop-in 0.18s ease; }
.modal-sheet { animation: modal-sheet-in 0.28s cubic-bezier(0.22, 1, 0.36, 1); }

/* ---------- 토스트 등장 ----------
   toast()가 호출될 때마다 매번 새로 만들어지는 요소라 클래스만으로
   안전하다. left:50% + translateX(-50%)로 가운데 정렬된 상태를 그대로
   유지하면서 세로로만 살짝 떠오른다. */
@keyframes toast-in { from { opacity: 0; transform: translate(-50%, 14px); } to { opacity: 1; transform: translate(-50%, 0); } }
.toast { animation: toast-in 0.3s cubic-bezier(0.22, 1, 0.36, 1); }

/* ---------- 히어로 마스코트 둥실둥실 (오늘 화면) ----------
   .hero가 overflow:hidden이라 떠다니는 범위가 카드 밖으로 새어나가지
   않는다. 진폭을 작게 둬서 은은하게만 움직인다. */
@keyframes mascot-float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-6px); }
}
.hero-illust { animation: mascot-float 3.6s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .hero-illust { animation: none; } }

/* ---------- 드래그로 순서 바꾸기 - 들어올리는 느낌 ----------
   transform은 today.js가 드래그 중 손가락 위치를 따라가며 매 프레임
   직접 바꾸므로(스타일 인라인), 여기서는 transform을 건드리지 않고
   그림자만 부드럽게 깊어지게 한다 - transform에 transition을 걸면
   손가락을 따라가는 움직임이 버벅이게 된다. */
.trow { transition: box-shadow 0.18s ease; }

/* ---------- 할 일 목록 카드 등장 ----------
   goals.js는(오늘 화면과 달리) 주기적으로 다시 그리지 않고 실제
   탐색/등록/수정 동작이 있을 때만 다시 그려지므로, 등장 애니메이션을
   걸어도 매번 "진짜 새로 나타난 순간"에만 재생된다. */
@keyframes card-rise-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.divider-list.goal-list-appear > .goal-row {
  animation: card-rise-in 0.35s cubic-bezier(0.22, 1, 0.36, 1) backwards;
}
.divider-list.goal-list-appear > .goal-row:nth-child(1) { animation-delay: 0.02s; }
.divider-list.goal-list-appear > .goal-row:nth-child(2) { animation-delay: 0.06s; }
.divider-list.goal-list-appear > .goal-row:nth-child(3) { animation-delay: 0.1s; }
.divider-list.goal-list-appear > .goal-row:nth-child(4) { animation-delay: 0.14s; }
.divider-list.goal-list-appear > .goal-row:nth-child(n+5) { animation-delay: 0.18s; }
