/* 베리북스 모션 — 디자이너 「베리북스 모션 스펙」 시트 그대로 (2026-09-23 받음)
 *
 * 화면마다 따로 적지 않고 여기 한 곳에 둡니다. 모든 쪽이 이 파일을 함께 읽습니다.
 * 스펙에 없는 움직임은 넣지 않습니다.
 *
 * 맨 아래 reduced-motion 은 스펙의 마지막 줄입니다 —
 * 「OS 설정 시 이동 · 스케일 · 자동 전환을 끄고 페이드 0.2s 만」.
 */

/* ───────── 공통 ───────── */

/* 버튼 hover — 면색 한 단계 진하게, 위로 1px, 0.15s */
.btn {
    transition: background-color 0.15s ease, color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease, filter 0.15s ease;
}
.btn:hover { transform: translateY(-1px); filter: brightness(0.92); }
/* 흰 버튼은 어둡게가 아니라 연녹으로 (스펙 「흰→연녹」 · 2026-09-28) */
.btn--secondary:hover, .btn--line:hover { filter: none; background-color: var(--vb-color-brand-green-tint); }
/* 버튼 클릭 — 누르는 순간 0.97 로 줄었다 돌아옴, 0.1s */
.btn:active { transform: scale(0.97); transition-duration: 0.1s; }

/* 버튼 로딩 — 라벨 자리에 점 3개, 버튼 폭은 그대로 */
.btn.is-loading { color: transparent !important; position: relative; pointer-events: none; }
.btn.is-loading::after {
    content: '';
    position: absolute; left: 50%; top: 50%; width: 4px; height: 4px; margin: -2px 0 0 -2px;
    border-radius: 50%; background: currentColor; color: inherit;
    box-shadow: -8px 0 0 currentColor, 8px 0 0 currentColor;
    animation: vb-dots 1s infinite steps(3);
}
@keyframes vb-dots { 0% { opacity: 0.25; } 50% { opacity: 1; } 100% { opacity: 0.25; } }

/* 텍스트 링크 hover — 밑줄이 왼쪽에서 오른쪽으로, 「→」 4px 이동, 0.2s */
.text-link {
    background-image: linear-gradient(currentColor, currentColor);
    background-repeat: no-repeat;
    background-position: 0 100%;
    background-size: 0 1px;
    text-decoration: none;
    transition: background-size 0.2s ease;
}
.text-link:hover { background-size: 100% 1px; }
.text-link .arrow, .text-link::after { transition: transform 0.2s ease; }
.text-link:hover .arrow { transform: translateX(4px); }

/* 카드 hover — 테두리 초록 + 위로 2px, 0.2s, 그림자 없음 (클릭되는 카드만) */
.b-card, .rd-shortcut, .rd-next, .bx-card--link {
    transition: transform 0.2s ease, border-color 0.2s ease;
}
.b-card:hover, .rd-shortcut:hover, .rd-next:hover, .bx-card--link:hover {
    transform: translateY(-2px);
    border-color: var(--vb-color-brand-green);
}

/* 칩 · 탭 전환 — 색만 0.15s (슬라이딩 없음) */
.bx-tab, .fr-tab, .rk-scope a, .rk-tools a, .my-chip, .sp-tab, .lt-step {
    transition: background-color 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;
}

/* 페이지 진입 — 아래서 위로 16px + 페이드 0.3s (헤더는 고정)
   명예의 전당(.rk)은 자체 연출이 있어 뺍니다 · 안쪽 .my-page · .sp 에 또 걸면 32px 겹쳐 움직여 뺐습니다 (2026-09-28 점검) */
.main:not(.rk), .auth, .org-wrap, .info-page, .bd-main, .lt-intro:not(.lt-result), main.page {
    /* backwards — 끝난 뒤 transform 을 남기지 않음. both 로 두면 본문이 고정 팝업의 기준이 되어
       팝업 카드가 긴 본문 한가운데(화면 밖)에 그려짐 · 독서 현황 보호자 전용 (2026-09-30 사용자 제보) */
    animation: vb-page-in 0.3s ease backwards;
}
@keyframes vb-page-in { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }

/* 인증 구간(RR 응시 · TR 작성 · 피드백 · 결과)은 페이드만 0.2s, 이동 없음 */
.rp-main, .rp-result, .lt-play, .tf-work, .tf-fb, .tf-center {
    animation: vb-fade-in 0.2s ease both;
}
@keyframes vb-fade-in { from { opacity: 0; } to { opacity: 1; } }

/* 오버레이 열기 · 닫기 — 딤 페이드 + 창 0.96 → 1, 0.2s · 닫기는 역순
   친구 요청(.fr-modal) · 회원정보(.vb-modal) · TR 작성(.tf-modal) · 기관(.org-modal)까지 모든 팝업 (2026-09-28)
   딤 색은 피그마 화면마다 정해진 색을 그대로 둡니다(스펙의 #101418 50% 와 달라 화면 쪽을 따름) */
[class*="-modal__card"], .vb-modal__box { animation: vb-pop-in 0.2s ease both; }
[class*="-modal__dim"] { animation: vb-fade-in 0.2s ease both; }
.is-closing [class*="-modal__card"], .is-closing .vb-modal__box { animation: vb-pop-out 0.2s ease both; }
.is-closing [class*="-modal__dim"] { animation: vb-fade-out 0.2s ease both; }
@keyframes vb-pop-in { from { opacity: 0; transform: scale(0.96); } to { opacity: 1; transform: none; } }
@keyframes vb-pop-out { from { opacity: 1; transform: none; } to { opacity: 0; transform: scale(0.96); } }
@keyframes vb-fade-out { from { opacity: 1; } to { opacity: 0; } }

/* ? 도움말 팝오버 — 버튼 아래 8px 에서 내려오며 페이드 0.15s */
.rp-help, .tf-help { animation: vb-pop-down 0.15s ease both; }
@keyframes vb-pop-down { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }

/* GNB 메뉴 hover — 메가메뉴 · 프로필 드롭다운 페이드 0.1s */
.gnb__mega { transition: opacity 0.1s ease, visibility 0.1s ease; }
/* 프로필 드롭다운은 hidden 으로 켜고 끄므로 나타날 때 페이드 (클래스 이름이 달라 안 걸리던 것 · 2026-09-28) */
.gnb__dropdown:not([hidden]) { animation: vb-fade-in 0.1s ease both; }

/* 표 행 hover — 스펙 대상(관리자 학생 목록 · 반 상세)은 관리자 CSS(admin-a/css/admin.css .tbl-hover)에 있습니다 */

/* 입력창 — focus 테두리 초록 0.15s · 오류 시 좌우 4px 흔들림 1회 */
.input, .form-textarea, input[type="text"], input[type="password"], input[type="email"], textarea, select {
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.is-error, .input.is-error, .input--error, .field--error .input,
input[aria-invalid="true"], textarea[aria-invalid="true"] { animation: vb-shake 0.2s ease 1; }
@keyframes vb-shake {
    0%, 100% { transform: translateX(0); }
    25% { transform: translateX(-4px); }
    75% { transform: translateX(4px); }
}

/* 진행 바 채움 — 0 에서 현재 값까지 0.6s */
.bx-bar > span, .bd-dist__bar > span, .rd-next__bar > span, .rd-next__bar > i, .km-bar__fill {
    transition: width 0.6s ease;
}

/* 토스트 — 아래 가운데에서 올라오고 2.5s 뒤 내려감 (복사됨 · 저장됨 · motion.js vbToast)
   관리자 알림(.xl-toast)은 사용자 요청으로 위쪽에 두어 여기서 다루지 않습니다 (2026-09-23) */
.vb-toast {
    position: fixed; left: 50%; bottom: 32px; z-index: 1000; transform: translate(-50%, 0);
    padding: 12px 20px; border-radius: 999px; background: var(--vb-color-text-title, #0f381f); color: #fff;
    font-size: 14px; line-height: 20px; box-shadow: 0 6px 20px rgba(15, 56, 31, 0.18);
    animation: vb-toast-in 0.25s ease both;
}
.vb-toast.is-out { animation: vb-toast-out 0.25s ease both; }
@keyframes vb-toast-in { from { opacity: 0; transform: translate(-50%, 12px); } to { opacity: 1; transform: translate(-50%, 0); } }
@keyframes vb-toast-out { from { opacity: 1; transform: translate(-50%, 0); } to { opacity: 0; transform: translate(-50%, 12px); } }

/* 스켈레톤 — 회색 블록 좌→우 쉬머 1.2s 반복 */
.skeleton {
    background: linear-gradient(90deg, #eef1f4 25%, #f7f9fa 37%, #eef1f4 63%);
    background-size: 400% 100%;
    animation: vb-shimmer 1.2s ease-in-out infinite;
}
@keyframes vb-shimmer { from { background-position: 100% 50%; } to { background-position: 0 50%; } }

/* ───────── 화면별 ───────── */

/* 도서 상세 하트 — 빨강 채움 + 1.3 → 1 바운스 0.3s (취소는 페이드 0.2s) */
.bd-wish img { transition: opacity 0.2s ease; }
.bd-wish[aria-pressed="true"] img { animation: vb-heart 0.3s ease both; }
.bd-wish.is-touched[aria-pressed="false"] img { animation: vb-fade-in 0.2s ease both; }
@keyframes vb-heart { 0% { transform: scale(1); } 40% { transform: scale(1.3); } 100% { transform: scale(1); } }

/* TR 글자 수 달성 — 카운터 회색→초록, ✓ 1.2 → 1 팝 0.2s */
.tf-count { transition: color 0.2s ease; }
.tf-count.is-ok { color: var(--vb-color-brand-green); }
.tf-count.is-ok::before { content: '✓'; display: inline-block; margin-right: 4px; animation: vb-pop 0.2s ease both; }
@keyframes vb-pop { from { transform: scale(1.2); } to { transform: scale(1); } }

/* 레벨테스트 타이머 — 남은 1분에 숫자 색만 빨강 (펄스 없음) */
.lt-top__timer.is-urgent { color: var(--vb-color-semantic-error); transition: color 0.2s ease; }

/* 명예의 전당 시상대 — 3위 → 2위(+120ms) 빠르게, 1위(+270ms)는 56px 아래서 0.6s 로 천천히 · 1위 거리 카운트업
   명예의 전당 카드(.podium__card--N)에만 겁니다 — 전에는 홈 미리보기에만 걸려 있었습니다 (2026-09-28) */
.rk .podium__card--3 { animation: vb-podium 0.35s ease both; }
.rk .podium__card--2 { animation: vb-podium 0.35s ease 0.12s both; }
.rk .podium__card--1 { animation: vb-podium-first 0.6s ease 0.27s both; }
@keyframes vb-podium { from { opacity: 0; transform: translateY(48px); } to { opacity: 1; transform: none; } }
@keyframes vb-podium-first { from { opacity: 0; transform: translateY(56px); } to { opacity: 1; transform: none; } }

/* 랭킹 전체 · 친구 전환 — 표 크로스페이드 0.25s (재정렬 아님) */
.rank-table { animation: vb-fade-in 0.25s ease both; }

/* 친구 요청 수락 — 행이 초록으로 물들고 위로 접히며 사라짐 0.3s */
.fr-row.is-accepted {
    animation: vb-row-accept 0.3s ease both;
    background: var(--vb-color-brand-green-surface, #eaf6ef);
}
@keyframes vb-row-accept {
    to { opacity: 0; transform: translateY(-8px); max-height: 0; padding-top: 0; padding-bottom: 0; }
}

/* 배지 획득 — 아이콘 0.6 → 1 바운스 0.5s + 연녹 파문 1회 */
.bx-earned__icon { animation: vb-badge-pop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) both; }
.bx-earned__ring { position: relative; display: inline-block; }
.bx-earned__ring::after {
    content: ''; position: absolute; inset: -6px; border-radius: 50%;
    background: var(--vb-color-brand-green-tint, #eaf8e6); z-index: -1;
    animation: vb-ripple 0.6s ease 0.2s both;
}
.bx-earned__title, .bx-earned__name, .bx-earned__desc, .bx-earned__chip { animation: vb-fade-in 0.3s ease 0.3s both; }
@keyframes vb-badge-pop { from { opacity: 0; transform: scale(0.6); } to { opacity: 1; transform: scale(1); } }
@keyframes vb-ripple {
    from { opacity: 0.5; transform: scale(0.8); }
    to { opacity: 0; transform: scale(1.6); }
}

/* 최종 인증 결과 진입 — RR · TR 카드가 좌우에서 모임 0.4s */
.rp-card { animation: vb-from-left 0.4s ease both; }
.rp-card--tr { animation: vb-from-right 0.4s ease both; }
.rp-next-badge { animation: vb-fade-in 0.3s ease 0.4s both; }
@keyframes vb-from-left { from { opacity: 0; transform: translateX(-24px); } to { opacity: 1; transform: none; } }
@keyframes vb-from-right { from { opacity: 0; transform: translateX(24px); } to { opacity: 1; transform: none; } }

/* 홈 FAQ 펼침 — 답변 0.25s + 쉐브론 180° */
.faq-item__a:not([hidden]) { animation: vb-faq-open 0.25s ease both; }
@keyframes vb-faq-open {
    from { opacity: 0; max-height: 0; }
    to { opacity: 1; max-height: 600px; }
}
.faq-item__q img { transition: transform 0.25s ease; }
.faq-item__q[aria-expanded="true"] img { transform: rotate(180deg); }

/* 수정 모드 힌트 — 고른 힌트가 0.9 → 1 로 커지며 나타남 0.15s
   (스펙의 「말풍선」은 디자인에 없어 힌트 단추에 걸었습니다) */
.tf-hint.is-active, .tf-hint[aria-pressed="true"] { animation: vb-pop-in 0.15s ease both; }

/* RR 결과 · 최종 인증 결과 등장 — 칩 → 제목 → 획득 km 순 0.3s
   (숫자 카운트업은 data-countup 이 맡습니다) */
.rp-result > * { animation: vb-fade-up 0.3s ease both; }
.rp-result > *:nth-child(2) { animation-delay: 0.08s; }
.rp-result > *:nth-child(3) { animation-delay: 0.16s; }
.rp-result > *:nth-child(4) { animation-delay: 0.24s; }
@keyframes vb-fade-up { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }

/* 레벨테스트 결과 등장 — 레벨 칩 → 설명 → 강점/보완 카드 → 버튼 순 0.3s */
.lt-result > * { animation: vb-fade-up 0.3s ease both; }
.lt-result > *:nth-child(2) { animation-delay: 0.08s; }
.lt-result > *:nth-child(3) { animation-delay: 0.16s; }
.lt-result > *:nth-child(4) { animation-delay: 0.24s; }

/* 인증 상세 차수 전환 — 1 · 2 · 3차 단추를 누르면 답변만 크로스페이드 0.25s */
.cd-answers { animation: vb-fade-in 0.25s ease both; }
.main.is-round-switch { animation: none; }

/* 배지 도감 탭 · 캐러셀 — 콘텐츠 크로스페이드 0.15s + 위에서부터 60ms 순차 · 카드 밀림 0.35s · 현재 카드 확대 */
.bx-panel:not([hidden]) { animation: vb-fade-in 0.15s ease both; }
.bx-panel:not([hidden]) .bx-group { animation: vb-fade-up 0.3s ease both; }
.bx-panel .bx-group:nth-child(2) { animation-delay: 0.06s; }
.bx-panel .bx-group:nth-child(3) { animation-delay: 0.12s; }
.bx-panel .bx-group:nth-child(4) { animation-delay: 0.18s; }
.bx-panel .bx-group:nth-child(5) { animation-delay: 0.24s; }
.bx-panel .bx-group:nth-child(n+6) { animation-delay: 0.3s; }
.bx-track[data-dir="next"] .bx-card:not([hidden]) { animation: vb-slide-next 0.35s ease both; }
.bx-track[data-dir="prev"] .bx-card:not([hidden]) { animation: vb-slide-prev 0.35s ease both; }
@keyframes vb-slide-next { from { transform: translateX(40px); opacity: 0.4; } to { transform: none; opacity: 1; } }
@keyframes vb-slide-prev { from { transform: translateX(-40px); opacity: 0.4; } to { transform: none; opacity: 1; } }
.bx-card { transition: transform 0.35s ease, border-color 0.2s ease; }
.bx-card--current { transform: scale(1.04); }

/* RR 선지 고르기 — 테두리 · 면 채움 0.15s */
.rp-choice { transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease; }

/* 랜딩(PUB-01B) — 히어로는 아이브로우 → 제목 → 설명 → 버튼 80ms 간격 fade-up 0.4s,
   다른 섹션은 20% 보이면 fade-up 24px 0.5s · 안의 카드 80ms 순차 · 한 번만 (motion.js 가 is-in 과 간격을 붙임) */
[data-appear] [data-appear-item] { opacity: 0; transform: translateY(24px); transition: opacity 0.5s ease, transform 0.5s ease; }
.lb-hero[data-appear] [data-appear-item] { transform: translateY(16px); transition-duration: 0.4s; }
[data-appear] [data-appear-item].is-in { opacity: 1; transform: none; }
.lb-hero__visual, .lb-hero .lb-graphic { animation: vb-fade-in 0.4s ease 0.32s both; }

/* ───────── OS 설정에서 움직임을 줄였을 때 ───────── */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.2s !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.2s !important;
        transition-property: opacity !important;
        scroll-behavior: auto !important;
    }
    /* 이동 · 스케일은 끄고 페이드만 남깁니다 */
    .btn:hover, .btn:active,
    .b-card:hover, .rd-shortcut:hover, .rd-next:hover, .bx-card--link:hover { transform: none !important; }
    .rk .podium__card--1, .rk .podium__card--2, .rk .podium__card--3, .bx-earned__icon,
    .rp-card, .rp-card--tr, .rp-result > *, .lt-result > *, .main, .auth, .org-wrap, .info-page, .bd-main, .lt-intro, main.page,
    [class*="-modal__card"], .vb-modal__box, .rp-help, .tf-help, .bx-panel .bx-group, .vb-toast,
    .bd-wish[aria-pressed="true"] img, .tf-count.is-ok::before, .tf-hint.is-active, .tf-hint[aria-pressed="true"],
    .fr-row.is-accepted, .bx-track[data-dir] .bx-card, [data-appear-item] {
        animation-name: vb-fade-in !important;
    }
    .is-error, .input--error, input[aria-invalid="true"], textarea[aria-invalid="true"], .bx-earned__ring::after { animation: none !important; }
    .is-closing [class*="-modal__card"], .is-closing .vb-modal__box, .vb-toast.is-out { animation-name: vb-fade-out !important; }
    .bx-card--current, .lb-card:hover { transform: none !important; }
}
