/* ═══════════════════════════════════════════════════════════
   motion.css — 메인 info01 히어로 이미지 전환
   명탐정토토(dosiraktoto02) · 2026-09-22 · v5

   [v5 — tympanus InfiniteScrollGSAPGallery 의 클릭 전환을 그대로 옮겼다]
   원본: https://tympanus.net/Tutorials/InfiniteScrollGSAPGallery/
   번들(codrops-infinite-scroll-and-content-transition.c2f4fb29.js)에서
   실제 타임라인을 읽어 왔다. 원본이 하는 일은 셋뿐이다.

     ① Flip.from(썸네일 rect) → 전면
        { duration: 1.2, ease: "power4.inOut", absolute: true }
        Flip 은 scale 이 아니라 박스(left·top·width·height)를 보간한다.
     ② 동시에 속 이미지  scale 1.2 → 1
        { duration: 1.2, ease: "power4.inOut" }
     ③ 나머지 썸네일     autoAlpha 1 → 0
        { duration: 0.5, ease: "power2.out" }

   [v4 에서 무엇이 바뀌었나 — 분기가 사라졌다]
   v4 는 PC 는 액자째 transform:scale, 모바일은 clip-path 로 창을 여는
   두 갈래였다. 액자째 scale 은 시작·끝 가로세로비가 다르면 비행 중에
   이미지가 눌리기 때문이었다(모바일 실측 77% 눌림).
   원본이 쓰는 박스 보간은 매 프레임 background-size:cover 가 다시 계산되므로
   가로세로비가 아무리 달라져도 눌리지 않는다. 그래서 분기가 필요 없다.
   덤으로 v4 PC 경로의 "끝 크롭이 진짜 이미지보다 1.8% 조임" 문제도 없어졌다 —
   끝 박스가 전면 이미지와 완전히 같은 사각형이라 크롭이 픽셀 단위로 일치한다.

   [대가]
   박스 보간은 transform 과 달리 합성 스레드에서 못 끝낸다. 매 프레임
   이 레이어 하나의 레이아웃·페인트가 다시 돈다. 원본도 전면 이미지 한 장을
   같은 방식으로 굴리고 있다. 대신 전환 중 backdrop-filter 는 반드시 꺼야 한다(7절).

   [썸네일도 같은 배율로 미리 물려 둔다 — 이게 없으면 원본이 안 된다]
   원본의 그리드 이미지는 평소에도 img{transform:scale(1.2)} 로 물려 있다.
   그래서 확대 레이어가 scale(1.2) 로 나타나는 순간 썸네일과 크롭이 정확히
   일치하고(튐 0), 비행하는 1.2초 동안 그 1.2 가 1 로 풀리면서
   "이미지가 액자보다 크게 잡혀 있다가 천천히 제자리를 찾는" 것으로 읽힌다.
   이 배율이 원본 클릭 전환의 신호 그 자체다.

   썸네일을 1 로 두고 확대 레이어만 1.2 로 띄우면, 바뀌는 첫 프레임에
   20% 크롭 차이가 "툭" 보인다 — 비행 곡선이 power4.inOut 이라 처음 150ms 는
   박스가 거의 안 움직여서 그 튐을 가려 주지도 못한다.
   배율을 1.08 까지 낮춰 튐을 줄여도 봤지만, 그러면 원본의 그 신호가
   거의 남지 않는다. 그래서 원본처럼 썸네일 쪽을 맞춘다(6절).

   ※ 대가: 스트립 썸네일이 평소에도 20% 더 조여서 보인다.
     되돌리려면 --mo-img-zoom 을 1 로 두면 된다 — 6절 썸네일 배율과
     3절 비행 배율이 같은 변수를 쓰므로 한 줄로 둘 다 꺼진다.

   [기존 CSS 를 건드리지 않는다]
   style.css / common_all.css 는 계속 손대는 중인 파일이다.
   여기의 모든 규칙은 html.motion-ready 아래에만 있다. js/motion.js 가
   못 뜨면 그 클래스가 붙지 않고, 페이지는 지금 모습 그대로 남는다.

   [왜 고스트 한 장이 필요한가]
   활성 항목은 li.on { position:static } 으로 컨테이닝 블록을 .info01_con 으로
   바꿔치기해서 전면 배경이 된다(style.css:139). position 은 보간되는 값이
   아니므로 이전 이미지는 20% 스트립으로 "반드시" 튄다. 그래서 이전 이미지의
   복제본을 한 장 위에 띄워 두고, 비행이 끝난 뒤에 지운다.
   원본에는 이 레이어가 없다 — 원본은 갤러리에서 상세로 넘어가는 것이라
   "이전 전면 이미지" 라는 것이 애초에 없기 때문이다.

   ※ js/motion.js 와 짝이다. 한쪽만 넣으면 안 된다.
   ※ 시간 값은 JS 가 이 :root 변수를 읽어서 쓴다. 여기만 고치면 된다.
   ═══════════════════════════════════════════════════════════ */


/* ── 0. 공통값 ─────────────────────────────────────────────
   JS 가 getComputedStyle 로 --mo-* 를 읽어 정리 타이머를 맞춘다.
   숫자를 JS 에도 적어 두면 반드시 어긋난다 */
:root {
	--mo-flight:1.2s;                                  /* 썸네일 → 전면 (원본 duration:1.2) */

	/* 자동 넘김이 다음 칸으로 가기 전에 사진을 세워 두는 시간(10절).
	   주기 = --mo-flight + 이 값. 지금은 1.2 + 1.4 = 2.6s 마다 한 칸
	   (모바일은 전환 1.0s 라 2.4s).

	   [줄일 곳은 전환이 아니라 여기다]
	   처음엔 swiper 옵션을 그대로 옮겨 3.0s 였다(전환 1.5 + 대기 3.0 = 4.5s).
	   느리다는 지적을 받았는데, 느린 쪽은 전환이 아니었다. 전환은 썸네일이
	   화면을 가로질러 커지는 볼거리라 길어도 지루하지 않다. 반면 이 구간은
	   사진이 완전히 정지해 있어서, 길면 "멈췄다" 로 읽힌다.
	   그래서 전환은 원본 1.2s 로 되돌리고 대기만 깎았다.

	   [1.4s 까지 내린 경과 — 값을 다시 만질 사람을 위해]
	   3.0 → 2.4s(주기 3.6s) 로 내린 뒤 "1초 더 빠르게" 요청을 받아
	   2.4 → 1.4s 로 한 번 더 깎았다. 1.4s 는 내가 권했던 하한(2.0s)보다
	   짧다 — 사진을 알아보기 전에 넘어가기 시작하는 구간이고, 전환까지
	   합치면 2.6s 중 1.2s(46%)가 움직이는 시간이라 화면이 분주하다.
	   요청이 명확했으므로 그대로 넣었고, 근거만 여기 남긴다.
	   되돌릴 때 기준: 2.4s = 주기 3.6s / 2.8s = 주기 4.0s.
	   분주한 쪽이 문제라면 대기를 늘리는 것보다 --mo-flight 를 1.0s 로
	   내리는 편이 주기를 지키면서 정지 시간을 1.6s 로 벌 수 있다 */
	--mo-auto-delay:1.4s;
	--mo-return-at:0;                                  /* 복귀가 비행의 몇 % 지점에서 시작할지. 0 = 같이 출발 (단위 없음, JS 가 읽는다) */
	--mo-img-zoom:1.2;                                 /* 이미지 배율 — 썸네일(6절)과 비행 시작값(3절)이 같이 쓴다 (원본 1.2) */

	/* 속 사진이 풀리는 기준점. 배율이 1.2 → 1 로 풀릴 때 이 점이 제자리에 남고
	   나머지가 그쪽으로 끌려온다. 그래서 기준점의 반대쪽으로 사진이 흐른다.
	     50% 50%  (원본)  사방으로 똑같이 풀림 — 내용이 위로 빠지는 느낌
	     50% 100% (지금)  아래를 붙잡고 풀림 — 내용이 아래로 내려앉는 느낌  ← 요청
	     50% 0%           위를 붙잡고 풀림 — 더 세게 위로

	   ※ 3절(비행 레이어)과 6절(썸네일)이 반드시 같은 값을 써야 한다.
	     비행은 썸네일 자리에서 같은 배율로 출발하는데, 기준점이 다르면
	     바뀌는 첫 프레임에 크롭이 어긋나 "툭" 튄다.
	   ※ 대가: 평소 썸네일이 보여 주는 창이 아래로 내려간다. 384x220 기준
	     약 22px(사진 높이의 8%)이다. 줄이려면 100% 대신 75% 처럼 낮추면 되고,
	     50% 로 되돌리면 원본 상태다 — 한 곳만 고치면 양쪽이 같이 따라간다 */
	--mo-img-origin:50% 100%;
	--mo-return-from:0;                                /* 돌아오는 썸네일의 시작 배율. 0 = 점에서 자람 · 1.08 = 앞에서 들어옴 */
	--mo-depth:1.08;                                   /* 깊이 연출. >1 앞으로 나왔다가 뒤로 · <1 뒤로 물러났다 앞으로 · 1 끔 */
	--mo-ease-depth:cubic-bezier(0.45, 0.05, 0.55, 0.95);    /* 깊이가 움직일 때 — 완만해야 한다(아래 주석) */
	--mo-handoff:0.18s;                                /* 비행 레이어 → 진짜 이미지 넘김 */
	--mo-altswap:0.28s;                                /* 모바일: 비행 중 .w → .m 갈아끼우기 */
	--mo-handoff-soft:0.55s;                           /* .m 이 끝까지 안 왔을 때의 느린 넘김 */

	/* 원본이 쓰는 GSAP 이징을 CSS 곡선으로 옮긴 것.
	   power4.inOut = easeInOutQuint = cubic-bezier(0.83, 0, 0.17, 1)
	   power2.out   = easeOutCubic   = cubic-bezier(0.33, 1, 0.68, 1)
	   power4.inOut 는 앞뒤가 아주 느리고 중간이 빠르다 — 30% 시점에 8%,
	   50% 에 50%, 70% 에 92% 다. 이 "가운데서 훅 지나가는" 배분이
	   원본 전환의 성격 그 자체라, 다른 곡선으로 바꾸면 느낌이 달라진다 */
	--mo-ease-flight:cubic-bezier(0.83, 0.00, 0.17, 1.00);
	--mo-ease-dim:cubic-bezier(0.33, 1.00, 0.68, 1.00);

	/* 아래는 동작 줄이기(reduce) 대체 연출 전용 */
	--mo-swap:0.85s;                                   /* 이전 이미지가 사라지는 시간 */
	--mo-settle:1.25s;                                 /* 새 이미지가 자리 잡는 시간 */
	--mo-zoom:1.055;                                   /* 새 이미지 시작 배율 */
	--mo-ease-swap:cubic-bezier(0.40, 0.00, 0.20, 1.00);
	--mo-ease-out:cubic-bezier(0.22, 0.61, 0.36, 1.00);
}


/* ── 1. 섹션 클리핑 ────────────────────────────────────────
   비행 레이어와 대체 연출의 배율이 섹션 밖으로 샌다.
   .info01_con 안에서 의도적으로 넘치는 요소는 없다(헤더는 position:fixed 라
   이 섹션 밖이다). motion-ready 아래에만 걸어 두어, 모션을 빼면 원상복귀된다 */
html.motion-ready #main_con > .info01_con {
	overflow:hidden;
}


/* ── 2. 고스트 레이어 (이전 전면 이미지) ───────────────────
   활성 .img_con 과 완전히 같은 박스. z-index 만 한 칸 위다.
     z-10  전면 이미지(활성 .img_con)
     z-11  고스트            ← 여기
     z-12  비행 레이어
     z-20  썸네일 li · 타이틀 · 하단 CTA
   .info01_con 의 직계 자식으로 붙는다(패딩 박스 기준이 활성 이미지와 같다) */
html.motion-ready #main_con > .info01_con > .mo_ghost {
	width:100%; height:100%;
	position:absolute; top:0; left:0; z-index:11;
	background-repeat:repeat; background-size:cover; background-position:center;
	opacity:0;
	pointer-events:none;
}

/* 붙잡기 — 이전 이미지를 띄운 직후. 여기서 transition 이 걸려 있으면
   0 → 1 이 한 프레임 보인다(깜빡임). 그래서 명시적으로 끈다 */
html.motion-ready #main_con > .info01_con > .mo_ghost.is-hold {
	opacity:1;
	transition:none;
	will-change:opacity;
}

/* 지우기 — 동작 줄이기 대체 연출에서만 쓴다.
   비행 연출에서는 고스트가 비행 레이어에 100% 가려진 뒤 그냥 꺼진다 */
html.motion-ready #main_con > .info01_con > .mo_ghost.is-out {
	opacity:0;
	transition:opacity var(--mo-swap) var(--mo-ease-swap);
	will-change:opacity;
}


/* ── 3. 비행 레이어 (주연출 — 원본의 Flip) ─────────────────
   겉(.mo_expand)      썸네일 사각형 → 섹션 사각형. left·top·width·height 를 보간한다
   속(.mo_expand_img)  같은 시간·같은 이징으로 scale(zoom) → scale(1)
   시작 좌표·크기는 JS 가 실측해서 인라인으로 넣는다 — 썸네일 위치는
   화면 폭마다 달라서 CSS 에 적어 둘 수 없다 */
html.motion-ready #main_con > .info01_con > .mo_expand {
	position:absolute; z-index:12;
	display:none;
	overflow:hidden;
	pointer-events:none;
}
html.motion-ready #main_con > .info01_con > .mo_expand.is-on {
	display:block;
}
html.motion-ready #main_con > .info01_con > .mo_expand > .mo_expand_img {
	width:100%; height:100%;
	background-repeat:repeat; background-size:cover; background-position:center;
	transform:scale(var(--mo-img-zoom));
	transform-origin:var(--mo-img-origin);   /* 0절 — 사진이 흐르는 방향을 정한다 */
	will-change:transform;
}

/* 재생 — 겉과 속이 같은 시간·같은 이징이어야 한 덩어리로 읽힌다 */
html.motion-ready #main_con > .info01_con > .mo_expand.is-fly {
	transition:left   var(--mo-flight) var(--mo-ease-flight),
	           top    var(--mo-flight) var(--mo-ease-flight),
	           width  var(--mo-flight) var(--mo-ease-flight),
	           height var(--mo-flight) var(--mo-ease-flight);
	animation:mo-depth var(--mo-flight) both;
	will-change:transform;
}

/* 클릭하면 앞으로 한 번 나왔다가 뒤로 들어가면서 날아간다.

   [방향 — 여기가 두 번 바뀐 자리다]
   처음에는 "뒤로 빠지면서" 요청을 받아 0.92 로 물러나게 했다(2026-09-22).
   그러자 "뒤에서 앞으로 오는 느낌" 이라는 지적이 왔다 — 맞는 말이다.
   뒤로 갔다가 돌아오면 마지막 움직임이 앞으로 나오는 것이라 그렇게 읽힌다.
   그래서 순서를 뒤집었다. 지금은 1.08 로 먼저 앞으로 나왔다가 제자리로
   들어가므로, 마지막 움직임이 뒤로 가는 것이 되어 "앞에서 뒤로" 로 읽힌다.
   ※ --mo-depth 한 값으로 방향이 정해진다. 1 보다 크면 앞으로 먼저,
     1 보다 작으면 뒤로 먼저, 정확히 1 이면 깊이 연출이 꺼진다.

   [이게 왜 필요한가 — 빈 구간을 메운다]
   박스 곡선이 power4.inOut 이라 앞이 아주 느리다. 실측하면 클릭 후 320ms 에
   높이가 220 → 248px, 전체의 3% 밖에 안 갔다. 그 0.3초가 무반응으로 읽힌다.
   원본은 이 구간을 "나머지 썸네일 페이드아웃" 으로 채우는데 여기서는 그걸
   뺐으므로(5절) 대신 이 깊이 연출이 그 자리를 맡는다.

   [길고 완만해야 한다 — 짧고 빠르면 덜컹거린다]
   처음에는 0 → 18% 구간에 빠른 out 곡선을 걸었다. 실측하니 화면에 보이는
   크기가 384 → 363 → 384 → 커짐 이었다. 20.5px(5.5%) 를 되돌아간 것이다.
   방향이 한 번 뒤집히니 "한번 덜컹거리고 움직인다" 로 읽혔다(지적받음).
   30% 까지 길게 펴고 공격 곡선을 완만하게 하니 되돌아감이 0.1px 로 떨어졌다.
   ※ 앞으로 나오는 지금 방향(>1)은 박스가 커지는 것과 같은 방향이라
     원리상 되돌아갈 일이 없다. 계산으로 PC 는 1.12, 모바일은 1.08 까지
     되돌아감 0px 임을 확인했다. 뒤로 물러나는 방향(<1)으로 되돌릴 때는
     이 여유가 없으니 반드시 다시 재야 한다 — 모바일은 0.97 이 한계였다.

   [왜 transform 을 .mo_expand 에 걸어도 되는가]
   이 레이어는 .info01_con 의 직계 자식이고, 전면 배경(.img_con)은 이 안에
   들어 있지 않다. 그래서 컨테이닝 블록을 가로챌 대상이 없다.
   ※ ul 이나 li 에는 같은 이유로 transform 을 주면 안 된다(9-B 절 참고).

   [85% 에서 닫는 이유]
   100% 까지 끌면 비행 막바지에도 레이어 크기가 어긋나 섹션 가장자리가
   맞지 않는다. 85% 에서 scale 1 로 닫으면 마지막 15% 구간은 오차 0 이고,
   넘길 때 진짜 전면 이미지와 픽셀 단위로 겹친다 */
/* ※ 곡선을 var() 가 아니라 숫자로 적은 이유 — 실측으로 확인한 함정이다.
     키프레임 안의 animation-timing-function 에 var() 를 쓰면 적용되지 않는다.
     무시되고 animation 단축 속성의 기본값(ease)이 먹는다. ease 는 앞이 빠른
     곡선이라, 완만하게 하려던 깊이 연출이 그대로 빨라져 덜컹이 안 없어졌다.
     실측: 125ms 에 배율 0.955 — 의도한 0.976 이 아니라 ease 의 값이었다.
     그래서 여기만 예외로 숫자를 적는다. 위 :root 의
     --mo-ease-depth / --mo-ease-flight 와 같은 값이니 함께 고쳐야 한다 */
@keyframes mo-depth {
	0%   { transform:scale(1);                animation-timing-function:cubic-bezier(0.45, 0.05, 0.55, 0.95); }
	30%  { transform:scale(var(--mo-depth));  animation-timing-function:cubic-bezier(0.83, 0.00, 0.17, 1.00); }
	85%  { transform:scale(1); }
	100% { transform:scale(1); }
}
html.motion-ready #main_con > .info01_con > .mo_expand.is-fly > .mo_expand_img {
	transform:scale(1);
	transition:transform var(--mo-flight) var(--mo-ease-flight);
}

/* ── 3-B. 모바일 전용: 비행 중에 .m 으로 갈아끼운다 ──────
   [왜 필요한가 — 끝에서 비율이 어긋났다]
   모바일은 전면 배경이 .img_con.m(세로 원본)인데, 비활성 항목의 .m 은
   display:none 이라 브라우저가 안 받는다. 그래서 비행에는 스트립에 이미
   그려져 있는 .w(가로 원본)를 쓴다(js/motion.js ⑤).
   그러면 끝에서 넘길 때 가로 원본 크롭 → 세로 원본 크롭으로 바뀐다.
   박스는 둘 다 375x817 로 같지만 원본 비율이 달라 cover 결과가 딴판이다 —
   가로 사진은 가운데 26% 만 잘려 보인다. 0.18초에 그게 바뀌니
   "마지막에 덜컹거리면서 배경 비율이 안 맞는다" 로 읽혔다(지적, 2026-09-22).

   [어떻게 푸는가]
   레이어를 한 장 더 겹쳐 .m 을 담아 두고, 그 파일이 도착하는 즉시 켠다.
   .m 은 .on 이 옮겨지는 순간 전면 배경 때문에 어차피 받기 시작하므로
   보통 비행 초반에 도착한다. 그때는 박스가 작고 빠르게 움직여서 크롭이
   바뀌는 것이 거의 안 보인다. 끝에 가서는 비행도 전면도 같은 .m 이라
   넘김이 픽셀 단위로 일치한다.
   ※ 배율·기준점은 위 3절 규칙이 두 장 모두에 걸린다. 같이 움직여야 한다.
   ※ PC 는 비행도 전면도 .w 라 이 레이어가 아예 안 만들어진다 */
html.motion-ready #main_con > .info01_con > .mo_expand > .mo_expand_img.is-alt {
	position:absolute; top:0; left:0;
	opacity:0;
}
html.motion-ready #main_con > .info01_con > .mo_expand > .mo_expand_img.is-alt.is-shown {
	opacity:1;
	transition:opacity var(--mo-altswap) linear;
}


/* 넘김 — 비행이 끝나면 진짜 전면 이미지를 켜고 이 레이어를 짧게 지운다.
   끝 박스가 전면 이미지와 같은 사각형이라 크롭은 일치하지만,
   배경 이미지 파일이 다를 수 있어(모바일 .w → .m) 페이드로 넘긴다 */
html.motion-ready #main_con > .info01_con > .mo_expand.is-handoff {
	opacity:0;
	transition:opacity var(--mo-handoff) linear;
}

/* .m 이 끝까지 안 온 경우(느린 회선)에만. 크롭이 바뀌는 것은 못 피하므로
   천천히 녹여서 "덜컹" 대신 디졸브로 읽히게 한다 */
html.motion-ready #main_con > .info01_con > .mo_expand.is-handoff.is-soft {
	transition:opacity var(--mo-handoff-soft) linear;
}


/* ── 4. 전면 이미지 마스킹 ─────────────────────────────────
   비행이 끝나기 전에 진짜 전면 이미지가 보이면 안 된다(밑에 깔려 있다).

   [transition:none 이 반드시 필요하다 — style.css:136 때문이다]
   style.css:136 의 .img_con 에 transition:all 0.5s ease 가 걸려 있다.
   그러면 숨기고 켜는 것까지 0.5초에 걸쳐 일어난다. 실측하면:
     · 숨길 때  opacity 1 → 0 이 0.5초 — 그 동안 비행이 목적지 이미지 위에 겹쳐 보인다
     · 켤 때    opacity 0 → 1 이 0.5초인데 비행 레이어는 0.18초에 사라진다
                → 그 사이 약 0.3초 동안 히어로가 반투명해져 배경이 비친다
   그래서 마스킹은 양쪽 다 즉시여야 한다. 끄는 쪽(is-unmasked)도 클래스로
   못 박는다 — 클래스를 그냥 떼면 style.css 의 transition 이 되살아나 또 서서히 켜진다.
   ※ style.css 를 고칠 수 있다면 136줄의 transition:all 을 빼는 게 맞다.
     position 은 보간되는 값이 아니라서 거기 있어도 아무것도 못 움직인다 */
html.motion-ready #main_con > .info01_con > .contents_con > .text01_con > .list_con > ul > li.on .img_con.is-masked {
	opacity:0;
	-webkit-transition:none !important;
	transition:none !important;
}
html.motion-ready #main_con > .info01_con > .contents_con > .text01_con > .list_con > ul > li.on .img_con.is-unmasked {
	opacity:1;
	-webkit-transition:none !important;
	transition:none !important;
}


/* ── 5. 직전 활성 썸네일이 스트립으로 돌아온다 ─────────────
   원본(③ others autoAlpha 0)은 뺐다 — 클릭해도 스트립이 안 숨는다(요청).
   여기 남은 것은 "직전까지 전면이던 항목" 하나뿐이다.

   [왜 이 항목만 손대나 — 숨기는 게 아니라 튐을 막는 것이다]
   .on 이 떨어지는 순간 그 항목의 .img_con 이 20% 슬롯으로 되돌아온다.
   position 은 보간되는 값이 아니므로 이건 무조건 "툭" 이다.
   그래서 떨어지는 즉시(mo_now, 전환 없음) 감췄다가 제대로 들여보낸다.

   [들어오는 모션 — 배율 0 → 1 로 자란다]
   세 번 바뀐 자리다.
     ① opacity 페이드만    — 다른 것은 전부 깊이로 움직이는데 이것만
                             아무 움직임 없이 생겨나서 겉돌았다.
     ② 1.08 → 1 + 페이드   — 깊이 언어는 맞췄지만 페이드 줌인이었다.
     ③ 0 → 1 (지금)        — 페이드를 아예 빼고 배율만 쓴다.
   배율 0 이면 면적이 0 이라 그 자체로 안 보인다. opacity 를 건드릴 이유가
   없고, 그래서 "페이드 줌인" 이 아니라 순수한 자라남이 된다.

   ※ transform 은 레이아웃을 안 바꾼다. li 는 배율 0 일 때도 20% 자리를
     그대로 차지하므로 스트립이 밀리거나 다시 흐르지 않는다.

   [곡선을 --mo-ease-out 으로 둔 이유]
   0 에서 자라는 것은 "도착" 이라 감속 곡선(power2.out)이 맞는다.
   깊이 연출에 쓰는 좌우대칭 곡선을 쓰면 앞 절반이 거의 점이어서
   한참 안 보이다가 뒤늦게 부풀어 오른다.

   [시계를 비행과 하나로 묶는다 — 타이밍을 세 번 고친 끝의 결론]
   세 가지를 차례로 시도했고 전부 "타이밍이 안 맞는다" 는 지적을 받았다.
       ① 비행보다 먼저 끝남   459ms 에 비행 8% / 썸네일 30% —
                              부차 모션이 주연출을 앞질러 갔다.
       ② 비행의 70% 에 시작   916ms 시작 · 1350ms 종료 · 착지 1200ms —
                              착지에 걸쳐서 앞뒤 어디에도 안 붙었다.
       ③ 착지하고 나서 시작   겹침은 없앴지만 전체가 1.64초로 늘어지고,
                              다 끝난 뒤에 따로 튀어나오는 별개 사건이 됐다.
   셋 다 안 맞은 이유는 "언제" 가 아니라 둘이 다른 시계로 움직였기 때문이다.
   비행은 1.2초 power4.inOut, 복귀는 0.42초 power2.out 이었다. 길이도
   곡선도 다르니 어느 지점에 놓아도 진행률이 어긋난다.

   지금은 같은 시계에 묶었다 — 같은 순간에 출발해서, 같은 곡선으로,
   같은 순간에 끝난다(--mo-return-at:0, 시간·이징 모두 --mo-flight 것).
   진행률이 매 순간 같으므로 어긋날 자리가 없다.
       0 ──────────────────── 1200ms
       [ 비행: 썸네일 → 전면          ]
       [ 복귀: 0 → 제자리              ]
   눌린 것은 스트립에서 나와 화면을 채우고, 놓인 것은 같은 박자로 스트립
   자리에 자란다. 둘이 한 몸짓의 앞뒤가 된다.

   ※ 시간을 따로 두지 않고 --mo-flight 를 그대로 쓴다. 변수를 나누면
     한쪽만 고쳤을 때 다시 어긋나는데, 그게 바로 위 ①~③ 의 원인이었다.

   [되돌리는 법]
   --mo-return-from 을 1.08 로 두면 앞에서 들어오는 방식이 된다.
   그때는 페이드가 같이 있어야 자연스러우므로 아래 mo_in 의 transition 에
   opacity 를 되살리고 mo_out 의 opacity 를 0 으로 바꿔야 한다.

   [배율을 li 에 거는 이유]
   .img_con 에는 이미 썸네일 배율(6절, 기준점 아래)이 걸려 있어서 덮어쓰면
   안 된다. li 는 비활성일 때 이미 position:relative 라 컨테이닝 블록이
   새로 생기지도 않는다. 활성 li 에는 이 클래스가 절대 안 붙는다 —
   play() 가 눌린 항목의 클래스를 동기로 먼저 떼기 때문이다(JS ④).
   ※ 이 배율 때문에 슬롯 폭을 getBoundingClientRect 로 재면 안 된다.
     js/motion.js 의 slotW() 가 offsetWidth 를 쓰는 이유다 */
html.motion-ready #main_con > .info01_con > .contents_con > .text01_con > .list_con > ul > li.mo_out {
	transform:scale(var(--mo-return-from));
	/* 전환 없음 — 이 클래스는 항상 mo_now 와 같이 붙어 즉시 적용된다 */
}
html.motion-ready #main_con > .info01_con > .contents_con > .text01_con > .list_con > ul > li.mo_out.mo_now {
	-webkit-transition:none !important;
	transition:none !important;
}
html.motion-ready #main_con > .info01_con > .contents_con > .text01_con > .list_con > ul > li.mo_in {
	transform:scale(1);
	/* 비행과 같은 시간·같은 곡선 — 이게 이 절의 핵심이다 */
	transition:transform var(--mo-flight) var(--mo-ease-flight);
}


/* ── 6. 썸네일 배율 (원본 .gallery__img-wrapper img) ───────
   원본과 같은 값으로 평소에도 물려 둔다. 이래야 클릭한 순간 확대 레이어와
   크롭이 정확히 일치하고, 비행하는 동안 이 배율이 1 로 풀린다 — 헤더 주석 참고.

   [li 에 overflow:hidden 이 반드시 같이 있어야 한다]
   li 는 원래 overflow 가 없어서 scale 이 옆 칸을 침범한다.
   활성 li 는 position:static 이라 전면 이미지의 컨테이닝 블록이 아니고,
   여기서도 :not(.on) 으로 제외되므로 잘리지 않는다 — 이 구분을 지워서는 안 된다.

   [transition:none 인 이유]
   style.css:136 의 .img_con 에 transition:all 0.5s 가 걸려 있어서, .on 이
   붙고 떨어질 때 이 배율이 0.5초에 걸쳐 움직인다. 그 순간 그 이미지는
   항상 가려져 있지만(새 활성은 is-masked, 직전 활성은 mo_now),
   연타로 타이밍이 겹치면 페이드백 중에 배율이 아직 움직이는 중일 수 있다.
   평소 화면에서 이 값이 애니메이션될 이유는 없으므로 아예 끈다 */
html.motion-ready #main_con > .info01_con > .contents_con > .text01_con > .list_con > ul > li:not(.on) {
	overflow:hidden;
}

/* 썸네일은 글이 아니라 버튼이다. 끌면 텍스트 선택 반전이 뜨고, 슬롯 안의
   블랭크 이미지는 브라우저 기본 이미지 드래그가 걸려 고스트가 따라다닌다.
   실측하니 draggable 이 true 였다. 둘 다 막는다 */
html.motion-ready #main_con > .info01_con > .contents_con > .text01_con > .list_con > ul > li {
	-webkit-user-select:none;
	-ms-user-select:none;
	user-select:none;
	-webkit-tap-highlight-color:transparent;
}
html.motion-ready #main_con > .info01_con > .contents_con > .text01_con > .list_con > ul > li img {
	-webkit-user-drag:none;
}

/* 키보드로 옮겨 다닐 때만 테두리를 보인다(js/motion.js 가 tabindex 를 붙인다).
   마우스 클릭에는 안 뜨므로 평소 화면은 그대로다.
   li 에 overflow:hidden 이 걸려 있어 바깥쪽 outline 은 잘린다 — 안쪽으로 넣는다 */
html.motion-ready #main_con > .info01_con > .contents_con > .text01_con > .list_con > ul > li:focus {
	outline:none;
}
html.motion-ready #main_con > .info01_con > .contents_con > .text01_con > .list_con > ul > li:focus-visible {
	outline:min(3px, 0.16vw) solid rgba(255,255,255,0.92);
	outline-offset:max(-3px, -0.16vw);
}
html.motion-ready #main_con > .info01_con > .contents_con > .text01_con > .list_con > ul > li:not(.on) .img_con {
	transform:scale(var(--mo-img-zoom));
	transform-origin:var(--mo-img-origin);   /* 3절과 반드시 같은 값 — 다르면 첫 프레임에 튄다 */
	-webkit-transition:none;
	transition:none;
}


/* ── 7. 전환 중 블러 끄기 ──────────────────────────────────
   레시피 03. 하단 CTA 2개가 backdrop-filter:blur(6px) 로 히어로 이미지
   바로 위에 올라가 있다(style.css / common_all.css 각 4곳).
   뒤 배경이 매 프레임 바뀌면 브라우저가 매 프레임 다시 블러링하므로
   GPU 합성만으로 끝나지 않는다 — blueocean 에서 55fps → 27fps 를 실측했다.
   v5 의 박스 보간은 v4 의 transform 보간보다 프레임당 일이 더 많아서
   이 처리가 v4 때보다 더 중요해졌다.
   전환 중에만 끄고 끝나면 되돌린다. 1.2s 동안 유리 질감이 빠지는 것은
   프레임이 무너지는 것보다 눈에 덜 띈다 */
html.motion-ready #main_con > .info01_con.mo_blurless,
html.motion-ready #main_con > .info01_con.mo_blurless * {
	-webkit-backdrop-filter:none !important;
	backdrop-filter:none !important;
}


/* ── 8. 동작 줄이기 대체 연출 ──────────────────────────────
   is-enter 로 배율만 올려 두고(전환 없음), 한 프레임 뒤 is-settle 로 바꿔
   scale(1) 까지 감속한다. 고스트는 그 사이 디졸브로 빠진다 */
html.motion-ready #main_con > .info01_con > .contents_con > .text01_con > .list_con > ul > li.on .img_con.is-enter {
	transform:scale(var(--mo-zoom));
	transition:none;
	will-change:transform;
}
html.motion-ready #main_con > .info01_con > .contents_con > .text01_con > .list_con > ul > li.on .img_con.is-settle {
	transform:scale(1);
	transition:transform var(--mo-settle) var(--mo-ease-out);
	will-change:transform;
}


/* ── 9. 모바일 ─────────────────────────────────────────────
   브레이크포인트는 common_all.css 와 같은 1024px 이다.
   화면이 작을수록 같은 시간도 길게 느껴지므로 조금 줄인다.
   ※ v4 와 달리 모바일 전용 연출 분기는 없다. 박스 보간은 시작(가로 썸네일)과
     끝(세로 크롭 전면)의 가로세로비가 281% 달라도 눌리지 않는다 */
@media all and (max-width: 1024px) {
	:root {
		/* 작은 화면에서는 같은 시간이 더 길게 느껴져 조금 줄인다.
		   대기(--mo-auto-delay)는 PC 와 같게 둔다 — 사진을 알아보는 데
		   걸리는 시간은 화면 크기와 상관이 없다. 모바일 주기는 3.4s */
		--mo-flight:1.00s;
		--mo-swap:0.70s;
		--mo-settle:1.00s;
		--mo-zoom:1.04;
	}
}


/* ── 9-B. 모바일 — 클릭하면 스트립이 한 칸 왼쪽으로 민다 ───
   common_all.css:36-38 은 모바일에서 이 스트립을 폭 288.9vw(57.78vw × 5)로
   깔고 .list_con 에 overflow:hidden 을 건다. 화면이 100vw 이므로 3~5번째
   썸네일은 평소에 볼 수가 없다. 클릭할 때마다 한 칸씩 밀어 다음 것을 꺼낸다.
   다 민 뒤에는 맨 앞 li 를 맨 뒤로 옮기고 margin 을 0 으로 되돌리므로
   끝없이 돈다(js/motion.js 8절).

   [왜 transform 이 아니라 margin-left 인가 — 취향이 아니라 구조 때문이다]
   활성 썸네일의 .img_con 은 li.on{position:static}(style.css:139) 으로 li 를
   빠져나와 .info01_con 을 기준으로 전면 배경이 된다. transform 이 걸린 요소는
   position:absolute 자손의 컨테이닝 블록이 되므로(값이 항등행렬이어도
   마찬가지다), ul 에 transform 을 걸면 그 기준을 가로채 전면 배경이 무너진다.
   실측으로 375x817 → 217x124 가 되는 것을 확인했다. Swiper 를 못 쓴 이유도
   같다 — .swiper-wrapper 에 transform 을 걸기 때문이다.
   margin 은 컨테이닝 블록을 만들지 않아서 전면 배경이 그대로 남는다.
   ※ 여기에 transform·filter·perspective·will-change 를 주면 안 된다.

   [PC 에 안 거는 이유]
   PC 는 ul 이 100%(li 20% × 5)라 한 칸 밀면 오른쪽 끝에 20% 빈칸이 생긴다.
   모바일은 ul 이 288.9vw 라 한 칸(57.78vw) 밀어도 231vw 가 남아 안 빈다. */
@media all and (max-width: 1024px) {
	html.motion-ready #main_con > .info01_con > .contents_con > .text01_con > .list_con > ul.mo_shift {
		transition:margin-left var(--mo-flight) var(--mo-ease-flight);
	}
}


/* ── 10. 동작 줄이기(prefers-reduced-motion) — 보지 않는다 ──
   [v6 에서 바꾼 것. 되돌리는 법이 아래에 있다]

   v5 까지는 이 미디어쿼리로 시간 값을 0.3s 로 줄이고, js/motion.js 가
   비행 자체를 건너뛰어 디졸브로 내려갔다. 원칙대로면 비행은 화면 절반을
   가로지르는 큰 이동이라 reduce 가 막으려는 바로 그 연출이 맞다.
   그런데 윈도우 "애니메이션 효과" 를 꺼 둔 PC 에서는 이 값이 켜지고,
   그 PC 에서는 클릭해도 이미지만 스윽 바뀌어 연출이 아예 안 들어간 것처럼
   보인다 — 실제로 그런 신고가 들어왔다(2026-09-22).

   옮겨 온 원본(tympanus InfiniteScrollGSAPGallery)은 이 값을 아예 다루지
   않는다 — JS 번들·CSS 양쪽에 prefers-reduced-motion 이 0 건이고, 모든
   방문자에게 같은 전환을 보여준다. "원본과 같게" 가 요구사항이라 원본을 따른다.
   접근성 신호를 일부러 무시하는 선택이고, 그렇게 결정한 것이다.

   ※ 되살리려면 이 블록을 아래 내용으로 되돌리고,
     js/motion.js 의 wantFly() 를 그 파일 주석대로 한 줄 바꾸면 된다.
         @media (prefers-reduced-motion: reduce) {
             :root { --mo-flight:0.30s;
                     --mo-swap:0.30s; --mo-settle:0.01s; --mo-zoom:1; }
         }
     썸네일 배율(6절)은 그때도 건드리지 않는다 — 그건 움직임이 아니라
     평소 크롭이고, 1 로 되돌리면 전환할 때마다 크롭이 튀어 더 시끄러워진다. */
