# 모션

움직임은 상태가 바뀌었다는 것을 알리는 데만 쓴다. 앱은 기기의 "동작 줄이기" 설정을 아직 읽지 않는다. 웹에서는 `prefers-reduced-motion`을 지킨다.

## 곡선

| 이름 | 앱 코드 | CSS | 쓰는 때 |
| --- | --- | --- | --- |
| out | `Easing.out(Easing.cubic)` | `cubic-bezier(0.33, 1, 0.68, 1)` | 나타날 때. 처음에 빠르고 끝에서 부드럽게 멈춘다. |
| in | `Easing.in(Easing.quad)` | `cubic-bezier(0.11, 0, 0.5, 0)` | 사라질 때. 천천히 시작해 빠르게 사라진다. |

## 시간

| 움직임 | 시간 | 곡선 | 쓰는 곳 |
| --- | --- | --- | --- |
| 시트 열림 | 240ms | out | `Sheet`. 어둠막은 투명해졌다 나타나고 시트는 아래에서 올라온다. |
| 시트 닫힘 | 180ms | in | `Sheet` |
| 메뉴 시트 열림 | 220ms | out | `dialog.menu` |
| 중앙 대화상자 열림 | 180ms | out | `dialog.alert`, `dialog.confirm`, `dialog.choose`. 0.96배에서 1배로 커지며 나타난다. |
| 대화상자·메뉴 닫힘 | 130ms | in | `dialog` 전체 |
| 끌어내리다 놓음 | 160ms | 기본 | `Sheet`와 메뉴 시트. 닫힐 만큼 끌지 않았을 때 제자리로 돌아온다. |
| 토스트 나타남 | 스프링(damping 18) | 스프링 | `toast`. 아래에서 위로 떠오른다. |
| 토스트 사라짐 | 160ms | 기본 | `toast` |
| 토스트 표시 시간 | 2400ms (되돌리기 버튼이 있으면 6000ms) | — | `toast` |
| 로딩 막대 깜빡임 | 700ms씩 반복 | 기본 | `Skeleton`. 투명도 0.5와 1 사이를 오간다. |
| 링 차트 채움 | 900ms (150ms 지연) | out | `AnimatedRing` |
| 숫자 올라감 | 900ms (150ms 지연) | out | `useCountUp` |
| 문제 진행 칸 채움 | 380ms | out | `SegmentedProgress` |
| 밀어서 삭제: 화면 밖으로 | 200ms | 기본 | `SwipeRow`. 110 이상 밀고 놓았을 때. |
| 밀어서 삭제: 제자리로 | 스프링(damping 18) | 스프링 | `SwipeRow` |
| 이미지 확대 되돌리기 | 180~220ms | 기본 | `ZoomableImage`. 더블탭 확대 220ms, 되돌리기 180~200ms. |
| 화면 모드 바뀜: 덮기 | 90ms | 기본 | `ThemeFade`. 새 배경색으로 화면을 덮는다. |
| 화면 모드 바뀜: 걷기 | 300ms (60ms 지연) | 기본 | `ThemeFade`. 새 모드가 그려진 뒤 덮개를 걷는다. |

## 눌림 표현

| 컴포넌트 | 눌렀을 때 |
| --- | --- |
| PrimaryButton | 0.985배 |
| CircleButton | 0.96배 |
| 탭 바 가운데 버튼 | 0.95배 |
| SecondaryButton, SmallButton, WellRow, FilterPill | 투명도 0.8 |
| AmberButton, Card | 투명도 0.85 |
| OptionRow, ChoiceCard | 투명도 0.9 |
| TextButton, IconButton | 투명도 0.6 |
| SettingsRow, 메뉴 행 | 배경이 `pressed` 색으로 바뀜 |

## 진동

| 함수 | 느낌 | 쓰는 때 |
| --- | --- | --- |
| `haptic.select` | 가벼운 선택 진동 | 탭, 칩, 슬라이더 같은 선택이 바뀔 때 |
| `haptic.tap` | 가벼운 눌림 | PrimaryButton, 대화상자 버튼을 누를 때 |
| `haptic.firm` | 중간 세기 눌림 | 길게 눌러 열기·끌기를 시작할 때 |
| `haptic.success` | 성공 알림 진동 | 정답을 맞혔을 때, 길게 눌러 확정했을 때 |
| `haptic.warning` | 경고 알림 진동 | 문제를 틀렸을 때 |
| `haptic.error` | 오류 알림 진동 | 확인 문제를 틀렸을 때, 신고 전송이 실패했을 때 |

