/* ============================================================
   shared/replay-stage.css — 전투 리플레이 "무대" 레이아웃·연출 스킨.
   전용 페이지(ui/battle-replay.html)와 battle-log.html의 풀스크린
   오버레이(기존 화면 위 레이어 — 2026-07-10 실사용 정정: 진짜 새 창이
   아니라 화면 위 전환)가 공용한다. #stage-root/#stageBg/#stageMount
   구조를 전제하며, replay.css 다음에 링크한다.
   ============================================================ */
#stage-root { position: relative; box-sizing: border-box; height: 100%; display: flex; flex-direction: column; padding: 14px; overflow: hidden; /* 종료 워시 등 오버사이즈 자식을 무대 경계에서 클리핑 */ }
/* ── 지역 무대 배경(L0) + 하단 스크림(L0.5) — docs/battle-replay-stage-blueprint.md §6 ──
   배경은 프리로드 완료 후에만 페이드인(.stage-bg-in) — 디코드 중엔 중립 무대가 그대로 보인다.
   inset:0 금지(Chrome79 조용한 무시 실사고) — 명시 좌표. */
#stageBg {
    position: absolute; left: 0; top: 0; width: 100%; height: 100%;
    background-size: cover; background-position: center;
    opacity: 0; transition: opacity .6s ease; pointer-events: none; z-index: 0;
}
#stageBg.stage-bg-in { opacity: 1; }
/* 사진 위 자막·컨트롤 가독용 국소 스크림 — profile.html 히어로 네임바(사진 위 텍스트) 선례 원용.
   정적 그라디언트(무애니메이션)·하단 대역 한정·HUD 글래스는 라이트 유지(캐논 §3-2). 다크 글래스
   토큰(--glass-d-*)은 glass.css 미로드 페이지라 동일 목적의 rgba 정적 그라디언트로 대체. */
#stageBg::after {
    content: ""; position: absolute; left: 0; bottom: 0; width: 100%; height: 38%;
    background: linear-gradient(to top, rgba(24, 20, 16, .42), rgba(24, 20, 16, 0));
}
#stageMount { position: relative; z-index: 1; }
/* ── 탈카드 무대 — "가로 카드를 세로로 뒤집은 느낌뿐"이라는 실사용 피드백(2026-07-10)로
   반투명 카드 상자를 폐기. 전투원·바·자막이 배경 위에 직접 서고, 가독이 필요한 요소(이름·자막대·
   컨트롤)만 개별 미니 글래스 필을 얹는다. 사진 유무와 무관하게 무대는 항상 탈카드(중립 결계 포함). */
#stageMount .replay {
    background: transparent; border: none; box-shadow: none;
    padding: 0 2px; border-radius: 0;
}
/* 이름 필 — 사진 위 가독. 좌(아군)/우(적) 정렬은 기존 텍스트 흐름 그대로. */
#stageMount .cb-name {
    display: inline-block; max-width: 100%;
    background: rgba(250, 248, 245, .9); border: 1px solid rgba(33, 28, 21, .12);
    border-radius: 999px; padding: 2px 12px; margin-bottom: 6px;
    box-shadow: 0 1px 4px rgba(24, 20, 16, .18);
}
/* inline-block은 flex 컨텍스트에서 블록화돼 stretch — align-self로 내용 폭에 붙인다
   (아군 필만 풀폭으로 늘어나던 비대칭, 실기기 5차). */
#stageMount .side-player .cb-name { align-self: flex-start; }
#stageMount .side-enemy .cb-name { align-self: flex-end; }
/* 바 — 밝은 사진(하늘) 위에서 빈 바가 "흰 띠"로 씻기던 문제(2026-07-10 실사용 피드백):
   트랙을 어두운 반투명으로 바꿔 채워진 색이 튀고 빈 구간은 '트랙'으로 읽히게. 잔상(고스트)은
   어두운 트랙 위에서 보이도록 밝은 톤으로 반전. */
#stageMount .bar {
    background: rgba(33, 28, 21, .32); border-color: rgba(250, 248, 245, .42);
    box-shadow: 0 1px 5px rgba(24, 20, 16, .28);
}
#stageMount .bar-ghost { background: rgba(250, 248, 245, .45); }
/* ⚔ 대치 글리프 — 하늘 위에서 존재감이 죽던 것을 밝은 획+먹 그림자로 보강. */
#stageMount .vs {
    font-size: 30px; color: rgba(250, 248, 245, .95);
    filter: drop-shadow(0 1px 3px rgba(24, 20, 16, .55));
}
/* 자막대(턴/칩 + 캡션)와 컨트롤 — 하나의 글래스 스트립 톤으로 묶는다. */
#stageMount .replay-meta,
#stageMount .beat-caption,
#stageMount .replay-controls,
#stageMount .scrub-wrap {
    background: rgba(250, 248, 245, .82); border: 1px solid rgba(33, 28, 21, .1);
    border-radius: var(--kh-r-md); padding: 6px 10px;
}
#stageMount .replay-meta { margin-top: 2px; }
/* 자막대 — 고정 높이는 5줄 케이스(무공명+본문+부가2+'외 N건')를 계속 잘랐고(9차, PC 창은 기본
   76px라 더 심함) — auto+min으로 전환. 성장분은 초상(flex 흡수체)이 받아 잘림이 원천 소멸,
   합마다 높이가 출렁이는 것은 초상 크롭 변화로 흡수된다. */
#stageMount .beat-caption { height: auto; min-height: 76px; flex-shrink: 0; /* 판당 잠금 높이가 flex 압축에 눌려 다시 잘리지 않게 — 초상이 흡수 */ }
/* 종료 오버레이 — 탈카드로 .replay가 풀스크린이 되면서 기존 84% 워시가 무대 전체를 덮어
   결말 순간의 무대·비네트가 지워진다. 무대에선 반투명을 낮춰 배경이 결말 뒤로 계속 보이게.
   오프셋: 오버레이가 .replay(패딩 안쪽)에만 깔려 승/패 시 "안쪽 사각형만 하얘지는" 어색함
   (2026-07-10 실사용 피드백) — 페이지가 아는 패딩 상수(#stage-root 14px·#stageMount 상 12/14px·
   .replay 좌우 2px·하단 safe-area)만큼 네거티브로 늘려 화면 전체를 덮는다. */
#stageMount .end-overlay {
    background: rgba(250, 248, 245, .58); border-radius: 0;
    /* 패딩 상수 역산(-16/-28/calc…)은 표면마다 어긋났다(10차: "그냥 배경 다 덮으면 되잖아") —
       넉넉한 오프셋을 #stage-root의 overflow:hidden이 경계에서 잘라내 항상 전부 덮인다.
       ⚠️ 단 이 블리드가 #stage-root까지 닿으려면 오버레이의 positioned 조상인 무대 .replay가
       overflow를 열어야 한다(아래 #stageMount .replay 참조) — 안 그러면 .replay 안쪽에서 먼저 잘린다. */
    left: -300px; right: -300px; top: -300px; bottom: -300px;
}
@supports (-webkit-backdrop-filter: blur(2px)) or (backdrop-filter: blur(2px)) {
    #stageMount .replay-meta,
    #stageMount .beat-caption,
    #stageMount .replay-controls,
    #stageMount .scrub-wrap {
        background: rgba(250, 248, 245, .66);
        -webkit-backdrop-filter: blur(8px) saturate(130%);
        backdrop-filter: blur(8px) saturate(130%);
    }
    #stageMount .cb-name {
        -webkit-backdrop-filter: blur(8px) saturate(130%);
        backdrop-filter: blur(8px) saturate(130%);
    }
}
/* 초상 하단을 무대로 살짝 녹이는 단축 마스크 — 지원 시에만(미지원=현행 사각 프레임, 정보 손실 0). */
@supports (-webkit-mask-image: linear-gradient(#000, #000)) {
    #stage-root.stage-has-photo #stageMount .cb-portrait {
        -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 88%, rgba(0, 0, 0, .55) 100%);
        mask-image: linear-gradient(to bottom, #000 0%, #000 88%, rgba(0, 0, 0, .55) 100%);
    }
}
/* 뒤로가기 — 우상단 40px 원형 X가 대각 배치의 적 초상(우상단)과 정면충돌해 상단 패딩을
   강요하던 문제(2026-07-10 실기기 피드백). 좌상단(적 초상 반대편=하늘 여백)의 낮은 글래스
   칩으로 바꿔 무대 상단을 초상에게 돌려준다. 동작은 동일(새 창=닫기, 같은 탭=목록 복귀). */
.stage-close {
    position: absolute; top: 10px; left: 12px; z-index: 20;
    min-width: 40px; height: 32px; border-radius: 999px;
    border: 1px solid rgba(33, 28, 21, .14); background: rgba(250, 248, 245, .72);
    color: var(--kh-ink, #211c15); font-size: 17px; line-height: 1; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    padding: 0 12px;
    box-shadow: 0 1px 4px rgba(24, 20, 16, .18);
    -webkit-tap-highlight-color: transparent;
}
@supports (-webkit-backdrop-filter: blur(2px)) or (backdrop-filter: blur(2px)) {
    .stage-close { -webkit-backdrop-filter: blur(8px) saturate(130%); backdrop-filter: blur(8px) saturate(130%); }
}
.stage-close:hover { color: var(--kh-cinnabar); border-color: var(--kh-cinnabar); }
/* 공유 재생 전용 상단 컨트롤 — '뒤로' 대신 연출 효과 토글(좌)+가독협객전 홈(우). pointer-events는 자식만
   받아 사이 빈 영역은 재생을 가리지 않는다(무대 탭 스킵·클릭 통과). */
.stage-share-controls { position: absolute; top: 10px; left: 12px; right: 12px; z-index: 20;
    display: flex; align-items: center; justify-content: space-between; gap: 10px; pointer-events: none; }
.stage-share-controls > * { pointer-events: auto; }
.stage-fx-toggle, .stage-home-cta { height: 32px; border-radius: 999px; padding: 0 14px; font-size: 13px;
    font-weight: 700; font-family: inherit; line-height: 1; display: inline-flex; align-items: center;
    cursor: pointer; -webkit-tap-highlight-color: transparent; box-shadow: 0 1px 4px rgba(24, 20, 16, .18);
    border: 1px solid rgba(33, 28, 21, .14); }
.stage-fx-toggle { background: rgba(250, 248, 245, .72); color: var(--kh-ink, #211c15); }
.stage-home-cta { background: var(--kh-cinnabar); color: var(--kh-on-primary, #fff); border-color: transparent; text-decoration: none; }
@supports (-webkit-backdrop-filter: blur(2px)) or (backdrop-filter: blur(2px)) {
    .stage-fx-toggle { -webkit-backdrop-filter: blur(8px) saturate(130%); backdrop-filter: blur(8px) saturate(130%); }
}
.stage-fx-toggle:hover { color: var(--kh-cinnabar); border-color: var(--kh-cinnabar); }
.stage-home-cta:hover { filter: brightness(1.07); }
/* 무대 마운트 — 재생 엔진이 만드는 .replay를 중앙 배치. 하단 여백은 컨트롤 바가 노치 뒤로 숨지 않게. */
#stageMount {
    flex: 1 1 auto; min-height: 0; display: flex; align-items: center; justify-content: center;
    padding: 14px 0 max(10px, env(safe-area-inset-bottom, 0px));
    box-sizing: border-box;
}
/* ── 뷰포트 핏 — 세로가 짧은 기기에서 내부 스크롤이 생기던 UX(2026-07-10 피드백)를 제거.
   고정 요소(이름·바·자막대·컨트롤)는 자연 높이를 갖고, 초상이 남는 높이를 흡수(flex)한다 —
   짧은 화면일수록 초상 크롭이 깊어질 뿐 화면은 항상 한 판에 들어찬다. */
#stageMount .replay-mount { margin: 0; width: 100%; height: 100%; min-height: 0; }
#stageMount .replay {
    /* overflow:visible — 종료 오버레이(-300px 블리드)가 .replay 안쪽에서 잘려 배경 전체를 못 덮던 결함
       (2026-07-20 실사용 '결과가 stageBg가 아니라 stageMount 크기') 수정. 카드 모드용 base
       `.replay{overflow:hidden}`은 무대(탈카드)엔 불필요하고, 넘치는 것은 #stage-root의 overflow:hidden이
       최종 클립한다(레이아웃은 초상 flex 흡수로 항상 한 판에 들어차 실제 오버플로는 없음). */
    width: 100%; height: 100%; min-height: 0; overflow: visible;
    display: flex; flex-direction: column;
}
#stageMount .replay-stage { flex: 1 1 auto; min-height: 0; }
/* PC(900px+, theme.css:422 기존 브레이크포인트 재사용) — 좌우 배치 + 중앙 여백. */
@media (min-width: 900px) {
    #stageMount .replay { max-width: 860px; margin: 0 auto; }
    #stageMount .replay-stage { align-items: stretch; }
    #stageMount .combatant { flex: 1 1 0; min-height: 0; }
    /* 초상 = 데스크톱도 가변 흡수체(자막 auto 성장을 받아 내부 스크롤 방지 — 9차). 고정 비율을
       풀고 남는 높이를 채운다(크롭은 아래 공용 img 규칙). */
    #stageMount .cb-portrait { flex: 1 1 auto; min-height: 140px; height: auto; padding-top: 0; }
}
/* 초상 이미지 공용(모바일·PC) — 가변 높이 컨테이너를 확실히 채우는 절대 배치(4방향 오프셋),
   object-position 상단 편향으로 세로가 모자라도 인물 머리 우선 보존. */
@supports (aspect-ratio: 1 / 1) {
    #stageMount .cb-portrait { aspect-ratio: auto; }
}
#stageMount .cb-portrait img {
    position: absolute; left: 0; top: 0; right: 0; bottom: 0;
    width: 100%; height: 100%; object-fit: cover; object-position: 50% 24%;
}
/* 모바일(<900px) — 대각 배치: 적 플레이트 상단·아군 플레이트 하단(세로 RPG 문법). 엔진이 만드는
   .replay-stage/.combatant 마크업은 불변, flex-direction·order 재배치만(§3-1). */
@media (max-width: 899.98px) {
    /* 종전 52px=우상단 X 버튼 회피용 — 버튼이 좌상단으로 가며 적 초상에게 상단을 돌려준다. */
    #stageMount { padding-top: 12px; }
    #stageMount .replay-stage { flex-direction: column; }
    #stageMount .side-enemy { order: -1; }
    #stageMount .vs { order: 0; align-self: center; flex: 0 0 auto; }
    #stageMount .side-player { order: 1; }
    /* 대각 대치 — "풀폭 가로 띠 2장 스택=문서" 인상(2026-07-10 실기기 피드백: 둘을 동시에
       띄우는 게 문제가 아니라 마주 보지 않는 게 문제). 초상을 폭 66% 비네트로 좁혀 적=우측,
       아군=좌측 반대편에 앉힌다 — 좁힌 만큼 세로가 살아 크롭이 세로→가로로 바뀌며 얼굴이
       보존되고, 좌하↔우상 대각선이 "마주 봄"을 만든다. 바(정보)는 풀폭 유지. */
    #stageMount .combatant { flex: 1 1 0; min-height: 0; }
    /* .combatant는 flex 컬럼(replay.css) — 높이를 제약하면 자식 전부가 비례 압축돼
       이름 필이 바 밑에 깔린다(2026-07-10 실기기 4차 피드백의 겹침 버그). 정보 요소는
       압축 금지, 초상만 남는 높이의 흡수체. */
    #stageMount .combatant .cb-name,
    #stageMount .combatant .bar { flex-shrink: 0; }
    #stageMount .cb-portrait {
        flex: 1 1 auto; min-height: 72px; height: auto; padding-top: 0;
        width: 66%;
    }
    #stageMount .side-enemy .cb-portrait { margin-left: auto; }
    #stageMount .side-player .cb-portrait { margin-right: auto; }
    @supports (aspect-ratio: 1 / 1) {
        #stageMount .cb-portrait { aspect-ratio: auto; }
    }
    /* 가변 높이 컨테이너에서 이미지가 확실히 채우도록 절대 배치(4방향 오프셋 — inset 단축 금지).
       object-position 상단 편향 = 세로가 모자랄 때도 인물 머리를 우선 보존. */
    #stageMount .cb-portrait img {
        position: absolute; left: 0; top: 0; right: 0; bottom: 0;
        width: 100%; height: 100%; object-fit: cover; object-position: 50% 24%;
    }
    /* 자막대 — 인라인 카드 기준 고정 76px(replay.css)이 무공명 줄 낀 비트에서 4줄째를 자른다
       (실기기 스크린샷 확인). 무대는 세로 여유가 있으니 고정 리듬을 유지한 채 높이만 확장. */
}
/* 세로 높이 사다리 — 카톡 인앱은 URL바·하단바가 뷰포트를 깎아(~660px) 일반(812)과 컴팩트(640)
   사이 사각지대에서 고정 예산이 넘쳤다(실기기 7차: 내공 바가 칩 줄에 깔림+스크롤). 중간 단 추가. */
@media (max-width: 899.98px) and (max-height: 760px) {
    #stageMount .cb-portrait { min-height: 60px; }
}
@media (max-width: 899.98px) and (max-height: 640px) {
    #stageMount .cb-portrait { min-height: 52px; }
}

/* ── 풀스크린 오버레이(battle-log 위 레이어) ──
   z=55: 탭바(40)·상단바(41)·공지(46) 위, 잉크 캔버스(75)·분석 모달(80) 아래 —
   전투 이펙트와 분석 모달이 무대 위에 정상으로 뜬다. */
.stage-overlay {
    position: fixed; left: 0; top: 0; right: 0; bottom: 0; z-index: 55;
    background: var(--kh-paper, #faf8f5);
    animation: khPlayerEnter .24s var(--kh-ease-out) both;
}
.stage-overlay #stage-root { height: 100%; }
/* PC(900px+)는 모니터 전체 풀스크린이 과함(내용은 중앙뿐·뒤로 칩만 저 멀리 — 실기기 7차 피드백)
   — 딤 백드롭 위 중앙 "창"으로: 원래 의도('새 창처럼')에 부합, 뒤로 칩도 창 안 좌상단에 붙는다.
   딤 영역 클릭 = 닫기(battle-log 오버레이 JS). */
@media (min-width: 900px) {
    .stage-overlay {
        background: rgba(24, 20, 16, .55);
        display: flex; align-items: center; justify-content: center;
        padding: 28px;
    }
    .stage-overlay #stage-root {
        position: relative; width: 920px; max-width: 94vw; height: 100%; max-height: 860px;
        border-radius: 16px; overflow: hidden;
        background: var(--kh-paper, #faf8f5);
        box-shadow: 0 24px 80px rgba(0, 0, 0, .42);
    }
}
/* 뒤 목록 스크롤 잠금 — iOS 웹뷰는 body overflow:hidden을 무시(러버밴드로 뒤가 스크롤돼
   '우측 스크롤+이상 반응', 실기기 7차) → position:fixed 기법. top은 JS가 -scrollY로 세팅하고
   닫을 때 scrollTo로 복원한다. */
body.stage-overlay-open { position: fixed; left: 0; right: 0; overflow: hidden; }
@media (prefers-reduced-motion: reduce) { .stage-overlay { animation: none; } }

/* ── 비디오 플레이어식 컨트롤(실기기 8차: "이전 합/재생/다음 합/1배 텍스트가 어색") ──
   라벨은 SR 전용으로 감추고 아이콘 원형 버튼, 배속만 텍스트 칩(x1·x2·x3). 카드 인라인은 불변. */
#stageMount .replay-controls { display: flex; align-items: center; justify-content: center; gap: 14px; }
#stageMount .replay-controls .ctl-label {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0); white-space: nowrap; border: 0; padding: 0; margin: -1px;
}
#stageMount .replay-controls .ctl-ic { display: block; width: 22px; height: 22px; }
#stageMount .replay-controls .ctrl {
    flex: 0 0 auto; /* replay.css의 flex:1 상속이 버튼을 풀폭 필로 늘리던 것(9차 PC·모바일 실측) */
    width: 44px; height: 40px; padding: 0; border-radius: 999px;
    display: flex; align-items: center; justify-content: center;
}
#stageMount .replay-controls .ctrl.play { width: 54px; height: 44px; }
#stageMount .replay-controls .ctrl.speed { width: auto; min-width: 48px; padding: 0 14px; font-weight: 700; }
#stageMount .replay-controls .ctrl.play .ic-pause { display: none; }
#stageMount .replay-controls .ctrl.play.playing .ic-play { display: none; }
#stageMount .replay-controls .ctrl.play.playing .ic-pause { display: block; }

/* ── 종료 상태 — 반투명 워시 아래 글래스 스트립이 밝은 블록으로 비쳐 얼룩덜룩(9차). 결과가 뜨면
   무대 HUD를 함께 가라앉혀 워시가 균일하게 읽히게 한다(다시 보기 시 showEnd(false)가 복원). */
.stage-mode.stage-ended .replay-stage,
.stage-mode.stage-ended .replay-meta,
.stage-mode.stage-ended .beat-caption,
.stage-mode.stage-ended .scrub-wrap,
.stage-mode.stage-ended .replay-controls {
    opacity: .22; transition: opacity .3s ease;
}
@media (prefers-reduced-motion: reduce) {
    .stage-mode.stage-ended .replay-stage,
    .stage-mode.stage-ended .replay-meta,
    .stage-mode.stage-ended .beat-caption,
    .stage-mode.stage-ended .scrub-wrap,
    .stage-mode.stage-ended .replay-controls { transition: none; }
}

/* ── 스크러버+컨트롤 = 한 장의 패널(실기기 10차: "분리돼 있던데 합치는 게 낫겠다") —
   위(스크러버)·아래(버튼)를 라운드 연결하고 사이 여백·중복 테두리를 지운다. */
#stageMount .scrub-wrap {
    border-radius: var(--kh-r-md) var(--kh-r-md) 0 0;
    border-bottom: none; margin-bottom: 0; padding-bottom: 2px;
}
#stageMount .replay-controls {
    border-radius: 0 0 var(--kh-r-md) var(--kh-r-md);
    border-top: none; margin-top: 0; padding-top: 2px;
}

/* ── 무공 컷인(P2) — 발동 비트에서 400×400 아트 카드가 중앙 상단에 정착했다 스러진다.
   등장 200ms 스케일(1.1→1)+페이드(이동 없음)·홀드 후 자연 페이드(전체 .95s, 다음 render가 제거).
   z=6: 대전 자막(7) 아래·초상 위. reduced-motion/저사양은 JS가 생성 자체를 생략. */
.stage-mode .skill-cutin {
    position: absolute; left: 50%; top: 32%; /* 하늘 갭(⚔ 존) 중심 — 24%는 적 바 줄과 겹침(E2E 실측) */
    width: clamp(96px, 26vw, 148px); height: clamp(96px, 26vw, 148px);
    margin-left: calc(-1 * clamp(96px, 26vw, 148px) / 2);
    z-index: 6; pointer-events: none;
    border-radius: 14px; overflow: hidden;
    border: 2px solid var(--kh-gold, #c9a227);
    box-shadow: 0 6px 24px rgba(24, 20, 16, .45), 0 0 0 1px rgba(250, 248, 245, .5);
    animation: khCutin .95s var(--kh-ease-out) both;
}
/* 진영 구분(11차) — 아군=옥·금 테두리+좌측 슬라이드, 적=진홍 테두리+우측 슬라이드. 색+방향+배지 삼중 부호화. */
.stage-mode .skill-cutin.cutin-ally {
    border-color: var(--kh-jade, #2f6f5e);
    box-shadow: 0 6px 24px rgba(24, 20, 16, .5), 0 0 14px rgba(47, 111, 94, .55), 0 0 0 1px rgba(201, 162, 39, .55);
    animation: khCutinAlly .95s var(--kh-ease-out) both;
}
.stage-mode .skill-cutin.cutin-enemy {
    border-color: #a02c2c;
    box-shadow: 0 6px 24px rgba(24, 20, 16, .5), 0 0 14px rgba(160, 44, 44, .6), 0 0 0 1px rgba(212, 87, 74, .45);
    animation: khCutinEnemy .95s var(--kh-ease-out) both;
}
.stage-mode .skill-cutin .cutin-badge {
    position: absolute; left: 6px; top: 6px;
    width: 22px; height: 22px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    color: #faf8f5;
    box-shadow: 0 1px 4px rgba(24, 20, 16, .4);
}
.stage-mode .skill-cutin.cutin-ally .cutin-badge { background: rgba(47, 111, 94, .92); }
.stage-mode .skill-cutin.cutin-enemy .cutin-badge { background: rgba(160, 44, 44, .92); }
.stage-mode .skill-cutin .cutin-badge svg { width: 13px; height: 13px; display: block; }
.stage-mode .skill-cutin img { width: 100%; height: 100%; object-fit: cover; display: block; }
@keyframes khCutin {
    0% { opacity: 0; transform: scale(1.1); }
    18% { opacity: 1; transform: scale(1); }
    72% { opacity: 1; transform: scale(1); }
    100% { opacity: 0; transform: scale(1); }
}
/* 진영별 진입 — 방향·기울기 펀치로 "누구의 기술"인지 몸으로 읽힌다(밋밋함 해소). */
@keyframes khCutinAlly {
    0% { opacity: 0; transform: translateX(-34px) rotate(-5deg) scale(1.12); }
    16% { opacity: 1; transform: translateX(3px) rotate(1deg) scale(.99); }
    26% { transform: translateX(0) rotate(0deg) scale(1); }
    72% { opacity: 1; transform: translateX(0) rotate(0deg) scale(1); }
    100% { opacity: 0; transform: translateX(0) rotate(0deg) scale(1.02); }
}
@keyframes khCutinEnemy {
    0% { opacity: 0; transform: translateX(34px) rotate(5deg) scale(1.12); }
    16% { opacity: 1; transform: translateX(-3px) rotate(-1deg) scale(.99); }
    26% { transform: translateX(0) rotate(0deg) scale(1); }
    72% { opacity: 1; transform: translateX(0) rotate(0deg) scale(1); }
    100% { opacity: 0; transform: translateX(0) rotate(0deg) scale(1.02); }
}
@media (prefers-reduced-motion: reduce) { .stage-mode .skill-cutin { display: none; } }
