/* ══════════════════════════════════════════════════════════════════
   아호비 모션 토큰 (단일 출처) · 계약: docs/MOTION_SPEC.md
   질감: 고급 슬라이딩 도어. 빠르게 출발해서 길게 부드럽게 감속한다.
   튕김(bounce)·오버슈트 금지. 애니메이션 속성은 transform·opacity 만.
   로드: index.html 에서 app.css 보다 먼저 <link> (?v= 는 서버가 자동 치환).
   여기에는 토큰과 공용 패턴 클래스만 둔다. 표면별 규칙은 각 CSS 파일에.
   ══════════════════════════════════════════════════════════════════ */
:root{
  /* ── 이징 ──
     2026-07-29 보스 "훨씬 더 부드럽게": quint(급출발)에서 S커브로 교체.
     천천히 출발해 부드럽게 가속했다가 길게 감속 — 프레임당 이동량 피크를
     낮춰 60fps 그대로도 훨씬 유려하게 보인다. */
  --motion-ease-out:cubic-bezier(.45,.05,.15,1); /* 등장·이동 (벨벳 S커브) */
  --motion-ease-in:cubic-bezier(.5,.05,.8,.5);   /* 퇴장 (완만한 가속) */

  /* ── 개폐 속도 배율 — 설정 슬라이더(settings.js)가 조정, 1=기본.
     JS(core.js ahoMotionApply)가 documentElement 인라인으로 덮어쓴다.
     폴백 타이머는 core.js ahoMs()가 같은 배율을 곱한다. ── */
  --motion-scale:1;

  /* ── 등장·이동 지속시간 위계 (큰 표면일수록 길게) ──
     2026-07-29 재조정: 이 PC 의 webview 는 GPU 가속 꺼짐 고정(TDR 이력)이라
     소프트웨어 합성이다. 실효 프레임률이 낮은 환경에서 긴 연출은 그 끊김을
     더 오래 노출할 뿐이다(1950ms = 100프레임 넘게 노출). 짧게 끊어 치는 쪽이
     같은 프레임률에서도 훨씬 매끄럽게 읽힌다. 속도 미세조정은 --motion-scale 로. */
  --motion-dur-micro:calc(180ms*var(--motion-scale));   /* 호버·토글·체브론·+버튼 회전 */
  --motion-dur-pop:calc(240ms*var(--motion-scale));     /* 드롭다운·컨텍스트 메뉴·플라이아웃 */
  --motion-dur-panel:calc(420ms*var(--motion-scale));   /* 우측 컬럼(#coCol/#orgPop/#gwPop)·모달·토스트 */
  --motion-dur-drawer:calc(520ms*var(--motion-scale));  /* 작업 패널(#work)·전폭 시트(모바일 orgPop) */
  --motion-dur-view:calc(700ms*var(--motion-scale));    /* 뷰 전환(resident↔full)·로그인→스튜디오 */

  /* ── 퇴장 지속시간 (등장의 60~70%) ── */
  --motion-dur-exit-pop:calc(160ms*var(--motion-scale));
  --motion-dur-exit-panel:calc(280ms*var(--motion-scale));
  --motion-dur-exit-drawer:calc(340ms*var(--motion-scale));
  --motion-dur-exit-view:calc(460ms*var(--motion-scale));
}

/* ── 공용 팝업 등장·퇴장 패턴 · core.js ahoShow()/ahoHide() 계약 ──
   display:none 토글 금지. visibility+opacity+transform 조합이라
   중간에 끊겨도 transition 이 역방향으로 저절로 재생된다(키프레임 금지 사유).
   표면별로 --aho-rise(진입 거리)·--aho-dur·--aho-dur-exit 만 덮어쓴다. */
.aho-anim{
  --aho-rise:8px;
  --aho-dur:var(--motion-dur-pop);
  --aho-dur-exit:var(--motion-dur-exit-pop);
  visibility:visible;opacity:1;transform:translate3d(0,0,0);
  transition:opacity var(--aho-dur) var(--motion-ease-out),
             transform var(--aho-dur) var(--motion-ease-out),
             visibility 0s;
}
.aho-anim.aho-out{
  visibility:hidden;opacity:0;transform:translate3d(0,var(--aho-rise),0);
  /* pointer-events 는 즉시 적용(트랜지션 불가 속성). visibility 지연이
     끝나기 전이나, 창 숨김 등으로 트랜지션이 멈춰 hidden 전환이 영영
     안 일어나는 경우에도 닫힌 오버레이가 클릭을 먹지 않게 한다
     (2026-07-29 "대화창 클릭 안 됨" 픽스). */
  pointer-events:none;
  transition:opacity var(--aho-dur-exit) var(--motion-ease-in),
             transform var(--aho-dur-exit) var(--motion-ease-in),
             visibility 0s linear var(--aho-dur-exit);
}
/* 애니메이션 종료 후에는 JS(transitionend)가 will-change 를 지우고
   transform 잔값을 정리한다 (글자 픽셀그리드 정렬 · 글자깨짐 이력 대응). */

/* ── 그림자 전환 패턴 (box-shadow 직접 트랜지션 금지) ──
   그림자가 변하는 요소는 ::after 에 목표 그림자를 미리 그려 두고
   opacity 만 움직인다 (래스터화 끊김·글자 깨짐 방지). 레시피:
   .foo{position:relative}
   .foo::after{content:'';position:absolute;inset:0;border-radius:inherit;
     box-shadow:<목표 그림자>;opacity:0;pointer-events:none;z-index:-1;
     transition:opacity var(--motion-dur-micro) var(--motion-ease-out)}
   .foo:hover::after{opacity:1}                                          */

/* ── 접근성: 모션 축소 ──
   지속시간만 1ms 로 줄인다 (0ms 는 transitionend 미발화 브라우저 이력). */
@media (prefers-reduced-motion:reduce){
  :root{
    --motion-dur-micro:1ms;--motion-dur-pop:1ms;--motion-dur-panel:1ms;
    --motion-dur-drawer:1ms;--motion-dur-view:1ms;
    --motion-dur-exit-pop:1ms;--motion-dur-exit-panel:1ms;
    --motion-dur-exit-drawer:1ms;--motion-dur-exit-view:1ms;
  }
}
