/* ── 연출 레이어 v1 (2026-11-01) ─────────────────────────────────
   index.html 위에 얹는 전환·등장 체계. html[data-t] 로 전환 변형을 고른다.
   data-t = rise(크로스페이드+올라옴, 추천) | fade(크로스페이드만) | zoom(줌 딥)
   토큰: --mo-out 나가는 시간 / --mo-d0 첫 요소 지연 / --mo-gap 요소 간격 / --mo-rise 올라오는 거리
   끄기: html 에 data-mo 가 없으면 아무 것도 하지 않는다 (prefers-reduced-motion 도 동일).
───────────────────────────────────────────────────────────────── */
html[data-mo]{--mo-out:.6s;--mo-txt:.28s;--mo-in:.55s;--mo-d0:.4s;--mo-gap:.085s;--mo-rise:18px;--mo-ease:cubic-bezier(.22,.8,.26,1)}
html[data-t="fade"]{--mo-rise:0px;--mo-gap:.07s}
html[data-t="zoom"]{--mo-rise:12px;--mo-out:.5s}

/* 나가는 장: 위에 겹쳐 두고 사라진다 (아래 장은 바로 보이므로 배경이 비치지 않음) */
/* 떠나는 장은 .on 을 700ms 더 가진다(본판 자체 애니메이션이 초기 상태로 튀지 않게). 그래서 나가는 연출은 !important 로 .on 규칙을 덮는다 */
html[data-mo] section.leaving{display:block!important;z-index:3!important;pointer-events:none;animation:moOut var(--mo-out) ease-in both!important}
html[data-t="zoom"] section.leaving{animation-name:moOutZoom!important}
html[data-mo] section.on{z-index:2}
@keyframes moOut{to{opacity:0}}
/* 나가는 장의 글은 배경보다 먼저 위로 빠진다 → 새 글과 겹치지 않음 */
html[data-mo] section.leaving .mv,html[data-mo] section.leaving .ttl .s,html[data-mo] section.leaving .ttl .b{animation:moOutText var(--mo-txt) ease both!important} /* ease-in 은 처음 .15s 가 멈춘 듯 보였음 */
html[data-mo] section.leaving.dv h2{animation:moOutClip var(--mo-txt) ease-in both!important}
html[data-mo] section.leaving .ttl.mv{animation:none!important;opacity:1!important}
html[data-mo] section.leaving .cnt{opacity:1!important}
@keyframes moOutText{from{opacity:1;transform:none}to{opacity:0;transform:translateY(-14px)}}
@keyframes moOutClip{from{opacity:1;clip-path:inset(-20% 0 -10% 0);transform:none}to{opacity:0;clip-path:inset(-20% 0 -10% 0);transform:translateY(-14px)}}
@keyframes moOutZoom{to{opacity:0;transform:scale(1.035)}}

/* 들어오는 장: 본문 블록이 순서대로 올라온다 */
html[data-mo] section.on .mv{opacity:0;animation:moRise var(--mo-in) var(--mo-ease) calc(var(--mo-d0) + var(--k,0)*var(--mo-gap)) both}
html[data-t="zoom"] section.on .mv{animation-name:moZoomIn}
@keyframes moRise{from{opacity:0;transform:translateY(var(--mo-rise))}to{opacity:1;transform:none}}
@keyframes moZoomIn{from{opacity:0;transform:translateY(var(--mo-rise)) scale(.975)}to{opacity:1;transform:none}}

/* 제목: 두 줄이 따로 올라오고, 강조어(.g)는 그라데이션이 뒤늦게 켜진다 */
html[data-mo] section.on .ttl .s,html[data-mo] section.on .ttl .b{display:block;opacity:0;animation:moRise .6s var(--mo-ease) both}
html[data-mo] section.on .ttl .s{animation-delay:calc(var(--mo-d0) + .02s)}
html[data-mo] section.on .ttl .b{animation-delay:calc(var(--mo-d0) + .12s)}
html[data-mo] section.on .ttl.mv{animation:none;opacity:1}

/* 사진 장: 천천히 밀려 들어오는 배경(켄 번즈) */
html[data-mo] section.ph.on>img:not(.logo){animation:moKen 16s linear both}
@keyframes moKen{from{transform:scale(1.06)}to{transform:scale(1)}}
html[data-mo] section.ph.on .sh{animation:moFadeIn 1.2s ease-out both}
@keyframes moFadeIn{from{opacity:0}to{opacity:1}}

/* 어두운 디바이더: 큰 제목은 아래서 가려진 채 올라오고, 워터마크 심볼은 떠오른다 */
html[data-mo] section.dv.on h2,html[data-mo] section.dv.on h2.mv{clip-path:inset(0 0 100% 0);animation:moClip .8s cubic-bezier(.2,.75,.2,1) calc(var(--mo-d0) + .1s) both}
@keyframes moClip{from{opacity:1;clip-path:inset(0 0 100% 0);transform:translateY(40px)}to{opacity:1;clip-path:inset(-20% 0 -10% 0);transform:none}}
html[data-mo] section.dv.on .wm{animation:moWm 1.6s var(--mo-ease) both}
@keyframes moWm{from{opacity:0;transform:translateY(60px) rotate(-6deg)}to{transform:none}} /* 끝 투명도는 본판 .wm(.07) 그대로 */
html[data-mo] section.dv.on .prog{animation:moFadeIn .8s .5s both}

/* 숫자 카운트업 중에는 폭이 흔들리지 않게 */
html[data-mo] .cnt{font-variant-numeric:tabular-nums}

/* 문제 카드(29~32) 아이콘 한 동작씩 — 공통 등장이 끝난 뒤 시작 */
html[data-mo] section.pa1.on .fq{--fqd:1.1s}
/* 29 기록이 끊기는 순간: 붉은 끊김 표시가 튀어나오고 양쪽 상자가 살짝 벌어진다 */
html[data-mo] section.pa1.on .fq g[stroke="#D4605E"]{transform-box:fill-box;transform-origin:center;animation:moSnap .5s cubic-bezier(.3,1.6,.4,1) var(--fqd) both}
@keyframes moSnap{from{opacity:0;transform:scale(.2) rotate(-30deg)}to{opacity:1;transform:none}}
/* 30 자석이 주사위 쪽으로 당겨 올라가고 점선이 떨린다 */
html[data-mo] section.pa1.on .fq path[stroke-width="14"]{animation:moPull 1.4s ease-in-out var(--fqd) infinite alternate}
@keyframes moPull{from{transform:translateY(0)}to{transform:translateY(-10px)}}
html[data-mo] section.pa1.on .fq path[stroke-width="6"][stroke="#D4605E"]{animation:moTremble .25s ease-in-out calc(var(--fqd) + .2s) infinite alternate}
@keyframes moTremble{from{opacity:.5;transform:translateY(0)}to{opacity:1;transform:translateY(-3px)}}
/* 31 점선 티켓이 깜박이며 "비어 있음"을 말하고, 금화가 하나씩 튀어오른다 */
html[data-mo] section.pa1.on .fq rect[stroke-dasharray]{animation:moBlink 1.8s ease-in-out var(--fqd) infinite}
@keyframes moBlink{0%,100%{opacity:1}50%{opacity:.35}}
html[data-mo] section.pa1.on .fq g[stroke="#fff"] circle{transform-box:fill-box;transform-origin:center bottom;animation:moCoin .6s cubic-bezier(.3,1.5,.5,1) both}
html[data-mo] section.pa1.on .fq g[stroke="#fff"] circle:nth-child(1){animation-delay:var(--fqd)}
html[data-mo] section.pa1.on .fq g[stroke="#fff"] circle:nth-child(2){animation-delay:calc(var(--fqd) + .12s)}
html[data-mo] section.pa1.on .fq g[stroke="#fff"] circle:nth-child(3){animation-delay:calc(var(--fqd) + .24s)}
@keyframes moCoin{from{opacity:0;transform:translateY(-26px) scale(.6)}to{opacity:1;transform:none}}
/* 32 연필이 붉은 줄을 긋는다 */
html[data-mo] section.pa1.on .fq path[stroke="#D4605E"][stroke-width="10"]{stroke-dasharray:70;stroke-dashoffset:70;animation:moDrawLine .7s ease-out calc(var(--fqd) + .15s) both}
@keyframes moDrawLine{to{stroke-dashoffset:0}}
html[data-mo] section.pa1.on .fq g[transform^="translate(378"]{animation:moPencil .7s ease-out calc(var(--fqd) + .15s) both}
@keyframes moPencil{from{transform:translate(316px,84px) rotate(-42deg)}to{transform:translate(378px,84px) rotate(-42deg)}}

@media (prefers-reduced-motion:reduce){
  html[data-mo] section.on .mv,html[data-mo] section.on .ttl .s,html[data-mo] section.on .ttl .b,html[data-mo] section.dv.on h2,html[data-mo] section.dv.on .wm{animation:none!important;opacity:1!important;clip-path:none!important}
  html[data-mo] section.leaving{display:none!important}
}

/* ══════════════════════════════════════════════════════════════
   장별 안무 v1 (2026-11-01) — A급: 내용이 곧 움직임인 장
   시간 기준: 장 진입 0s, 제목 .5s~, 핵심 그림 .9s~, 보조 카드는 그림이 말한 뒤
   ══════════════════════════════════════════════════════════════ */

/* ── 4장 공책 1,000권: 거래 한 건이 들어오면 첫 사람(강조 점)에서 파동이 퍼져 1,000권이 차례로 맞춰진다 ── */
html[data-mo] .s4.on .grid i{animation:moWave 4.2s calc(1.2s + var(--w,0)*1.5s) ease-out infinite;will-change:transform}
html[data-mo] .s4.on .grid i:first-child{animation:moPulse 4.2s 1.1s ease-out infinite}
@keyframes moWave{0%,4%{background:#D7DCE6;transform:scale(1)}9%{background:#82549d;transform:scale(1.45)}22%{background:#AEB6CC;transform:scale(1)}100%{background:#AEB6CC;transform:scale(1)}}
@keyframes moPulse{0%{box-shadow:0 0 0 3px #fff,0 0 0 5px var(--g2),0 0 0 5px rgba(130,84,157,.6)}6%{transform:scale(1.5)}18%{box-shadow:0 0 0 3px #fff,0 0 0 5px var(--g2),0 0 0 26px rgba(130,84,157,0);transform:scale(1)}100%{box-shadow:0 0 0 3px #fff,0 0 0 5px var(--g2),0 0 0 26px rgba(130,84,157,0);transform:scale(1)}}
/* 보조 카드는 파동이 끝에 닿은 뒤 */
html[data-mo] .s4.on .gridc p.mv{animation-delay:1.3s}
html[data-mo] .s4.on .col .card.mv:nth-child(1){animation-delay:2.7s}
html[data-mo] .s4.on .col .card.mv:nth-child(2){animation-delay:3.3s}

/* ── 13장 머클: ① 잎 4개 → ② 둘씩 묶어 올라가 루트 → ③ 잎 하나가 손대지면 그 경로만 붉게 타고 올라가 루트가 바뀐다 ── */
html[data-mo] .m1 .fgL .dif path,html[data-mo] .m1 .fgL circle[fill="#D4605E"],html[data-mo] .m1 .fgL circle[stroke="#D4605E"]{opacity:0}
html[data-mo] .m1.on .fgL circle{animation:kPop .5s cubic-bezier(.2,.8,.2,1) forwards}
html[data-mo] .m1.on .fgL circle[cx="70"]{animation-delay:.7s}html[data-mo] .m1.on .fgL circle[cx="170"]{animation-delay:.8s}html[data-mo] .m1.on .fgL circle[cx="270"]{animation-delay:.9s}html[data-mo] .m1.on .fgL circle[cx="370"][fill="#C9CFDD"]{animation-delay:1s}
html[data-mo] .m1.on .fgL circle[cy="80"][fill="#C9CFDD"]{animation-delay:1.8s}
html[data-mo] .m1.on .fgL circle[cy="30"][fill^="url"]{animation-delay:2.5s}
html[data-mo] .m1.on .fgL g:not(.dif) path{animation:kDraw .45s ease-out forwards}
html[data-mo] .m1.on .fgL g:not(.dif) path:nth-of-type(1){animation-delay:1.4s}html[data-mo] .m1.on .fgL g:not(.dif) path:nth-of-type(2){animation-delay:1.48s}html[data-mo] .m1.on .fgL g:not(.dif) path:nth-of-type(3){animation-delay:1.56s}html[data-mo] .m1.on .fgL g:not(.dif) path:nth-of-type(4){animation-delay:1.64s}
html[data-mo] .m1.on .fgL g:not(.dif) path:nth-of-type(5),html[data-mo] .m1.on .fgL g:not(.dif) path:nth-of-type(6){animation-delay:2.15s}
/* ③ 손댐 */
html[data-mo] .m1.on .fgL circle[fill="#D4605E"]{animation:moTamper .7s cubic-bezier(.2,.9,.3,1.4) 3.3s forwards}
@keyframes moTamper{0%{opacity:0;transform:scale(.2)}35%{opacity:1;transform:scale(1.9)}100%{opacity:1;transform:scale(1)}}
html[data-mo] .m1.on .fgL .dif path{stroke-dasharray:120;stroke-dashoffset:120;opacity:1;animation:kDraw .4s ease-out forwards}
html[data-mo] .m1.on .fgL .dif path:nth-of-type(1){animation-delay:3.7s}
html[data-mo] .m1.on .fgL .dif path:nth-of-type(2){animation-delay:4.25s}
html[data-mo] .m1.on .fgL circle[cy="80"][stroke="#D4605E"]{animation:moTamper .6s cubic-bezier(.2,.9,.3,1.4) 4.05s forwards}
html[data-mo] .m1.on .fgL circle.dif{animation:moTamper .6s cubic-bezier(.2,.9,.3,1.4) 4.6s forwards,moSpin 14s 5.2s linear infinite}
@keyframes moSpin{to{transform:rotate(360deg)}}
html[data-mo] .m1.on .fgL circle[cy="30"][fill^="url"]{animation:kPop .5s cubic-bezier(.2,.8,.2,1) 2.5s forwards,moRootShake .5s 4.6s ease-in-out}
@keyframes moRootShake{0%,100%{transform:translateX(0)}20%{transform:translateX(-4px)}40%{transform:translateX(4px)}60%{transform:translateX(-3px)}80%{transform:translateX(2px)}}
/* 단계 글은 그림과 같은 박자 */
html[data-mo] .m1.on .steps>div.mv:nth-child(1){animation-delay:.7s}
html[data-mo] .m1.on .steps>div.mv:nth-child(2){animation-delay:1.5s}
html[data-mo] .m1.on .steps>div.mv:nth-child(3){animation-delay:3.3s}

/* ── 19장 차트: 선이 2022→2026 을 x 등속으로 그려지고(가파른 구간에서 펜이 빨라짐), 누적 숫자는 선 끝의 실제 값을 따라간다 (JS chart19) ── */
html[data-mo] .s13c .chart svg path[stroke="url(#cl)"]{stroke-dasharray:none;stroke-dashoffset:0}
html[data-mo] .s13c.on .chart svg path[stroke="url(#cl)"],html[data-mo] .s13c.on .chart svg path[fill="url(#ca)"],html[data-mo] .s13c.on .chart svg circle,html[data-mo] .s13c.on .chart svg rect,html[data-mo] .s13c.on .chart svg rect+text{animation:none}
html[data-mo] .s13c .chart svg text.yr[text-anchor="middle"]{opacity:0}
html[data-mo] .s13c .ns>div:first-child{--cnt-mode:chart}
html[data-mo] .s13c .ns>div:nth-child(2){--cnt-delay:.9s;--cnt-dur:3.1s;--cnt-ease:in}
html[data-mo] .s13c .ns>div:nth-child(3){--cnt-delay:.9s;--cnt-dur:3.1s;--cnt-ease:linear}

/* ── 20장 주기: 59.5초 가 차오르고 블록 10개가 60초 박자로 켜진다 · 오른쪽은 띠가 거의 전부 차고 끝에 붉은 14가 톡 찍힌다 ── */
html[data-mo] .s16 .l{--cnt-delay:.8s;--cnt-dur:1.6s}
html[data-mo] .s16 .r{--cnt-delay:1s;--cnt-dur:1.9s;--cnt-ease:in}
html[data-mo] .s16.on .deco .nd{animation-duration:.3s}
html[data-mo] .s16.on .deco .nd:nth-child(1){animation-delay:.9s}html[data-mo] .s16.on .deco .nd:nth-child(2){animation-delay:1.04s}html[data-mo] .s16.on .deco .nd:nth-child(3){animation-delay:1.18s}html[data-mo] .s16.on .deco .nd:nth-child(4){animation-delay:1.32s}html[data-mo] .s16.on .deco .nd:nth-child(5){animation-delay:1.46s}html[data-mo] .s16.on .deco .nd:nth-child(6){animation-delay:1.6s}html[data-mo] .s16.on .deco .nd:nth-child(7){animation-delay:1.74s}html[data-mo] .s16.on .deco .nd:nth-child(8){animation-delay:1.88s}html[data-mo] .s16.on .deco .nd:nth-child(9){animation-delay:2.02s}html[data-mo] .s16.on .deco .nd:nth-child(10){animation-delay:2.16s}
html[data-mo] .s16.on .deco .nd:nth-child(10){animation-name:kFade,moLock}
@keyframes moLock{0%,70%{box-shadow:0 0 0 0 rgba(130,84,157,0)}80%{box-shadow:0 0 0 10px rgba(130,84,157,.35)}100%{box-shadow:0 0 0 16px rgba(130,84,157,0)}}
html[data-mo] .s16.on .l svg circle{animation-delay:1s}
html[data-mo] .s16.on .l svg circle+text{animation-delay:2.3s}
html[data-mo] .s16.on .ratio .in{transform-origin:left center;animation:moGrowX 1.9s cubic-bezier(.3,.6,.2,1) 1s both}
@keyframes moGrowX{from{transform:scaleX(0)}to{transform:scaleX(1)}}
html[data-mo] .s16.on .ratio .in b,html[data-mo] .s16.on .ratio .in span{animation:moFadeIn .4s 2.6s both}
html[data-mo] .s16.on .ratio .out{animation:moPopX .55s cubic-bezier(.3,1.5,.5,1) 2.9s both}
@keyframes moPopX{from{opacity:0;transform:translateX(36px)}to{opacity:1;transform:none}}
html[data-mo] .s16.on .ratio .out b{display:inline-block;animation:moTick .5s 3.4s ease-in-out}
@keyframes moTick{0%,100%{transform:scale(1)}30%{transform:scale(1.35)}}
html[data-mo] .s16.on .r p.mv{animation-delay:3.6s}

/* ══ 안무 1회차 다듬기 (2026-11-01 오후) ══ */
/* 이징에 성격 주기: 제목은 길게 미끄러져 멈추고(expo), 카드는 살짝 넘쳤다 자리잡고, 팝은 튄다 */
html[data-mo]{--mo-ease-ttl:cubic-bezier(.16,1,.3,1);--mo-ease-card:cubic-bezier(.2,.9,.25,1.04)}
html[data-mo] section.on .ttl .s,html[data-mo] section.on .ttl .b{animation-timing-function:var(--mo-ease-ttl);animation-duration:.8s}
html[data-mo] section.on .card.mv{animation-timing-function:var(--mo-ease-card);animation-duration:.65s}
/* 19장: 숫자는 선이 출발할 때 같이 나타난다 */
html[data-mo] .cnt{transition:opacity .4s}
html[data-mo] .s13c .chart svg .mo-live{opacity:0}
/* 4장: 파동은 두 번 치고 고요해진다 · 끝에 "1,000권 일치" 확인 표시 */
html[data-mo] .s4.on .grid i{animation-iteration-count:2}
html[data-mo] .s4.on .grid i:first-child{animation-iteration-count:2}
html[data-mo] .mo-ok{display:inline-flex;align-items:center;gap:8px;margin-left:auto;padding:6px 16px 6px 12px;border-radius:999px;background:linear-gradient(90deg,#4a7199,#82549d);color:#fff;font-size:22px;font-weight:700;opacity:0;transform:scale(.6)}
html[data-mo] .mo-ok::before{content:"";width:12px;height:7px;border-left:3px solid #fff;border-bottom:3px solid #fff;transform:rotate(-45deg) translateY(-2px)}
html[data-mo] .s4.on .mo-ok{animation:moOk .55s cubic-bezier(.3,1.5,.5,1) 3.4s both}
@keyframes moOk{from{opacity:0;transform:scale(.6)}to{opacity:1;transform:none}}
/* 13장: 루트 옆 해시가 손댐 뒤 붉게 바뀐다 */
html[data-mo] .m1 .fgL .mo-hash{font-size:13px;font-weight:700;fill:#6B7489;opacity:0;letter-spacing:.02em}
html[data-mo] .m1 .fgL .mo-hash.b{fill:#D4605E}
html[data-mo] .m1.on .fgL .mo-hash.a{animation:moFadeIn .4s 2.7s both,moFadeOut .25s 4.6s forwards}
html[data-mo] .m1.on .fgL .mo-hash.b{animation:moTamper .5s cubic-bezier(.2,.9,.3,1.3) 4.7s forwards}
@keyframes moFadeOut{to{opacity:0}}
/* 매직 무브로 들어온 장(mo-linked): 빈 흰 카드가 1.0s 에 자리잡은 뒤 평소 타임라인을 +.8s 밀어 그대로 재생한다 (Teo: "배경이 나온 뒤 나머지 이어서") */
html[data-mo] section.mo-linked.on{--mo-d0:1s}
html[data-mo] .m1.mo-linked.on .fgL circle[cx="70"]{animation-delay:1.5s!important}html[data-mo] .m1.mo-linked.on .fgL circle[cx="170"]{animation-delay:1.6s!important}html[data-mo] .m1.mo-linked.on .fgL circle[cx="270"]{animation-delay:1.7s!important}html[data-mo] .m1.mo-linked.on .fgL circle[cx="370"][fill="#C9CFDD"]{animation-delay:1.8s!important}
html[data-mo] .m1.mo-linked.on .fgL circle[cy="80"][fill="#C9CFDD"]{animation-delay:2.6s!important}
html[data-mo] .m1.mo-linked.on .fgL g:not(.dif) path:nth-of-type(1){animation-delay:2.2s!important}html[data-mo] .m1.mo-linked.on .fgL g:not(.dif) path:nth-of-type(2){animation-delay:2.28s!important}html[data-mo] .m1.mo-linked.on .fgL g:not(.dif) path:nth-of-type(3){animation-delay:2.36s!important}html[data-mo] .m1.mo-linked.on .fgL g:not(.dif) path:nth-of-type(4){animation-delay:2.44s!important}
html[data-mo] .m1.mo-linked.on .fgL g:not(.dif) path:nth-of-type(5),html[data-mo] .m1.mo-linked.on .fgL g:not(.dif) path:nth-of-type(6){animation-delay:2.95s!important}
html[data-mo] .m1.mo-linked.on .fgL circle[fill="#D4605E"]{animation-delay:4.1s!important}
html[data-mo] .m1.mo-linked.on .fgL .dif path:nth-of-type(1){animation-delay:4.5s!important}
html[data-mo] .m1.mo-linked.on .fgL .dif path:nth-of-type(2){animation-delay:5.05s!important}
html[data-mo] .m1.mo-linked.on .fgL circle[cy="80"][stroke="#D4605E"]{animation-delay:4.85s!important}
html[data-mo] .m1.mo-linked.on .fgL circle.dif{animation-delay:5.4s,6s!important}
html[data-mo] .m1.mo-linked.on .fgL circle[cy="30"][fill^="url"]{animation-delay:3.3s,5.4s!important}
html[data-mo] .m1.mo-linked.on .fgL .mo-hash.a{animation-delay:3.5s,5.4s!important}
html[data-mo] .m1.mo-linked.on .fgL .mo-hash.b{animation-delay:5.5s!important}
html[data-mo] .m1.mo-linked.on .steps>div.mv:nth-child(1){animation-delay:1.5s}
html[data-mo] .m1.mo-linked.on .steps>div.mv:nth-child(2){animation-delay:2.3s}
html[data-mo] .m1.mo-linked.on .steps>div.mv:nth-child(3){animation-delay:4.1s}
/* 20장 눈금자: 60초 기준선이 먼저 서고, 실측 점이 미끄러져 와 59.5 에 붙는다 */
html[data-mo] .s16 .l svg path[stroke-dasharray]{opacity:0}
html[data-mo] .s16.on .l svg path[stroke-dasharray]{animation:moFadeIn .4s 1s both}
html[data-mo] .s16 .l svg text[y="-4"]{opacity:0}
html[data-mo] .s16.on .l svg text[y="-4"]{animation:moFadeIn .4s 1.1s both}
html[data-mo] .s16.on .l svg circle{animation-delay:1.4s;animation-duration:1.1s;animation-timing-function:cubic-bezier(.2,.9,.25,1.08)}
html[data-mo] .s16.on .l svg circle+text{animation:moOk .5s cubic-bezier(.3,1.5,.5,1) 2.5s both;transform-box:fill-box;transform-origin:center}

/* ══ 연속 전환(매직 무브): 12장 카드 → 13·14·15장 그림으로 확대 ══ */
html[data-mo] .mo-ghost{position:absolute;z-index:6;pointer-events:none;overflow:visible}
html[data-mo] .mo-ghost>.card{position:absolute;inset:0;width:100%!important;height:100%!important;margin:0!important;padding:0!important;background:var(--card);border-radius:28px;box-shadow:var(--shadow)} /* 바깥 상자가 장 클래스, 안쪽이 .card (글 규칙이 먹게) */
html[data-mo] .mo-ghost svg{position:absolute;margin:0;max-width:none;max-height:none} /* 출발 장의 .fg{max-width:440px} 가 유령 svg 의 확대를 막았었음 */
html[data-mo] .mo-ghost .tx{position:absolute;margin:0}
html[data-mo] .mo-hold{opacity:0!important} /* visibility:hidden 이면 다시 보일 때 Chrome 이 svg 일부 애니메이션을 다시 그려 나무가 비었다 차는 결함 */
html[data-mo] section.on .mo-land.mv{animation:none;opacity:1}

/* 밝기가 다른 쌍(밝은↔어두운·사진): 배경 교차를 짧게 해서 회색 베일이 남지 않게 (JS mo-xdark) */
html[data-mo] section.leaving.mo-xdark{animation-duration:.38s!important}

/* ══ 같은 틀 연속(mo-same, JS SAME 표): 카드 틀은 그 자리에 두고 속(자식)만 글 박자로 바뀐다 → 13→14→15, 29→30→31→32 ══ */
html[data-mo] section.on.mo-same .card.mv{animation:none;opacity:1}
html[data-mo] section.on.mo-same .card.mv>*{opacity:0;animation:moRise var(--mo-in) var(--mo-ease) calc(var(--mo-d0) + (var(--k,0) + var(--j,0))*var(--mo-gap)) both}
html[data-mo] section.leaving.mo-same .card.mv{animation:none!important;opacity:1!important}
html[data-mo] section.leaving.mo-same .card.mv>*{animation:moOutText var(--mo-txt) ease-in both!important}

/* ── 14장 아토믹 스왑 (JS swap14): 그림 요소는 JS 가 켠다 ── */
html[data-mo] .mo-n14 .fgL circle,html[data-mo] .mo-n14 .fgL path[d^="M210"]{opacity:0}
html[data-mo] .mo-n14.on .steps>div.mv:nth-child(1){animation-delay:1.2s}
html[data-mo] .mo-n14.on .steps>div.mv:nth-child(2){animation-delay:2.5s}
html[data-mo] .mo-n14.on .steps>div.mv:nth-child(3){animation-delay:3.3s}
html[data-mo] .mo-n14.mo-linked.on .steps>div.mv:nth-child(1){animation-delay:2s}
html[data-mo] .mo-n14.mo-linked.on .steps>div.mv:nth-child(2){animation-delay:3.3s}
html[data-mo] .mo-n14.mo-linked.on .steps>div.mv:nth-child(3){animation-delay:4.1s}

/* ── 15장 블록 해시 난수 (JS rand15): 본판 자체 페이드는 끄고 JS 가 켠다 ── */
html[data-mo] .m3.on .fgL rect,html[data-mo] .m3.on .fgL text,html[data-mo] .m3.on .fgL circle,html[data-mo] .m3.on .fgL g path{animation:none}
html[data-mo] .m3.on .steps>div.mv:nth-child(1){animation-delay:1s}
html[data-mo] .m3.on .steps>div.mv:nth-child(2){animation-delay:2.1s}
html[data-mo] .m3.on .steps>div.mv:nth-child(3){animation-delay:3.3s}
html[data-mo] .m3.mo-linked.on .steps>div.mv:nth-child(1){animation-delay:1.8s}
html[data-mo] .m3.mo-linked.on .steps>div.mv:nth-child(2){animation-delay:2.9s}
html[data-mo] .m3.mo-linked.on .steps>div.mv:nth-child(3){animation-delay:4.1s}

/* ══ 2회차 안무 (2026-11-01 저녁) ══ */
/* ── 5장 선언: 큰 줄은 살짝 커지며 길게 미끄러져 서고, 설명 → 태그가 도장 찍히듯 ── */
html[data-mo] .dec.on .ttl .b{animation-name:moRiseBig;animation-duration:1s}
@keyframes moRiseBig{from{opacity:0;transform:translateY(26px) scale(.97)}to{opacity:1;transform:none}}
html[data-mo] .dec.on .sub.mv{animation-delay:1.15s}
html[data-mo] .dec.on .tags.mv{animation:none;opacity:1}
html[data-mo] .dec.on .tags span{opacity:0;animation:moOk .5s cubic-bezier(.3,1.5,.5,1) both}
html[data-mo] .dec.on .tags span:nth-child(1){animation-delay:1.7s}html[data-mo] .dec.on .tags span:nth-child(2){animation-delay:1.8s}html[data-mo] .dec.on .tags span:nth-child(3){animation-delay:1.9s}html[data-mo] .dec.on .tags span:nth-child(4){animation-delay:2s}html[data-mo] .dec.on .tags span:nth-child(5){animation-delay:2.1s}

/* ── 6장 경주(두 번 출발, 2026-11-02): 1차 T0=1.0s 모두 출발 → 사슬 4초(1.25s)·이더 12초(1.55s)·비트 10분(선 1.0→2.2s) / 2차 T1=2.9s 모두 다시 출발 → 사슬 10분(3.9s)·이더 13분(4.2s)·비트 60분(4.9s, 화살표). 시각은 본판 inline --d 그대로 ── */
/* 사슬 결승: 점이 링을 내고 숫자가 톡 */
html[data-mo] .scmp.on .rw.me .d:nth-child(4){animation-name:kPop,moLock!important;animation-duration:.4s,.8s!important;animation-delay:3.9s,4s!important}
html[data-mo] .scmp.on .rw.me .t:nth-child(6) b{display:inline-block;animation:moTick .5s 4.2s ease-in-out}
/* 같은 시계: 세로 커서가 2차 출발과 함께 0→20분을 2초에 지나간다 (JS cursor6) */
html[data-mo] .mo-cur{position:absolute;width:2px;background:linear-gradient(180deg,rgba(130,84,157,0),#82549d 15%,#82549d 85%,rgba(130,84,157,0));opacity:0;pointer-events:none}
html[data-mo] .scmp.on .mo-cur{animation:moCur 2.3s 2.9s linear both}
@keyframes moCur{0%{opacity:0;transform:none}4%{opacity:.8}87%{opacity:.8;transform:translateX(1200px)}100%{opacity:0;transform:translateX(1200px)}}

/* ── 9장 두 체인: 같은 시간축(1.2s~3.7s)을 리소스 블록은 느린 박자로, 메인 체인 점은 빠른 박자로 채운다 → 끝에 큰 점(리소스 블록 자리)이 물결친다 ── */
html[data-mo] .s9.on .r1>div{animation-delay:calc(1.2s + var(--i)*.07s);animation-duration:.45s}
html[data-mo] .s9.on .r2 i{animation-delay:calc(1.2s + var(--i)*.07s);animation-duration:.3s}
html[data-mo] .s9.on .r1::before{animation:kGrow 2.45s 1.2s linear forwards}
html[data-mo] .s9.on .r2::before{animation:kGrow 2.45s 1.2s linear forwards}
html[data-mo] .s9.on .r2 i:nth-child(5n+1){animation-name:kPop,moRipple;animation-duration:.3s,.7s;animation-delay:calc(1.2s + var(--i)*.07s),calc(4s + var(--i)*.03s)}
@keyframes moRipple{0%{box-shadow:0 0 0 0 rgba(130,84,157,.45)}100%{box-shadow:0 0 0 16px rgba(130,84,157,0)}}

/* ── 10장 맞물림: 노드가 하나씩 켜지며(링) 그 아래 카드가 따라 올라온다 ── */
html[data-mo] .s9b.on .bar .nd.mv{animation:moNode .55s cubic-bezier(.3,1.5,.5,1) both}
html[data-mo] .s9b.on .bar .nd.mv:nth-child(1){animation-delay:1s}html[data-mo] .s9b.on .bar .nd.mv:nth-child(2){animation-delay:1.7s}html[data-mo] .s9b.on .bar .nd.mv:nth-child(3){animation-delay:2.4s}
@keyframes moNode{from{opacity:0;transform:scale(.3);box-shadow:0 0 0 0 rgba(130,84,157,.4)}60%{opacity:1;box-shadow:0 0 0 14px rgba(130,84,157,.22)}to{opacity:1;transform:none;box-shadow:0 8px 18px rgba(30,45,90,.18)}}
html[data-mo] .s9b.on .bar::before{transform-origin:left;animation:moGrowX 1.5s 1s linear both}
html[data-mo] .s9b.on .row .card.mv:nth-child(1){animation-delay:1.1s}html[data-mo] .s9b.on .row .card.mv:nth-child(2){animation-delay:1.8s}html[data-mo] .s9b.on .row .card.mv:nth-child(3){animation-delay:2.5s}

/* ══ 3회차 안무 (2026-11-01 밤) ══ */
/* ── 11장 서명: 검증자 6명이 점점 빠르게 켜지고(1.0→2.5s) 선이 블록으로 내려오며 점이 찍힌다 → 서명 6/9 에서 블록 글로우, 안 켜진 3명은 흐려짐 → 카드 3장 ── */
html[data-mo] .s6.on .fig svg .v{animation-duration:.6s!important}
html[data-mo] .s6.on .fig svg .v:nth-of-type(1){animation-delay:1s!important}html[data-mo] .s6.on .fig svg .v:nth-of-type(2){animation-delay:1.4s!important}html[data-mo] .s6.on .fig svg .v:nth-of-type(3){animation-delay:1.75s!important}html[data-mo] .s6.on .fig svg .v:nth-of-type(4){animation-delay:2.05s!important}html[data-mo] .s6.on .fig svg .v:nth-of-type(5){animation-delay:2.3s!important}html[data-mo] .s6.on .fig svg .v:nth-of-type(6){animation-delay:2.5s!important}
html[data-mo] .s6.on .fig svg .ln{animation-duration:.4s!important}
html[data-mo] .s6.on .fig svg .ln:nth-of-type(1){animation-delay:1.15s!important}html[data-mo] .s6.on .fig svg .ln:nth-of-type(2){animation-delay:1.55s!important}html[data-mo] .s6.on .fig svg .ln:nth-of-type(3){animation-delay:1.9s!important}html[data-mo] .s6.on .fig svg .ln:nth-of-type(4){animation-delay:2.2s!important}html[data-mo] .s6.on .fig svg .ln:nth-of-type(5){animation-delay:2.45s!important}html[data-mo] .s6.on .fig svg .ln:nth-of-type(6){animation-delay:2.65s!important}
html[data-mo] .s6.on .blk .sl .nd:not(.o){animation:moSig .32s cubic-bezier(.3,1.5,.5,1) both!important}
@keyframes moSig{from{opacity:0;transform:scale(.3)}to{opacity:1;transform:none}}
html[data-mo] .s6.on .blk .sl .nd:nth-child(1){animation-delay:1.4s!important}html[data-mo] .s6.on .blk .sl .nd:nth-child(2){animation-delay:1.8s!important}html[data-mo] .s6.on .blk .sl .nd:nth-child(3){animation-delay:2.15s!important}html[data-mo] .s6.on .blk .sl .nd:nth-child(4){animation-delay:2.45s!important}html[data-mo] .s6.on .blk .sl .nd:nth-child(5){animation-delay:2.7s!important}html[data-mo] .s6.on .blk .sl .nd:nth-child(6){animation-delay:2.9s!important}
html[data-mo] .s6 .blk .tx span.mo-tk{display:inline-block;animation:moTick .35s ease-out}
html[data-mo] .s6.on .blk{animation:kGlow .9s 3s ease-out!important}
html[data-mo] .s6.on .fig svg g[filter] circle:not(.v){animation:moDim .5s 3s ease-out both}
@keyframes moDim{to{opacity:.4}}
html[data-mo] .s6.on .row .card.mv:nth-child(1){animation-delay:3.2s}html[data-mo] .s6.on .row .card.mv:nth-child(2){animation-delay:3.35s}html[data-mo] .s6.on .row .card.mv:nth-child(3){animation-delay:3.5s}

/* ── 16장 특허: 큰 숫자 12 가 먼저 차오르고(0.5~1.5s) 카드 2·2·4·4 가 뒤따른다 ── */
html[data-mo] .s12 .big{--cnt-delay:.5s;--cnt-dur:1s}
html[data-mo] .s12.on .row .card.mv{animation-delay:calc(1.6s + (var(--k,1) - 1)*.12s)}
html[data-mo] .s12.on .src.mv{animation-delay:2.2s}

/* ── 22장 쓰임: 세 숫자(23,253 · 26,229 · …) 카운트업 (JS countUp 대상에 .s18 .u b 추가) ── */
html[data-mo] .s18 .u b{--cnt-delay:.9s;--cnt-dur:1.4s}

/* ── 28장 사업 지도: 줄마다 왼쪽 특징 → 화살표가 자라고 → 오른쪽 사업이 올라온다 (.map 을 묶음으로 펼쳐 줄(.r)이 --k 를 받음) ── */
html[data-mo] .mo-n28.on{--mo-gap:.3s}
html[data-mo] .mo-n28.on .map .r.mv .ar i{transform-origin:left;transform:scaleX(0);animation:moGrowX .45s ease-out calc(var(--mo-d0) + var(--k,0)*var(--mo-gap) + .3s) both}
html[data-mo] .mo-n28.on .map .r.mv .ar .ah{opacity:0;animation:moShow .2s calc(var(--mo-d0) + var(--k,0)*var(--mo-gap) + .7s) both}
html[data-mo] .mo-n28.on .map .r.mv .v{opacity:0;animation:moRise .45s var(--mo-ease) calc(var(--mo-d0) + var(--k,0)*var(--mo-gap) + .75s) both}
html[data-mo] .mo-n28.on .band.mv{animation-delay:2.4s}
@keyframes moShow{to{opacity:1}}

/* ── 20장 오른쪽 관중: 경기장 0.7s 떠오름 → ×2.4 1.3s 톡 → 글 1.6s → 붉은 사람 2.3s 톡 → 글 2.5s ── */
html[data-mo] .s16.on .crowd .stads img{opacity:0;animation:moRise .7s cubic-bezier(.2,.8,.2,1) .7s both}
html[data-mo] .s16.on .crowd .stads em{opacity:0;animation:moMarble .5s cubic-bezier(.3,1.6,.5,1) 1.3s both}
html[data-mo] .s16.on .crowd .cap{opacity:0;animation:moShow .35s 1.6s both}
html[data-mo] .s16.on .crowd .one svg{opacity:0;animation:moMarble .6s cubic-bezier(.3,1.6,.5,1) 2.3s both}
@keyframes moMarble{from{opacity:0;transform:scale(.2)}60%{opacity:1;transform:scale(1.4)}to{opacity:1;transform:none}}
html[data-mo] .s16.on .crowd .one div{opacity:0;animation:moShow .35s 2.5s both}
