@charset "utf-8";

/* <eve-3d> 3D 북 커버 — UI.CSS의 <book-3d> 블록(1743~1788) 포크.
   1) 아래 "면 배치·전이" 구간은 원본의 순수 리네임이다 — 프로퍼티·값·순서를 한 글자도 바꾸지 않아
      원본이 개정돼도 식별자만 치환해 diff로 재동기화할 수 있다.
      태그 book-3d→eve-3d / 클래스 yR_book3d__*→eve3d__* / 변수 --yR-book-3d-*→--eve3d-*.
      프리픽스가 전부 갈라져 있어 book-3d.css와 같은 페이지에 동시에 실려도 충돌하지 않는다.
   2) 예외 2건(의도적 변경)은 해당 줄에 [변경] 주석으로 표시했다.
   3) 맨 아래 sizeopt 구간은 eve-3d 전용 추가분이다.
   4) [변경] 면 이미지를 __bdr 래퍼(span.eve3d__bdr.eve3d__bdr-{front|spine|back} > img)로 감싼다.
      이미지 자체의 검정 테두리를 래퍼 overflow:hidden + 이미지 확대(--eve3d-bdr-crop)로 잘라내고,
      그 위에 반투명 선(--eve3d-bdr-color)을 ::after로 얹는다. 책등·뒤표지의 위치·transform·filter·
      box-shadow는 img가 아니라 래퍼가 소유한다(래퍼가 __body의 직계 3D 면이다).
   공개 노브: --eve3d-perspective, --eve3d-spine-w(두께 폴백/오버라이드),
             --eve3d-flip-cursor, --eve3d-dim-gap/-dim-color/-dim-label-color,
             --eve3d-bdr-crop(잘라낼 원본 테두리 두께, 기본 1px)/-bdr-color(반투명 선 색).
   --eve3d-angle/-shift/-z/-dur는 eve3d.js가 기록하는 내부 상태 변수. */
eve-3d { display:block;position:relative;perspective:var(--eve3d-perspective);--eve3d-perspective:800px;--eve3d-sw:var(--eve3d-spine-w, 56px);--eve3d-seam:1px;/* 이음선 겹침: 옆면(책등·책배)이 앞표지 접힘선(z=0)에 정확히 맞닿으면 서브픽셀 틈으로 뒷배경이 샌다. 옆면을 뷰어 쪽으로 이만큼 당겨 덮는다. 부호는 회전 방향 종속 — 네 면 모두 +seam(-90°면 sw/-2+seam, +90°면 sw/2+seam); 한쪽만 -seam이면 그 접힘선이 되레 벌어진다. */ }
eve-3d img { display:block;width:100%;height:auto;-webkit-user-drag:none; }

/* fit: 표지 크기를 CSS가 잡고 host가 shrink-wrap한다(인라인 크기 주입 없음).
   [변경] book-3d는 세로 캡을 --eve3d-max-h로만 잡아, 그 변수를 선언하지 않으면 표지가 원본 높이로
   터졌다(캡 변수를 매번 손으로 줘야 했다). eve-3d는 fit 사슬(eve-3d→__body→앞표지)에 block-size:100%를
   심어, 컨테이너에 height만 있으면 그 높이가 사슬을 타고 내려가 앞표지 max-block-size:100%가 resolve된다
   (CSS의 % 높이는 부모 높이가 명시적일 때만 계산되는 제약을 이렇게 우회한다).
   결과: 컨테이너 width/height만으로 자동 contain — 캡 변수는 이제 선택(주면 그 값이 우선, 회귀 없음).
   컨테이너에 height가 없으면 종전대로 폭 기준으로만 맞춘다. */
eve-3d[fit] { margin:auto;inline-size:fit-content;block-size:100%;max-block-size:var(--eve3d-max-h, 100%);max-inline-size:var(--eve3d-max-w, 100%);--eve3d-spine-w:16px;/* 실 contain은 앞표지 img가 — host max-*는 상한 방어 겸 소비 카드가 읽는 캡 계약(정규 속성) *//* fit 로드 전·옆면 없을 때의 책등 두께 폴백(비-fit 데모 56px과 구분) */ }

/* [변경] auto-spine도 fit과 같은 로드 전 폴백(16px)을 쓴다 — 둘 다 "진짜 두께는 책등 이미지에서 온다"는
   선언이라 폴백만 다를 이유가 없다. 이게 없으면 auto-spine 단독 사용 시 첫 페인트에 일반 기본값 56px로
   그렸다가 이미지 로드 후 유도값(가령 16px)으로 튄다. fit과 값이 같아 둘 다 붙어도 충돌하지 않는다. */
eve-3d[auto-spine] { --eve3d-spine-w:16px; }

/* __body가 표지를 shrink-wrap해 host fit-content 폭을 표지 폭으로 확정.
   [변경] block-size:100%로 컨테이너 높이 사슬을 이어주고, 앞표지를 flex 중앙정렬한다 —
   폭 제약 슬롯(표지가 슬롯 높이보다 짧은 경우)에서 앞표지가 상단으로 쏠려 3D 회전 기준이
   어긋나는 것을 막는다. flex는 정적 흐름의 앞표지만 정렬하고, 절대배치 책등·뒤표지에는 무영향. */
eve-3d[fit] .eve3d__body { display:flex;align-items:center;justify-content:center;inline-size:fit-content;block-size:100%; }

/* 앞표지: width/height auto + max-* 두 캡을 종횡비 유지로 동시 적용 = contain(판형 분기 없음) */
/* [변경] 캡 두 폴백을 모두 none → 100%로 낮췄다. fit은 기본 width:100%를 inline-size:auto로 덮어
   이미지를 원본 크기로 되돌리는데, 원본 폴백이 none이면 캡 변수를 선언하지 않을 때 표지가
   naturalWidth(예스24 XL = 815px)로 터진다. 100% 폴백이면 __body(block-size:100%)를 통해 이어진
   컨테이너 높이·폭에 자동으로 갇힌다. 캡 변수를 선언하면 그 값이 우선(회귀 없음). */
/* [변경] 앞표지가 __bdr-front 래퍼로 감싸져, 높이 사슬(body 100%)을 래퍼가 받고 img는 래퍼를 기준으로 contain한다.
   img 캡에 crop×2를 더해 래퍼보다 사방 crop만큼 크게 그린 뒤 래퍼 overflow:hidden이 가장자리를 잘라낸다.
   래퍼가 block-size:100%라 spine·back(height:100%)과 같은 높이를 공유한다. */
eve-3d[fit] .eve3d__bdr-front { inline-size:fit-content;block-size:100%;max-inline-size:var(--eve3d-max-w, 100%);max-block-size:var(--eve3d-max-h, 100%); }
/* eve-3d[fit] .eve3d__bdr-front img.eve3d__front { inline-size:auto;block-size:auto;max-inline-size:calc(var(--eve3d-max-w, 100%) + var(--eve3d-bdr-crop) * 2);max-block-size:calc(var(--eve3d-max-h, 100%) + var(--eve3d-bdr-crop) * 2); } */
eve-3d[fit] .eve3d__bdr-front img.eve3d__front { inline-size:auto;block-size:auto;min-inline-size:30px;min-block-size:45px;max-inline-size:calc(var(--eve3d-max-w, 100%) + var(--eve3d-bdr-crop) * 2);max-block-size:calc(var(--eve3d-max-h, 100%) + var(--eve3d-bdr-crop) * 2); }

/* fit 가로 정렬 — flex 자동 마진이 justify-content를 이겨 부모 정렬과 무관하게 밀어붙는다(기본=중앙) */
eve-3d[fit][align="start"] { margin-inline-start:0;margin-inline-end:auto; }
eve-3d[fit][align="end"] { margin-inline-start:auto;margin-inline-end:0; }

/* 무JS·평면 강등 기본값: 앞표지만 평면 노출 */
eve-3d { --eve3d-bdr-crop:1.5px;--eve3d-bdr-color:rgb(0 0 0 / 7%);/* 원본 이미지 검정 테두리를 잘라낼 두께(표시 px)와 그 위에 얹는 반투명 선 색 */ }

/* __bdr 공통: 래퍼가 이미지를 사방 crop만큼 크게 받아 overflow:hidden으로 가장자리(검정 테두리)를 잘라내고,
   ::after가 잘려난 새 가장자리 위에 반투명 1px 선을 그린다. */
eve-3d .eve3d__bdr { display:block;position:relative;overflow:hidden; }
eve-3d .eve3d__bdr:after { position:absolute;left:0;top:0;right:0;bottom:0;content:"";border:1px solid var(--eve3d-bdr-color);pointer-events:none; }
eve-3d .eve3d__bdr img { margin:calc(var(--eve3d-bdr-crop) * -1);width:calc(100% + var(--eve3d-bdr-crop) * 2);max-width:none; }
eve-3d .eve3d__bdr-spine img, eve-3d .eve3d__bdr-back img { position:absolute;left:calc(var(--eve3d-bdr-crop) * -1);top:calc(var(--eve3d-bdr-crop) * -1);margin:0;height:calc(100% + var(--eve3d-bdr-crop) * 2); }

/* 무JS·평면 강등 기본값: 앞표지만 평면 노출 (공통 display:block 뒤에 와야 이긴다) */
eve-3d .eve3d__bdr-spine, eve-3d .eve3d__bdr-back { display:none; }

/* 연령 코너 배지: 앞표지 면(__body) 안에 있어 회전을 함께 탄다. 앞표지와 동일 평면(z=0)이라
   preserve-3d에서 z-fighting이 나므로 뷰어 쪽으로 1px 띄운다 — 기운 표지 코너에 얹힌 것처럼 보인다.
   yR_ageBadge는 eve-3d 소유가 아닌 외부 배지 컴포넌트라 클래스명을 그대로 둔다. */
.eve3d__body .yR_ageBadge { transform:translateZ(1px); }

/* 3D 활성 — 저자가 마크업에 __body 래퍼·책배(__edge)·data-3d를 직접 작성한다(스크립트는 DOM을 만들지 않음) */

/* [변경] 원본의 touch-action:pan-y를 뺐다. 그 값은 flip="drag"가 가로 스와이프를 가로채는 대신
   세로 스크롤만 브라우저에 넘기려던 선언인데, drag를 제거한 eve3d에는 가로 제스처를 받을 주체가
   없다. 그대로 두면 캐러셀(Swiper 등) 위에 얹혔을 때 표지를 잡고 하는 가로 스와이프만 먹히지 않는다. */
eve-3d[data-3d] { -webkit-user-select:none;user-select:none; }
eve-3d[data-3d] img { pointer-events:none; }

/* [변경] 원본의 고정 애셋 경로(url("../../assets/ui/ico-flip.svg") 30 30)를 변수로 뺐다 — 프로젝트마다
   경로가 달라 하드코딩하면 깨진 참조가 남는다. 커서 애셋이 있으면 소비처에서
   --eve3d-flip-cursor:url("<경로>") 30 30, pointer; 로 준다(미지정 시 pointer).
   뒤표지 없는 tilt 전용([data-tilt-only])에는 붙지 않는다. */
eve-3d[flip="click"][data-3d]:not([data-tilt-only]) { cursor:var(--eve3d-flip-cursor, pointer); }
eve-3d[data-3d] .eve3d__body { display:block;position:relative;transition:transform var(--eve3d-dur, 0s) ease;transform:translateX(var(--eve3d-shift, 0px)) rotate3d(0, 1, 0, var(--eve3d-angle, 0deg)) translate3d(0, 0, var(--eve3d-z, 0px));transform-origin:50% 50% 0;transform-style:preserve-3d;/* 인라인 박스에는 transform이 적용되지 않는다 *//* 앞표지 면(z=0)에서 회전 — 앞표지가 제자리에서 돌고 책등·책배는 뒤로 접힌다. translateX(--shift): 기운 각의 좌측 쏠림 보정(eve3d.js가 넣는다, 0°=0). */ }
eve-3d[data-3d] .eve3d__bdr-spine { display:block;position:absolute;top:0;left:calc(var(--eve3d-sw) / -2);width:var(--eve3d-sw);height:100%;transform:rotate3d(0, 1, 0, -90deg) translate3d(calc(var(--eve3d-sw) / -2 + var(--eve3d-seam)), 0, 0);filter:brightness(0.85);/* 책등 입체감: 같은색 표지·책등 구분용 옅은 먹 */ }
eve-3d[data-3d] .eve3d__bdr-back { display:block;position:absolute;top:0;left:0;width:100%;height:100%;box-shadow:-10px 20px 15px rgb(0 0 0 / 20%);transform:rotate3d(0, 1, 0, -180deg) translate3d(0, 0, var(--eve3d-sw)); }
eve-3d[data-3d] .eve3d__edge { position:absolute;top:0;left:calc(100% - var(--eve3d-sw) / 2);width:var(--eve3d-sw);height:100%;background:#e8e4da;transform:rotate3d(0, 1, 0, 90deg) translate3d(calc(var(--eve3d-sw) / 2 + var(--eve3d-seam)), 0, 0);/* 책배 텍스처 대응 단색 */ }

/* 책등·뒤표지 래퍼 크기 고정 — 같은 규칙의 left/top은 먹는데 width/height만 0으로 덮이는 사례가 있어(사이트 CSS의 span 계열 규칙 추정),
   자식 결합자로 명시도를 올리고 !important로 못 박는다. 이 두 줄은 위 면 배치 규칙의 크기 선언과 값이 같다. */
eve-3d[data-3d] .eve3d__body > .eve3d__bdr-spine { width:var(--eve3d-sw)!important;height:var(--eve3d-ch, 100%)!important; }
eve-3d[data-3d] .eve3d__body > .eve3d__bdr-back { width:100%!important;height:var(--eve3d-ch, 100%)!important; }
/* 책등·뒤표지 img도 같은 이유로 못 박는다 — height가 auto로 덮이면 원본 비율(책등 31:400)대로 자라 래퍼보다 길어지고 아래가 잘린다 */
eve-3d[data-3d] .eve3d__body > .eve3d__bdr-spine > img, eve-3d[data-3d] .eve3d__body > .eve3d__bdr-back > img { position:absolute!important;left:calc(var(--eve3d-bdr-crop) * -1)!important;top:calc(var(--eve3d-bdr-crop) * -1)!important;margin:0!important;width:calc(100% + var(--eve3d-bdr-crop) * 2)!important;max-width:none!important;height:calc(100% + var(--eve3d-bdr-crop) * 2)!important; }

/* 우철(spine-right): 책등·책배 자리 교환 — 회전각 부호 반전은 eve3d.js 소관 */
eve-3d[spine-right][data-3d] .eve3d__bdr-spine { left:calc(100% - var(--eve3d-sw) / 2);transform:rotate3d(0, 1, 0, 90deg) translate3d(calc(var(--eve3d-sw) / 2 + var(--eve3d-seam)), 0, 0); }
eve-3d[spine-right][data-3d] .eve3d__edge { left:calc(var(--eve3d-sw) / -2);transform:rotate3d(0, 1, 0, -90deg) translate3d(calc(var(--eve3d-sw) / -2 + var(--eve3d-seam)), 0, 0); }
eve-3d[spine-right][data-3d] .eve3d__bdr-back { box-shadow:10px 20px 15px rgb(0 0 0 / 20%); }

/* eve3dCover — 카드 표지 맥락(리스트·랭킹 등 좁은 슬롯)의 3D 도서 기하값. yR_book3dCover 대응.
   비율(aspect-ratio)은 인스턴스별로 인라인, 원근은 모든 표지가 공유하므로 여기서 고정.
   책등 폭은 eve3d.js가 SIDE 이미지 종횡비로 자동 유도(폴백은 eve-3d[fit]의 16px).
   작은 표지라 기본 원근(1800px)은 입체가 약해 1200px로 좁힌다. */
.eve3dCover { --eve3d-perspective:1200px;block-size:100%;inline-size:auto;max-inline-size:100%;/* 슬롯(정의된 부모 박스) 높이에 맞추고 폭은 aspect-ratio로 유도 — 기기별 표지 캡을 그대로 따라 축소된다(고정 px는 좁은 모바일 슬롯을 넘쳐 흐른다). */ }

/* ────────────────────────────────────────────────────────────────
   sizeopt — 실측 치수(mm) 오버레이 (eve-3d 추가분)

   eve3d.js가 sizeopt 속성을 감시해 front img의 data-w-mm·data-h-mm, spine img의 data-w-mm을
   읽고 아래 구조를 채운다.
     .eve3d__body > .eve3d__dims > .eve3d__dimRow.eve3d__dim-{width|height|spine-top|spine-bottom}
                                     > .eve3d__dimLine + .eve3d__dimLabel

   각도가 저절로 맞는 원리: .eve3d__dims가 .eve3d__body의 자식이라 같은 3D 좌표계를 공유하고,
   각 줄에 "그 줄이 재는 면과 똑같은 힌지"만 걸어둔다 — 가로·세로는 앞표지 평면(z=0, transform 없음),
   두께는 위 .eve3d__bdr-spine에서 그대로 복사한 rotate3d(0,1,0,-90deg)+translate3d. 그러면 body가
   --eve3d-angle로 돌 때 안내선도 표지와 같은 각도로 함께 기울고, 화면상의 대각선(원근 투영)은
   CSS 3D 엔진이 계산해 준다 — JS에서 각도를 다시 풀 필요가 없다.

   주의: 안내선은 표지 박스 바깥으로 --eve3d-dim-gap만큼 삐져나온다. 소비처 조상에
   overflow:hidden이 걸려 있으면 잘리므로 그만큼 패딩을 두거나 클리핑을 풀어야 한다.
   ──────────────────────────────────────────────────────────────── */
eve-3d { --eve3d-dim-gap:20px;--eve3d-dim-color:rgb(0 0 0 / 55%);--eve3d-dim-label-color:#fff;/* 선·라벨칩 색과 라벨 글자색. 기본은 밝은 배경 기준(어두운 선 + 어두운 칩 + 흰 글자) — 어두운 히어로 위에 얹을 땐 소비처에서 두 변수만 뒤집는다. */ }

/* 3D가 아닌 평면 강등 상태에선 통째로 숨긴다 — 책등 라인이 접힐 3D 컨텍스트 자체가 없어
   납작하게 뭉개진다. 원본의 spine/back display:none → [data-3d] display:block 패턴과 동형. */
eve-3d .eve3d__dims { display:none; }
eve-3d[data-3d][sizeopt] .eve3d__dims { display:block; }

/* transform-style:preserve-3d 필수 — 이게 없으면 기본값 flat이 자식(책등 라인)의 rotate3d를
   자기 평면으로 납작하게 눌러버려 두께 라인이 0폭으로 사라진다. */
.eve3d__dims { position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;transform-style:preserve-3d; }
.eve3d__dimRow { position:absolute;color:var(--eve3d-dim-color);transform-style:preserve-3d;/* 라벨이 아래에서 역회전(rotateY)을 걸기 때문에 이 줄도 3D를 유지해야 한다 — flat이면 그 역회전이 납작하게 눌려 글자가 되레 뭉개진다 */ }
.eve3d__dimLine { display:block;position:relative;width:100%;height:1px;background:currentColor; }

/* 양 끝 마감선(치수보조선) */
.eve3d__dimLine::before, .eve3d__dimLine::after { position:absolute;top:-3px;width:1px;height:7px;background:currentColor;content:""; }
.eve3d__dimLine::before { left:0; }
.eve3d__dimLine::after { right:0; }

/* 라벨은 선 한가운데에 얹는다 — 칩 배경이 선 가운데를 가려 "선―값―선"으로 읽힌다.
   flex 배치를 쓰지 않는 이유: 책등처럼 선(16px)보다 라벨이 넓은 줄에서 선이 0폭으로 찌그러진다.

   라벨만 화면 쪽으로 되돌린다(역회전): 안내선은 각 면에 눕혀야 기하가 맞지만, 글자까지 같이 누우면
   특히 책등 면(힌지 ∓90°)에서 완전히 뭉개져 못 읽는다. 누적 회전이 0이 되도록 되돌린 각을 건다 —
   앞표지 면은 body 각 A만(-A), 책등 면은 힌지까지 함께(좌철 90°-A / 우철 -90°-A).
   전이 시간은 body와 같은 --eve3d-dur을 써야 회전하는 동안 라벨만 튀지 않는다. */
.eve3d__dimLabel { position:absolute;top:50%;left:50%;padding:2px 5px;font-size:10.5px;font-weight:700;line-height:1;color:var(--eve3d-dim-label-color);letter-spacing:0;white-space:nowrap;border-radius:3px;background:var(--eve3d-dim-color);transition:transform var(--eve3d-dur, 0s) ease;transform:translate(-50%, -50%) rotateY(calc(-1 * var(--eve3d-angle, 0deg))); }
.eve3d__dim-spine-top .eve3d__dimLabel, .eve3d__dim-spine-bottom .eve3d__dimLabel { transform:translate(-50%, -50%) rotateY(calc(90deg - var(--eve3d-angle, 0deg))); }
eve-3d[spine-right] .eve3d__dim-spine-top .eve3d__dimLabel, eve-3d[spine-right] .eve3d__dim-spine-bottom .eve3d__dimLabel { transform:translate(-50%, -50%) rotateY(calc(-90deg - var(--eve3d-angle, 0deg))); }

/* 판형 가로(front data-w-mm) — 앞표지 평면 위쪽, 별도 transform 없음(z=0) */
.eve3d__dim-width { top:calc(var(--eve3d-dim-gap) * -1);left:0;width:100%; }

/* 판형 세로(front data-h-mm) — 앞표지 평면 오른쪽(좌철 기준, 책등 반대편) 세로선 */
.eve3d__dim-height { top:0;left:calc(100% + var(--eve3d-dim-gap));height:100%; }
.eve3d__dim-height .eve3d__dimLine { width:1px;height:100%; }
.eve3d__dim-height .eve3d__dimLine::before, .eve3d__dim-height .eve3d__dimLine::after { right:auto;left:-3px;width:7px;height:1px; }
.eve3d__dim-height .eve3d__dimLine::before { top:0; }
.eve3d__dim-height .eve3d__dimLine::after { top:auto;bottom:0; }

/* 책등 두께(spine data-w-mm) — .eve3d__bdr-spine과 동일한 힌지로 접혀 책등 면 위에 눕는다.
   위·아래 두 줄이라 기운 책의 양쪽 모서리에서 두께가 함께 읽힌다. */
.eve3d__dim-spine-top, .eve3d__dim-spine-bottom { left:calc(var(--eve3d-sw) / -2);width:var(--eve3d-sw);transform:rotate3d(0, 1, 0, -90deg) translate3d(calc(var(--eve3d-sw) / -2 + var(--eve3d-seam)), 0, 0); }
.eve3d__dim-spine-top { top:calc(var(--eve3d-dim-gap) * -1); }
.eve3d__dim-spine-bottom { bottom:calc(var(--eve3d-dim-gap) * -1); }

/* 우철(spine-right) — 책등 라인은 힌지 좌우·부호를 반전하고, 세로 치수선은 반대쪽으로 넘긴다 */
eve-3d[spine-right] .eve3d__dim-spine-top, eve-3d[spine-right] .eve3d__dim-spine-bottom { left:calc(100% - var(--eve3d-sw) / 2);transform:rotate3d(0, 1, 0, 90deg) translate3d(calc(var(--eve3d-sw) / 2 + var(--eve3d-seam)), 0, 0); }
eve-3d[spine-right] .eve3d__dim-height { left:auto;right:calc(100% + var(--eve3d-dim-gap)); }
