/* 리더 스타일 — 모든 책 공용.
   페이지 넘김은 scroll-snap 만 쓴다. JS 터치 핸들러는 단어 탭을 삼킨다(CLAUDE.md 절대 규칙 1).
   책장 넘김 연출은 스크롤 '위치를 읽어' 그리기만 한다 — 판정은 여전히 브라우저 것이다.

   ⚠ 새 클래스 이름은 프로젝트에서 유일해야 한다. `.sheet`(단어 뜻풀이 창)와 겹쳐
     넘어가는 종이가 통째로 사라진 적이 있다 → `.turnsheet` · `.turnface`. */

:root {
  --paper: #fbf5e7;          /* 펼친 면 */
  --paper-warm: #f6eeda;     /* 책등 쪽으로 아주 살짝 가라앉는 톤 */
  --paper-edge: #ddd0b6;     /* 책 바깥 바탕 (책상 위 느낌) */
  --ink: #332c24;
  --muted: #8a7c68;
  --accent: #b0512c;
  --key-line: rgba(176, 81, 44, .5);
  --sheet: #fffdf6;
  --fold-ink: 58, 42, 26;    /* 접힘 그림자·책등 그림자에 같이 쓰는 갈색 */
  --shadow: 0 -8px 40px rgba(var(--fold-ink), .22);
  --body: clamp(17px, 1.1vw + 1.75vh, 23px);
}

/* 자동 다크 모드는 쓰지 않는다. 종이책 느낌이 이 리더의 정체성이라
   화면이 어두워지면 삽화·종이색·접힘 그림자가 전부 따로 논다. */

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--paper-edge);
  color: var(--ink);
  font-family: Georgia, 'Iowan Old Style', 'Times New Roman', serif;
  -webkit-text-size-adjust: 100%;
  overscroll-behavior: none;
}

.reader { position: relative; display: flex; flex-direction: column; height: 100dvh; width: 100%; overflow: hidden; }

/* ── 상단 바 */
.bar {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: .75rem;
  padding: .45rem clamp(.7rem, 2.5vw, 1.4rem);
  background: var(--paper-edge);
  font-size: .82rem; color: #6f6249;
  font-family: system-ui, -apple-system, 'Segoe UI', sans-serif;
}
.bar-title { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar button {
  font: inherit; color: inherit; cursor: pointer;
  background: none; border: 1px solid currentColor; border-radius: 999px;
  padding: .2rem .7rem; opacity: .75;
}
.bar button:hover { opacity: 1; }
.bar-count { font-variant-numeric: tabular-nums; }

/* ── 책: 가로 스크롤 스냅. 스냅 단위는 '펼침면'이고 그 안에 페이지가 1장 또는 2장 들어간다. */
.book {
  flex: 1 1 auto;
  min-width: 0;                        /* 없으면 flex 아이템이 27쪽 전체 너비로 부풀어 화면을 넘긴다 */
  display: flex;
  overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x mandatory;
  overscroll-behavior-x: contain;      /* iOS 뒤로가기 스와이프 차단 */
  scrollbar-width: none;
  background: var(--paper-edge);
}
.book::-webkit-scrollbar { display: none; }

/* 스냅 단위. 가로로 늘어서 있는 건 '스크롤이라는 입력'을 받기 위한 뼈대일 뿐이다.
   눈에 보이는 자리는 아래 view-timeline 이 정한다. */
.spread {
  flex: 0 0 100%;
  scroll-snap-align: center;
  scroll-snap-stop: always;
  height: 100%;
}

/* 펼쳐 놓은 책 한 면. 3D 무대 노릇을 한다.
   overflow: hidden 이 두 가지를 동시에 해결한다 —
   넘어가는 종이가 화면 밖으로 나가면 잘리고(책등이 화면 끝이라 그게 맞다),
   회전이 가로 스크롤 폭을 늘려 스냅을 어긋나게 하는 것도 막는다.
   배경은 깔지 않는다 — 종이가 넘어가 비워진 자리로 다음 장이 비쳐 보여야 한다. */
.leaf {
  display: flex;
  height: 100%; width: 100%;
  position: relative;
  perspective: 1800px;
  overflow: hidden;
}

/* 실제로 넘어가는 종이 한 장. 2단에서는 오른쪽 장(축이 책등), 1단에서는 그 페이지 전체. */
.turnsheet {
  flex: 1 1 0;
  min-width: 0;
  position: relative;
  transform-origin: left center;
  transform-style: preserve-3d;
}

.turnface {
  position: absolute; inset: 0;
  display: flex;
  backface-visibility: hidden;
  background: var(--paper);
}
.turnface.back { transform: rotateY(180deg); }
.turnface > .page { flex: 1 1 auto; }

/* 넘어가는 동안 종이에 지는 그림자. 모로 설 때(90도) 가장 어둡다.
   pointer-events 를 반드시 끈다 — 이 한 줄이 없으면 단어를 덮는다. */
.turnface::after {
  content: '';
  position: absolute; inset: 0; z-index: 5;
  pointer-events: none;
  opacity: 0;
  background: linear-gradient(90deg,
    rgba(var(--fold-ink), 0) 26%, rgba(var(--fold-ink), .20) 70%, rgba(var(--fold-ink), .55) 100%);
}
.turnface.back::after {
  background: linear-gradient(270deg,
    rgba(var(--fold-ink), 0) 26%, rgba(var(--fold-ink), .22) 70%, rgba(var(--fold-ink), .58) 100%);
}

/* ══ 책장 넘김 — 브라우저가 스크롤에 맞춰 직접 굴린다 ══════════════
   JS 로 스크롤 이벤트를 받아 매 프레임 다시 그리면 안 된다. 모바일에서 손가락으로 미는
   스크롤은 합성 스레드가 굴리고 JS 는 메인 스레드라, 종이가 한 박자 전 자리에 멈춰
   화면이 어긋나 벌어진다(2026-08-05 실기기에서 확인). view-timeline 은 브라우저가
   같은 스레드에서 굴리므로 원리적으로 어긋날 수가 없다.

   진행도: 0 = 오른쪽에서 들어오기 직전 · 0.5 = 화면에 펼쳐짐 · 1 = 왼쪽으로 다 넘어감.
   지원하지 않는 브라우저(구형 사파리 등)는 이 블록이 통째로 무시되어
   원래의 scroll-snap 미끄러짐으로 읽힌다 — 읽는 데는 아무 지장이 없다. */
@supports (animation-timeline: view()) {
  .spread {
    view-timeline-name: --spread-run;
    view-timeline-axis: x;
    animation-name: spread-stack;
    animation-timeline: --spread-run;
    animation-duration: auto;
    animation-timing-function: linear;
    animation-fill-mode: both;
  }
  /* 넘어가는 장이 다음 장 위에 있어야 한다.
     그리고 범위 밖(아직 안 온 면 · 이미 넘어간 면)은 감춘다 — 안 감추면 진행도가 0/1 에서
     멈춘 채 스크롤을 따라 흘러다니며 지금 보는 면 위에 옛 내용을 겹친다. 탭도 가로챈다. */
  @keyframes spread-stack {
    0%    { z-index: 1; visibility: hidden; }
    1%    { z-index: 1; visibility: visible; }
    50%   { z-index: 2; visibility: visible; }
    99%   { z-index: 2; visibility: visible; }
    100%  { z-index: 2; visibility: hidden; }
  }

  /* 책을 제자리에 세운다 — 스크롤이 흘러도 면은 화면에 머문다 */
  .leaf {
    animation-name: leaf-stay;
    animation-timeline: --spread-run;
    animation-duration: auto;
    animation-timing-function: linear;
    animation-fill-mode: both;
  }
  /* 진행도 0 일 때 면은 화면 한 칸 오른쪽에 있으므로 왼쪽으로 한 칸 당겨야 제자리다.
     진행도 1 이면 한 칸 왼쪽에 있으니 오른쪽으로 당긴다. 부호를 뒤집으면 면들이 화면 밖으로 흩어진다. */
  @keyframes leaf-stay {
    from { transform: translateX(-100%); }
    to   { transform: translateX(100%); }
  }

  /* 책등을 축으로 종이가 넘어간다 */
  .turnsheet {
    animation-name: sheet-turn;
    animation-timeline: --spread-run;
    animation-duration: auto;
    animation-timing-function: linear;
    animation-fill-mode: both;
  }
  @keyframes sheet-turn {
    0%, 50% { transform: rotateY(0deg); }
    100%    { transform: rotateY(-180deg); }
  }

  .turnface::after {
    animation-name: face-shade;
    animation-timeline: --spread-run;
    animation-duration: auto;
    animation-timing-function: linear;
    animation-fill-mode: both;
  }
  @keyframes face-shade {
    0%, 50% { opacity: 0; }
    75%     { opacity: .9; }
    100%    { opacity: 0; }
  }
}

/* 뒷면에 복제해 넣은 다음 장. 진짜 단어는 앞면에만 있어야 한다. */
.turnface.back .page { pointer-events: none; }

.page {
  flex: 1 1 0;
  min-width: 0;
  height: 100%;
  overflow-y: auto;
  /* 종이 결. 한 방향으로만 그으면 '줄 쳐진 종이'로 읽히고 배율에 따라 모아레가 진다 —
     주기가 다른 두 방향을 아주 옅게 겹쳐 섬유처럼 보이게 한다. */
  background:
    repeating-linear-gradient(93deg, rgba(150, 120, 70, .013) 0 1px, transparent 1px 7px),
    repeating-linear-gradient(3deg, rgba(150, 120, 70, .010) 0 1px, transparent 1px 11px),
    linear-gradient(var(--paper-warm), var(--paper) 20%);
  padding: clamp(1.1rem, 3.2vw, 2.6rem) clamp(1.1rem, 3.4vw, 3rem) clamp(2rem, 5vw, 3rem);
}

/* 책등 그림자 — 종이가 안쪽으로 말려 들어가는 자리.
   1단은 왼쪽이 책등, 2단은 가운데가 책등이라 마주 보는 두 쪽에 넣는다. */
.leaf > .turnsheet:only-child .page   { box-shadow: inset 16px 0 26px -18px rgba(var(--fold-ink), .55); }
.leaf > .page:first-child         { box-shadow: inset -16px 0 26px -18px rgba(var(--fold-ink), .5); }
.leaf > .page + .turnsheet .page      { box-shadow: inset 16px 0 26px -18px rgba(var(--fold-ink), .5); }
.leaf > .page + .turnsheet::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 1px; z-index: 6;
  background: rgba(var(--fold-ink), .16); pointer-events: none;
}

/* 이북처럼 위에서부터 내려온다. 한 줄 길이는 34em 으로 묶어 가로로만 가운데. */
.page.text { display: flex; flex-direction: column; justify-content: flex-start; align-items: center; }
.page.text > * { width: 100%; max-width: 34em; }

/* ── 본문 */
.page h2 {
  margin: 0 0 1.1em;
  font-size: 1.02em; font-weight: normal; font-style: italic;
  color: var(--accent); letter-spacing: .01em;
}
.page p { margin: 0 0 .95em; font-size: var(--body); line-height: 1.78; text-wrap: pretty; }
.page p:last-child { margin-bottom: 0; }

.w { cursor: pointer; border-radius: 3px; }
.w.k { border-bottom: 1.5px dotted var(--key-line); }
.w.on { background: var(--accent); color: var(--paper); border-bottom-color: transparent; }

.page figure { margin: 1.4em 0; }
.page figure img {
  display: block; width: 100%; height: auto; border-radius: 3px;
  box-shadow: 0 1px 0 rgba(var(--fold-ink), .18), 0 6px 18px -10px rgba(var(--fold-ink), .5);
}

/* ── 전면 삽화 페이지 */
.page.plate {
  padding: 0;
  background: #191310;
  display: flex; align-items: center; justify-content: center;
}
.page.plate img { max-width: 100%; max-height: 100%; object-fit: contain; }

/* ── 표지 */
.page.cover {
  padding: 0; position: relative; overflow: hidden;
  display: flex; align-items: flex-end;
  background: #191310;
}
.page.cover img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: .62; }
.cover-text {
  position: relative; width: 100%;
  padding: clamp(1.4rem, 5vw, 3rem);
  background: linear-gradient(to top, rgba(10, 8, 7, .93) 35%, rgba(10, 8, 7, 0));
  color: #f6ecda;
}
.cover-text h1 { margin: 0 0 .4rem; font-size: clamp(1.5rem, 3.6vw + .6rem, 2.9rem); line-height: 1.18; }
.cover-text .sub { margin: 0; color: #d8c6a8; font-size: .95rem; }
.cover-text .ko { margin: .5rem 0 0; color: #b9a68a; font-size: .85rem;
  font-family: system-ui, -apple-system, 'Malgun Gothic', sans-serif; }

/* ── 가장자리 탭 힌트. 판정은 reader.js 가 좌표로 하고(단어가 언제나 우선),
      이건 "여기를 누르면 넘어간다"를 알려주는 그림일 뿐이라 절대 클릭을 먹지 않는다. */
.edge-hint {
  position: absolute; top: 50%; z-index: 4;
  transform: translateY(-50%);
  pointer-events: none;
  color: rgba(var(--fold-ink), .28);
  font-size: 1.6rem; line-height: 1;
  font-family: system-ui, -apple-system, sans-serif;
  transition: opacity .25s ease;
}
.edge-hint.prev { left: clamp(.35rem, 1.6vw, 1rem); }
.edge-hint.next { right: clamp(.35rem, 1.6vw, 1rem); }
.edge-hint[hidden] { display: none; }

/* ── 단어 팝오버 (바닥 시트: 위치 계산이 없어 화면 밖으로 잘릴 일이 없다)
      ⚠ 여기의 .sheet 는 화면 아래에서 올라오는 뜻풀이 창이다.
        넘어가는 종이(.turnsheet)와 이름이 겹치면 종이가 position:fixed 를 뒤집어써 사라진다. */
.sheet {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
  background: var(--sheet); box-shadow: var(--shadow);
  border-radius: 18px 18px 0 0;
  padding: 1rem clamp(1rem, 4vw, 2rem) calc(1rem + env(safe-area-inset-bottom));
  transform: translateY(102%); transition: transform .18s ease-out;
  font-family: system-ui, -apple-system, 'Malgun Gothic', sans-serif;
}
.sheet.open { transform: none; }
.sheet-head { display: flex; align-items: baseline; gap: .6rem; margin-bottom: .55rem; }
.sheet-word { font-family: Georgia, serif; font-size: 1.45rem; color: var(--accent); }
.sheet-ko { font-size: 1.12rem; }
.sheet-ja { margin: .1rem 0 0; color: var(--muted); font-size: .98rem; }
.sheet-ja b { font-weight: 600; color: var(--ink); }
.sheet-actions { display: flex; gap: .5rem; margin-top: .9rem; }
.sheet-actions button {
  font: inherit; cursor: pointer; color: var(--ink);
  background: var(--paper-edge); border: 0; border-radius: 999px; padding: .5rem 1.1rem;
}
.sheet-actions button.on { background: var(--accent); color: var(--sheet); }
.sheet-close { margin-left: auto; background: none !important; color: var(--muted) !important; }

/* ── 단어장 */
.vocab {
  position: fixed; inset: 0; z-index: 30;
  background: var(--paper); overflow-y: auto;
  padding: 1rem clamp(1rem, 4vw, 2rem) 3rem;
  font-family: system-ui, -apple-system, 'Malgun Gothic', sans-serif;
  transform: translateX(101%); transition: transform .2s ease-out;
}
.vocab.open { transform: none; }
.vocab-head { display: flex; align-items: center; gap: .8rem; margin-bottom: 1rem; }
.vocab-head h2 { margin: 0; font-size: 1.15rem; flex: 1 1 auto; }
.vocab-head button { font: inherit; cursor: pointer; background: none; border: 0; color: var(--muted); font-size: 1.4rem; }
.vocab ul { list-style: none; margin: 0; padding: 0; }
.vocab li { display: flex; align-items: center; gap: .8rem; padding: .7rem 0; border-bottom: 1px solid var(--paper-edge); }
.vocab li > div { flex: 1 1 auto; min-width: 0; }
.vocab .v-en { font-family: Georgia, serif; font-size: 1.05rem; color: var(--accent); }
.vocab .v-ko { font-size: .92rem; }
.vocab .v-ja { font-size: .82rem; color: var(--muted); }
.vocab li button { font: inherit; cursor: pointer; background: none; border: 0; color: var(--muted); font-size: 1.1rem; padding: .3rem .5rem; }
.vocab .empty { color: var(--muted); font-size: .92rem; line-height: 1.7; }

/* 멀미·저사양 대비. 넘김 연출은 장식이라 꺼도 읽는 데 아무 지장이 없다 —
   이때는 원래대로 옆으로 미끄러지는 scroll-snap 이 된다. */
@media (prefers-reduced-motion: reduce) {
  .spread, .leaf, .turnsheet, .turnface::after { animation: none; }
  .turnsheet { transform: none; }
  .turnface::after { opacity: 0; }
}
