/* 모션 언어 (MOTION-BRIEF.md) — 움직임 정도·마이크로 인터랙션·상태 호흡. 길이·곡선은 tokens.css 토큰만.
   html[data-motion] = normal | calm | off  (public/js/motion.js 가 관리자 설정 + 「동작 줄이기」로 정한다)
   transform·opacity 만 움직인다(레이아웃 속성 금지). 깜빡임은 초당 3회를 넘지 않는다(가장 빠른 반복 --d-pulse 1.2s). */

/* ───────── 움직임 정도 ───────── */
:root[data-motion="calm"] { --loop: 3; }
:root[data-motion="off"] *, :root[data-motion="off"] *::before, :root[data-motion="off"] *::after {
  animation-duration: 1ms !important; animation-iteration-count: 1 !important; animation-delay: 0ms !important;
  transition-duration: 1ms !important; transition-delay: 0ms !important; scroll-behavior: auto !important;
}
:root[data-motion="off"] ::view-transition-group(*), :root[data-motion="off"] ::view-transition-old(*), :root[data-motion="off"] ::view-transition-new(*) { animation: none !important; }
/* 진행 표시는 「끔」·「동작 줄이기」에서도 돈다(멈추면 멈춘 것처럼 보여 오해) */
:root[data-motion="off"] .spinner, :root[data-motion="off"] .btn.is-busy::after { animation: spin var(--d-loader) linear infinite !important; }
:root[data-motion="off"] .progress.indet > i, :root[data-motion="off"] .topbar-progress i { animation: indet var(--d-loader) var(--ease-in-out) infinite !important; }
@media (prefers-reduced-motion: reduce) {
  .spinner, .btn.is-busy::after { animation: spin var(--d-loader) linear infinite !important; }
  .progress.indet > i, .topbar-progress i { animation: indet var(--d-loader) var(--ease-in-out) infinite !important; }
}

/* ───────── 조작 반응 ───────── */
.btn, .tab, .seg button, .stat-tile[type="button"], button.stat-tile, .switch, .pe-zrow, .hp-chip {
  transition: transform var(--d-fast) var(--ease), background-color var(--d-fast) var(--ease), border-color var(--d-fast) var(--ease), color var(--d-fast) var(--ease), box-shadow var(--d-base) var(--ease);
}
.btn:active:not(:disabled), .seg button:active, button.stat-tile:active, .pe-zrow:active { transform: scale(.97); }
.switch i { transition: transform var(--d-base) var(--ease-spring); }
:focus-visible { transition: outline-offset var(--d-fast) var(--ease); }

/* 값 바뀜·새로 생김: 잠깐 떠올랐다가 가라앉음(테두리 빛 + 아주 작은 들림) */
@keyframes mo-bump {
  0% { transform: translateY(0); box-shadow: 0 0 0 0 color-mix(in srgb, var(--st-line, var(--brand)) 0%, transparent); }
  25% { transform: translateY(-1px); box-shadow: 0 0 0 3px color-mix(in srgb, var(--st-line, var(--brand)) 28%, transparent); }
  100% { transform: none; box-shadow: 0 0 0 0 color-mix(in srgb, var(--st-line, var(--brand)) 0%, transparent); }
}
.mo-bump { animation: mo-bump var(--d-bump) var(--ease); }
/* 실패: 짧은 흔들림 한 번 */
@keyframes mo-shake { 0%, 100% { transform: none; } 20% { transform: translateX(-5px); } 40% { transform: translateX(4px); } 60% { transform: translateX(-3px); } 80% { transform: translateX(2px); } }
.mo-shake { animation: mo-shake var(--d-slow) var(--ease); }

/* 목록 등장(차례로): --i 는 motion.js stagger() 가 매긴다 */
@keyframes mo-rise { from { transform: translateY(6px); } to { transform: none; } } /* 투명도는 쓰지 않는다: 뒤 탭에서 멈춰도 내용이 보이게 */
.mo-rise { animation: mo-rise var(--d-slow) var(--ease) both; animation-delay: calc(var(--i, 0) * var(--stagger)); }

/* 저장 성공: 체크가 그려짐 */
@keyframes mo-draw { from { stroke-dashoffset: 24; } to { stroke-dashoffset: 0; } }
.toast .icon path, .mo-check path { stroke-dasharray: 24; animation: mo-draw var(--d-slow) var(--ease) var(--d-fast) both; }

/* ───────── 서랍·모달: 배경 흐림 + 아래에서 올라옴 ───────── */
dialog.dlg::backdrop, dialog.drawer::backdrop { backdrop-filter: blur(3px) saturate(.9); -webkit-backdrop-filter: blur(3px) saturate(.9); }
@keyframes mo-dlg-in { from { transform: translateY(14px) scale(.985); } to { transform: none; } }
dialog.dlg[open] { animation: mo-dlg-in var(--d-slow) var(--ease-spring); }
@media (min-width: 769px) {
  @keyframes mo-drawer-in { from { transform: translateX(28px); } to { transform: none; } }
  dialog.drawer[open] { animation: mo-drawer-in var(--d-slow) var(--ease); }
}
@media (max-width: 768px) {
  @keyframes mo-sheet-in { from { transform: translateY(40%); } to { transform: none; } }
  dialog.drawer[open] { animation: mo-sheet-in var(--d-slow) var(--ease-spring); }
}

/* ───────── 화면 전환: 본문만 짧게 — 화면 틀(.page 의 page-in)은 그대로, 본문 덩어리가 차례로 떠오른다 ───────── */
.page > :nth-child(-n+6) { animation: mo-rise var(--d-slow) var(--ease) both; }
.page > :nth-child(2) { animation-delay: calc(var(--stagger) * 1); }
.page > :nth-child(3) { animation-delay: calc(var(--stagger) * 2); }
.page > :nth-child(4) { animation-delay: calc(var(--stagger) * 3); }
.page > :nth-child(5) { animation-delay: calc(var(--stagger) * 4); }
.page > :nth-child(6) { animation-delay: calc(var(--stagger) * 5); }
.page > .st-savebar, .page > .pe-savebar { animation: none; }

/* ───────── 상태가 살아 있게 ───────── */
/* 연결·정상: 아주 느린 호흡(점 둘레 빛) */
@keyframes mo-breath { 0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--st-done-line) 0%, transparent); } 50% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--st-done-line) 22%, transparent); } }
.conn-dot[data-conn="live"] i, .mh-live[data-conn="live"] i, .mh-live:not([data-conn]) i { animation: mo-breath var(--d-breath) var(--ease-in-out) var(--loop); }

/* 경보 단계: 주의 = 부드러운 맥동, 위험(P1) = 선명한 맥동 + 테두리(기존 pulse-ring) */
@keyframes mo-caution { 0%, 100% { box-shadow: 0 0 0 1px color-mix(in srgb, var(--st-caution-line) 40%, transparent); } 50% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--st-caution-line) 22%, transparent); } }
.bedtile[data-alarm="p2"], .bedtile[data-alarm="p3"] { animation: mo-caution calc(var(--d-breath) * .75) var(--ease-in-out) var(--loop); }
.fc.is-new:not([data-lv="p1"]) { animation: fc-in var(--d-base) var(--ease), mo-bump var(--d-bump) var(--ease) var(--d-base); }

/* KPI 값: 롤링하는 동안 자리 고정(숫자 폭 흔들림 방지) */
.st-value { font-variant-numeric: tabular-nums; }

/* 실패 알림창: 등장 뒤 한 번 흔들림(ui.js alertBox → motion.shake). dialog.dlg[open] 의 등장 애니메이션보다 우선해야 한다 */
dialog.dlg[open].mo-shake { animation: mo-shake var(--d-slow) var(--ease); }
