:root {
  --navy: #1a3a5c; --navy-deep: #0f2540; --paper: #faf6ee;
  --raz-purple: #4A0A8A; --raz-navy: #243E55; --raz-blue: #497CAA;
  --paper-warm: #f4ebd9; --ink: #1f1d1a; --ink-soft: #4a4642;
  --blue: #2e6e9e; --orange: #e86a3a; --purple: #6b4a7a;
  --green: #2e7a4a; --danger: #c4533a; --border: rgba(0,0,0,0.1);
  --highlight: #fff3a0;

  /* ── 부속 페이지(속표지·words to know·문법) 공통 글자 크기 (v202) ──
     세 페이지를 각각 다른 시기에 만들면서 한글이 22 / 16 / 19px로 제각각이었고
     영어·로마자는 전부 13px로 성인 독자가 읽기엔 작았다. 여기 한 곳에서 관리한다.
     ★ 새 부속 페이지를 만들면 px를 직접 쓰지 말고 이 변수를 쓸 것. */
  --aux-title: 26px;   /* 페이지 제목 (Your Korean So Far / words to know / 문법)
                          소문자만 있는 "words to know"는 위로 솟는 획이 k·t뿐이라
                          같은 px에서도 20~25% 작아 보인다 → 셋을 같은 값으로 묶어야
                          비로소 같아 보인다 */
  --aux-sub:   14px;   /* 부제 (지금까지 배운 것) */
  --aux-ko:    20px;   /* 본문 한글 (Gowun Batang 굵게) — 기준값 */
  --aux-en:    15px;   /* 영어 뜻 — 실제로 읽는 줄. 한글의 0.75배 */
  --aux-rom:   14px;   /* 로마자 — 발음 참고용이라 뜻보다 한 단계 아래 */
  --aux-tag:   13px;   /* 태그·잔글씨 (a word / + describing / you are here) */
  --aux-label: 12px;   /* 자간 넓은 대문자 라벨 (NOUNS) — 키우면 뜻보다 시끄러워짐 */

  /* 베이지 글자색. 기존 #A89878은 흰 배경 대비 2.2:1로 접근성 기준(4.5:1)의 절반이라
     "작다"기보다 "안 읽힌다"에 가까웠다. 4.2:1로 올리되 색 계열은 그대로. */
  --aux-beige: #887F6F;   /* ★ v222: 시안에 맞춰 #8A7A5A → #887F6F (부속 페이지 5곳 공용) */
}
* { box-sizing: border-box; margin: 0; padding: 0; -webkit-tap-highlight-color: transparent; }
html, body { height: 100%; background: #0e2426; /* Bright Playground(다크): 하단 안전영역 = 책장 배경과 통일 */ font-family: 'Gowun Batang', serif; color: var(--ink); overflow: hidden; -webkit-user-select: none; user-select: none; }
/* ★v125: 실행 직후 뷰포트 높이는 <body> 시작부의 JS가 px로 고정 (v123 방식 회수) */
input, textarea, select { -webkit-user-select: text; user-select: text; }
button { font-family: inherit; cursor: pointer; }

/* ─── APP SHELL ─── */
#app { height: 100%; /* ★v123: body가 화면에 고정되므로 100%가 실제 화면 높이 (기존 100vh/100dvh) */ max-width: 480px; margin: 0 auto; background: var(--paper); display: flex; flex-direction: column; overflow: hidden; box-shadow: 0 0 60px rgba(0,0,0,0.4); }

/* ─── TOP BAR ─── */
.topbar { background: var(--raz-purple); color: white; padding: 14px 16px; padding-top: max(14px, env(safe-area-inset-top)); display: flex; align-items: center; justify-content: space-between; flex-shrink: 0; z-index: 10; gap: 8px; }
.topbar-title { font-weight: 700; font-size: 17px; flex: 1; min-width: 0; text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.topbar-btn { background: transparent; border: none; color: white; padding: 4px 8px; display: flex; align-items: center; gap: 4px; font-size: 14px; font-family: 'Fraunces', serif; opacity: 0.95; flex-shrink: 0; }
.topbar-btn.pill { background: var(--orange); padding: 6px 14px; border-radius: 100px; font-weight: 600; font-size: 12px; }
.topbar-btn svg { width: 18px; height: 18px; }
/* 리더 화면 전용: 닫기/편집 버튼은 아이콘만 표시 */
.topbar[data-topbar="reader"] .topbar-btn .label-text { display: none; }
.topbar[data-topbar="reader"] .topbar-btn svg { width: 22px; height: 22px; }
.topbar[data-topbar="reader"] .topbar-btn { padding: 6px 10px; }

/* ─── SCREENS ─── */
.screen { flex: 1; overflow-y: auto; display: none; -webkit-overflow-scrolling: touch; padding-bottom: max(16px, env(safe-area-inset-bottom)); }
.screen.active { display: block; }
#screen-reader { background: white; }
/* 리더 화면이 비활성일 땐 공통 .screen 규칙(display:none) 유지 */
#screen-reader.screen { overflow: hidden; padding-bottom: 0; }
/* 리더 화면이 활성일 때만: 스크롤 해제 + flex로 부모(#app) 높이를 끝까지 채움 (height:100%는 flex item에서 무시되므로 flex:1 사용) */
#screen-reader.screen.active { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }

/* ─── LOGIN SCREEN ─── */

/* 회원가입용 기본 스타일 */
.login-wrap {
  min-height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: center;
  padding: 40px 32px;
  background: linear-gradient(160deg, var(--paper) 60%, var(--paper-warm));
}

/* ─── 로그인 전용 (★ 2026-09-02 새 화면) ───────────────────────
   가족 사진 → 실제 책 표지 다섯 장. 배경도 남색 → 책의 종이색.
   ⚠️ 상단 바도 함께 남색으로 내린다 — 보라색은 종이색과 안 맞는다.
   ⚠️ 회원가입·비밀번호 찾기 화면은 예전 .login-wrap 을 그대로 쓴다. */
.topbar[data-topbar="login"] { background: var(--navy); }

.login-wrap.login-main {
  justify-content: flex-start;
  padding: 22px 20px max(22px, env(safe-area-inset-bottom));
  gap: 10px;
}

/* 표지 다섯 장 — 한 줄. 좁은 화면에서도 다섯이 다 보이게 flex 로 나눈다. */
.login-covers {
  display: flex;
  gap: 6px;
  width: 100%;
  max-width: 330px;
  flex-shrink: 0;
}
.login-covers img {
  flex: 1 1 0;
  min-width: 0;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border-radius: 7px;
  border: 2px solid #fff;
  box-shadow: 0 5px 14px rgba(0,0,0,0.16);
  background: var(--paper-warm);
}

.login-wrap.login-main .login-title {
  font-family: 'Fraunces', serif;
  font-style: italic;
  font-size: 32px;
  color: var(--navy-deep);
  margin: 6px 0 0;
}
.login-wrap.login-main .login-sub {
  font-size: 14px;
  margin: 0 0 4px;
  text-align: center;
}

/* 소셜 로그인 단추
   ⚠️ `display:flex`가 HTML의 `hidden`을 이긴다 — Supabase에서 안 켠 제공자를
      감추려면 반드시 이 한 줄이 있어야 한다(★ 2026-09-03). */
.oauth-btn[hidden], .login-or[hidden] { display: none !important; }
.oauth-btn {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 12px;
  margin-bottom: 9px;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 9px;
  font-family: 'Gowun Batang', serif;
  font-size: 15px;
  font-weight: 700;
  color: var(--ink);
  cursor: pointer;
}
.oauth-btn:active { opacity: .85; }
.oauth-btn.oauth-fb { background: #1877F2; border-color: #1877F2; color: #fff; }
.oauth-icon { width: 19px; height: 19px; flex-shrink: 0; }

/* OR 구분선 */
.login-or {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 14px 0 12px;
  font-family: 'Fraunces', serif;
  font-size: 11px;
  letter-spacing: 0.14em;
  color: var(--aux-beige, #887F6F);
}
.login-or::before, .login-or::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border);
}

/* 「New here? Create an account」 / 「Forgot your password?」 */
.login-alt { text-align: center; margin-top: 12px; font-family: 'Fraunces', serif; font-size: 13px; color: var(--ink-soft); }
.login-alt button {
  background: transparent; border: none; padding: 0;
  font-family: 'Fraunces', serif; font-size: 13px; font-weight: 700;
  color: var(--blue); text-decoration: underline; cursor: pointer;
}
.login-alt-quiet { margin-top: 7px; }
.login-alt-quiet button { font-weight: 400; color: var(--ink-soft); }

.login-legal {
  margin-top: auto;
  padding-top: 16px;
  font-family: 'Fraunces', serif;
  font-size: 11px;
  line-height: 1.5;
  text-align: center;
  color: var(--aux-beige, #887F6F);
}
.login-legal a { color: inherit; }

/* 폼 카드 (크림색) */
.login-form {
  width: 100%;
  max-width: 320px;
}
.login-wrap.login-main .login-form { max-width: 330px; }

.login-field { margin-bottom: 14px; }
.login-label {
  display: block;
  font-size: 11px;
  font-weight: 700;
  color: var(--ink-soft);
  text-transform: uppercase;
  letter-spacing: 1px;
  margin-bottom: 6px;
  font-family: 'Fraunces', serif;
}
.login-input {
  width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: 'Gowun Batang', serif;
  font-size: 15px;
  background: white;
  color: var(--ink);
}
.login-input:focus { outline: 2px solid var(--orange); border-color: transparent; }
.login-btn {
  width: 100%;
  padding: 14px;
  background: var(--navy);
  color: white;
  border: none;
  border-radius: 8px;
  font-family: 'Gowun Batang', serif;
  font-size: 15px;
  font-weight: 700;
  margin-top: 8px;
}
.login-btn:active { opacity: .85; }
.login-error {
  color: var(--danger);
  font-size: 13px;
  text-align: center;
  margin-top: 10px;
  font-family: 'Fraunces', serif;
  min-height: 20px;
}

/* ─── FILTER BAR ─── */
.filter-bar { background: var(--raz-navy); padding: 10px 14px; display: flex; gap: 6px; border-bottom: 1px solid rgba(255,255,255,0.12); flex-shrink: 0; overflow-x: auto; }
.filter-tab { background: transparent; border: 1px solid rgba(255,255,255,0.35); color: rgba(255,255,255,0.85); font-family: 'Fraunces', serif; font-weight: 600; font-size: 12px; padding: 6px 14px; border-radius: 100px; flex-shrink: 0; }
.filter-tab.active { background: white; color: var(--raz-navy); border-color: white; }
/* 관리자/편집자 전용 필터(초안·검토중·A·B·C) — 주황 점선으로 일반 필터와 구별.
   출시 전에 아래 한 줄을 추가하면 전부 숨길 수 있음:  .admin-filter { display: none; } */

/* ★ v259 — 「독자 모드」. 설정 → 화면 모드 에서 켜면 body 에 .view-reader 가 붙는다.
   위의 «출시 때 지울 한 줄»을 만드는 동안에도 켜 볼 수 있게 한 스위치다.
   ⚠️ 출시할 때는 이 규칙을 지우는 게 아니라 .admin-filter{display:none}을 따로 넣는다
   (독자 모드를 끈 채 출시되는 사고를 막기 위해). */
/* ★ 2026-09-02 — «편집자가 아닌 사람»에게 감추는 것 (검수자·독자).
   ⚠️ .admin-filter 와 다르다 — admin-filter 는 «독자 모드일 때» 감추는 것이라
      편집자가 독자 모드를 미리 보다가 되돌아올 길(화면 모드 스위치)까지 사라진다.
      editor-only 는 «권한»으로 감춘다. 판정은 DB 의 is_editor() 가 한다. */
body.role-viewer .editor-only { display: none !important; }

body.view-reader .admin-filter { display: none !important; }
.filter-tab.admin-filter { border-style: dashed; border-color: var(--orange); color: var(--orange); }
.filter-tab.admin-filter.active { background: var(--orange); color: white; border-color: var(--orange); border-style: solid; }
/* ★v110: 제작자 필터 — 보라색 점선으로 레벨/상태 칩과 구별 */
.filter-tab.author-filter { border-color: #b39ddb; color: #d1c4e9; }
.filter-tab.author-filter.active { background: #b39ddb; color: var(--raz-navy); border-color: #b39ddb; border-style: solid; }
.filter-divider { width: 1px; align-self: stretch; background: var(--border); margin: 2px 2px; flex-shrink: 0; }

/* ★v173: 칩 안의 권수 — 라벨보다 작고 흐리게(레벨 글자가 주인공, 숫자는 보조) */
.filter-count { font-size: 10px; font-weight: 600; opacity: 0.65; margin-left: 1px; font-variant-numeric: tabular-nums; }
.filter-tab.active .filter-count { opacity: 0.75; }
/* 아직 책이 없는 레벨은 흐리게 — 눌러봐야 빈 화면이라는 걸 미리 알려준다 */
.filter-tab.is-empty { opacity: 0.45; }

/* ─── BOOK GRID ─── */
.book-grid { padding: 14px 64px 100px; display: grid; grid-template-columns: 1fr; gap: 16px; background: var(--raz-blue); min-height: 100%; }
/* 무한 스크롤 sentinel — bookGrid 다음에 위치, 보이면 로드 */
.book-grid-sentinel {
  padding: 20px 12px 80px;
  text-align: center;
}
.book-grid-sentinel-spinner {
  display: inline-block;
  padding: 10px 18px;
  font-family: 'Fraunces', serif;
  font-size: 12px;
  color: var(--ink-soft);
  background: var(--paper-warm);
  border-radius: 100px;
}
.book-card { background: white; border-radius: 8px; overflow: hidden; box-shadow: 0 4px 14px rgba(0,0,0,0.18); cursor: pointer; transition: transform 0.15s; }
.book-card:active { transform: scale(0.97); }
.book-cover { width: 100%; aspect-ratio: 4/3; background-size: cover; background-position: center top; background-color: var(--paper-warm); display: flex; align-items: center; justify-content: center; font-size: 32px; color: var(--ink-soft); }
.book-info { padding: 10px 14px; }
.book-title { font-size: 18px; font-weight: 700; color: var(--ink); line-height: 1.3; margin-bottom: 8px; min-height: 34px; text-align: center; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
/* ★v241: 레벨 배지와 작업 상태가 너무 작아 안 읽혔다(배지 9px · 상태 10px).
   카드가 커져도 이 줄만 그대로여서 상대적으로 더 작아 보였다. */
.book-meta { display: flex; justify-content: space-between; align-items: center; font-size: 13px; color: var(--ink-soft); font-family: 'Fraunces', serif; }
/* ⚠️ letter-spacing을 빼는 이유: 배지 글자는 「ㄱ」 한 글자다.
   자간은 마지막 글자 «뒤»에도 붙어서, 한 글자짜리 배지가 왼쪽으로 치우쳐 보였다. */
.level-badge { background: var(--orange); color: white; font-weight: 700; font-size: 14px; padding: 3px 12px; border-radius: 100px; letter-spacing: 0; }
.level-badge.b { background: var(--blue); }
.level-badge.c { background: var(--purple); }
/* ★ 2026-08-30 — 레벨별 배지 색 «21단 사다리» (Raz 방식 — 레벨마다 제 색).
   따뜻함(초급) → 빨강·자주 → 보라·파랑 → 청록·초록(졸업) 순서로 한 바퀴.
   등급 3색(.b/.c)보다 뒤에 두어 chosung_tag 가 있으면 이쪽이 이긴다.
   흰 글자가 읽히도록 밝기를 40~54%로 맞췄다(초록 계열은 더 어둡게). */
.level-badge.lv-g   { background: hsl(35, 75%, 48%); }
.level-badge.lv-n   { background: hsl(24, 72%, 50%); }
.level-badge.lv-d   { background: hsl(12, 70%, 50%); }
.level-badge.lv-r   { background: hsl(0, 65%, 52%); }
.level-badge.lv-m   { background: hsl(348, 62%, 50%); }
.level-badge.lv-b   { background: hsl(332, 60%, 48%); }
.level-badge.lv-s   { background: hsl(316, 55%, 48%); }
.level-badge.lv-ng  { background: hsl(300, 48%, 46%); }
.level-badge.lv-j   { background: hsl(285, 50%, 50%); }
.level-badge.lv-ch  { background: hsl(270, 52%, 52%); }
.level-badge.lv-k   { background: hsl(255, 55%, 54%); }
.level-badge.lv-t   { background: hsl(240, 52%, 54%); }
.level-badge.lv-p   { background: hsl(225, 58%, 48%); }
.level-badge.lv-h   { background: hsl(210, 62%, 44%); }
.level-badge.lv-a   { background: hsl(197, 68%, 40%); }
.level-badge.lv-ya  { background: hsl(184, 55%, 36%); }
.level-badge.lv-eo  { background: hsl(170, 48%, 34%); }
.level-badge.lv-yeo { background: hsl(155, 45%, 34%); }
.level-badge.lv-o   { background: hsl(140, 42%, 34%); }
.level-badge.lv-yo  { background: hsl(125, 40%, 33%); }
.level-badge.lv-u   { background: hsl(110, 38%, 33%); }
.level-badge.lv-tmp { background: #8a8a8a; }
.status-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--border); display: inline-block; }
.status-dot.published { background: var(--green); }
/* ★v234 작업 상태 — 대기 · 작업중 · 검수 대기 · 완료.
   색만으로 구분하지 않고 글자를 함께 두어, 색을 구별하기 어려운 사람도 읽을 수 있게 한다. */
.status-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
/* ★v237: 접이식 요약이 «채워야 함»을 알릴 때 */
.edit-collapse-sum.warn { color: var(--danger); font-weight: 600; }
.work-state { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.work-state .work-state-label { font-weight: 600; font-size: 13px; }
/* 담당 편집자 — 상태 옆 작은 딱지. 이름이 길면 줄임표로 잘라 카드가 밀리지 않게. */
.work-who {
  max-width: 92px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  padding: 2px 8px; border-radius: 8px;
  font-size: 12px;
}

/* ─── EMPTY + FAB ─── */
.empty-state { text-align: center; padding: 60px 30px; color: var(--ink-soft); }
.empty-icon { font-size: 48px; margin-bottom: 12px; opacity: 0.4; }
.empty-title { font-size: 16px; font-weight: 700; color: var(--ink); margin-bottom: 6px; }
.empty-text { font-size: 13px; line-height: 1.6; }
/* ★v120: 하단 중앙 알약 → 우측 하단 원형 + 버튼 (Repite 스타일, 주황 유지) */
.fab { position: fixed; bottom: max(22px, env(safe-area-inset-bottom)); right: max(22px, calc(50vw - 240px + 22px)); background: var(--orange); color: white; border: none; width: 64px; height: 64px; padding: 0; border-radius: 50%; box-shadow: 0 8px 20px rgba(232,106,58,0.5); display: flex; align-items: center; justify-content: center; z-index: 100; }
.fab:active { transform: scale(0.94); }
.fab svg { width: 28px; height: 28px; }

/* ─── Pull-to-refresh ─── */
.ptr-indicator {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 0;
  overflow: hidden;
  color: rgba(255,255,255,0.72); /* v140 다크 책장 위 — 기존 라이트 색은 밝은 베이지 띠로 보였음 */
  font-family: 'Fraunces', serif;
  font-size: 13px;
  transition: height 0.18s ease-out;
  background: transparent;
}
.ptr-indicator.pulling { height: var(--ptr-pull, 0px); transition: none; }
.ptr-indicator.ready { color: var(--orange); }
.ptr-indicator.refreshing {
  height: 48px;
}
.ptr-indicator svg {
  width: 16px;
  height: 16px;
  transition: transform 0.2s;
}
.ptr-indicator.ready svg { transform: rotate(180deg); }
.ptr-indicator.refreshing svg {
  animation: ptr-spin 0.9s linear infinite;
}
@keyframes ptr-spin { from { transform: rotate(0); } to { transform: rotate(360deg); } }

/* ─── FORM ELEMENTS ─── */
.form-page { padding: 18px 18px 100px; }
.form-section { margin-bottom: 22px; }
.form-label { display: block; font-size: 11px; font-weight: 700; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 1px; margin-bottom: 6px; font-family: 'Fraunces', serif; }
.form-input, .form-textarea, .form-select { width: 100%; padding: 10px 12px; border: 1px solid var(--border); border-radius: 8px; font-family: 'Gowun Batang', serif; font-size: 15px; background: white; color: var(--ink); }
.form-textarea { min-height: 90px; resize: vertical; line-height: 1.6; }
.form-input:focus, .form-textarea:focus, .form-select:focus { outline: 2px solid var(--orange); border-color: transparent; }
.level-picker { display: flex; gap: 8px; }
.level-opt { flex: 1; padding: 12px 8px; border: 2px solid var(--border); border-radius: 8px; background: white; cursor: pointer; text-align: center; transition: all 0.15s; }
.level-opt.sel { border-color: var(--orange); background: #fff3ec; }
.level-opt-lbl { font-family: 'Fraunces', serif; font-weight: 700; font-size: 16px; color: var(--navy); }
.level-opt-sub { font-size: 10px; color: var(--ink-soft); margin-top: 2px; }
/* 책 난이도 (ㄱ~ㅎ) 선택 그리드 — 7열 × 2행 */
.chosung-picker { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.chosung-opt { padding: 8px 4px; border: 2px solid var(--border); border-radius: 6px; background: white; cursor: pointer; text-align: center; font-family: 'Gowun Batang', serif; font-weight: 700; font-size: 16px; color: var(--navy); transition: all 0.15s; }
.chosung-opt.sel { border-color: var(--orange); background: #fff3ec; color: var(--orange); }

/* ─── PHOTO AREA ─── */
.photo-upload { border: 2px dashed var(--border); border-radius: 8px; padding: 28px 20px; text-align: center; background: var(--paper-warm); cursor: pointer; color: var(--ink-soft); font-size: 13px; }
.photo-preview { width: 100%; aspect-ratio: 4/3; background-size: cover; background-position: center; background-color: var(--paper-warm); border-radius: 8px; position: relative; }
.photo-preview.portrait { aspect-ratio: 3/4; }
.photo-remove { position: absolute; top: 8px; right: 8px; background: rgba(0,0,0,0.6); color: white; border: none; width: 32px; height: 32px; border-radius: 50%; display: flex; align-items: center; justify-content: center; }
.photo-remove svg { width: 16px; height: 16px; }

/* ─── PAGE CARDS ─── */
.page-card { background: white; border: 1px solid var(--border); border-radius: 8px; padding: 10px; margin-bottom: 8px; display: flex; gap: 10px; align-items: center; cursor: pointer; }
.page-thumb { width: 60px; height: 60px; flex-shrink: 0; border-radius: 6px; background-size: cover; background-position: center; background-color: var(--paper-warm); display: flex; align-items: center; justify-content: center; font-size: 22px; color: var(--ink-soft); }
.page-body { flex: 1; min-width: 0; }
.page-num { font-size: 10px; color: var(--ink-soft); font-family: 'Fraunces', serif; letter-spacing: 1px; }
.page-text { font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.page-actions { display: flex; gap: 4px; }
.page-action { background: transparent; border: none; padding: 6px; color: var(--ink-soft); }
.page-action svg { width: 18px; height: 18px; display: block; }
.btn-add-page { width: 100%; padding: 14px; background: var(--paper-warm); border: 2px dashed var(--border); border-radius: 8px; color: var(--ink-soft); font-size: 14px; font-family: 'Gowun Batang', serif; display: flex; align-items: center; justify-content: center; gap: 8px; }
.btn-add-page svg { width: 18px; height: 18px; }
.btn-danger { width: 100%; padding: 12px; margin-top: 30px; background: white; border: 1px solid var(--danger); color: var(--danger); border-radius: 8px; font-size: 14px; font-family: 'Gowun Batang', serif; font-weight: 600; }

/* ─── 어휘 편집 섹션 (책 편집 화면) ─── */
.vocab-edit-section {
  margin: 0 12px 30px;
  background: white;
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}
.vocab-edit-section-header {
  background: var(--paper-warm);
  padding: 12px 14px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  border-bottom: 1px solid var(--border);
}
.vocab-edit-section-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 700;
  font-size: 14px;
  color: var(--navy-deep);
}
.vocab-edit-count {
  background: var(--navy);
  color: white;
  font-family: 'Fraunces', serif;
  font-size: 11px;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 100px;
  min-width: 22px;
  text-align: center;
}
.vocab-edit-section-actions {
  display: flex;
  gap: 6px;
}
.vocab-edit-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 6px 11px;
  background: white;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-family: 'Gowun Batang', serif;
  font-size: 12px;
  color: var(--ink);
  cursor: pointer;
  transition: all 0.15s;
}
.vocab-edit-btn:hover { background: var(--paper-warm); }
.vocab-edit-btn:active { transform: scale(0.96); }
.vocab-edit-btn.primary {
  background: var(--navy);
  color: white;
  border-color: var(--navy);
}
.vocab-edit-btn.primary:hover { background: var(--navy-deep); }

.vocab-edit-list {
  padding: 4px 0;
  max-height: 600px;
  overflow-y: auto;
}
.vocab-edit-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 10px 12px;
  border-bottom: 1px solid rgba(0,0,0,0.04);
}
.vocab-edit-row:last-child { border-bottom: none; }
.vocab-edit-row-top {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 50px 32px;
  gap: 6px;
  align-items: center;
}
.vocab-edit-row-note {
  display: flex;
  align-items: center;
  gap: 6px;
  padding-left: 2px;
}
.vocab-edit-input {
  width: 100%;
  padding: 6px 8px;
  border: 1px solid transparent;
  border-radius: 4px;
  font-size: 13px;
  font-family: 'Gowun Batang', serif;
  background: transparent;
  color: var(--ink);
  transition: all 0.15s;
}
.vocab-edit-input:hover { background: var(--paper-warm); }
.vocab-edit-input:focus {
  outline: none;
  background: white;
  border-color: var(--navy);
}
.vocab-edit-input.kor { font-weight: 700; font-size: 14px; }
.vocab-edit-input.rom { font-family: 'Fraunces', serif; font-style: italic; color: var(--ink-soft); font-size: 12px; }
.vocab-edit-input.eng { font-family: 'Fraunces', serif; color: var(--ink-soft); font-size: 12px; }
.vocab-edit-input.note {
  font-family: 'Fraunces', serif;
  font-style: italic;
  font-size: 12px;
  color: #6B5F4F;
  flex: 1;
}
.vocab-note-label {
  font-size: 10px;
  color: var(--ink-soft);
  white-space: nowrap;
  flex-shrink: 0;
  font-family: 'Fraunces', serif;
  font-style: italic;
}
.vocab-edit-pos {
  padding: 5px 4px;
  border: 1px solid transparent;
  border-radius: 4px;
  font-family: 'Gowun Batang', serif;
  font-size: 11px;
  background: transparent;
  color: var(--ink-soft);
  cursor: pointer;
}
.vocab-edit-pos:hover { background: var(--paper-warm); }
.vocab-edit-pos:focus { outline: none; background: white; border-color: var(--navy); }
.vocab-edit-delete {
  width: 28px;
  height: 28px;
  border: none;
  background: transparent;
  border-radius: 50%;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-soft);
  font-size: 16px;
  transition: all 0.15s;
}
.vocab-edit-delete:hover { background: rgba(196,83,58,0.1); color: var(--danger); }
.vocab-edit-delete:active { transform: scale(0.9); }

.vocab-edit-empty {
  text-align: center;
  padding: 30px 20px;
}

/* ─── READER ─── */
.reader-wrap { height: 100%; display: flex; flex-direction: column; background: white; position: relative; overflow: hidden; }
/* 컨트롤바가 FAB으로 바뀜 - 전체 높이 사용 */
.reader-pages { display: flex; height: 100%; transition: transform 0.42s cubic-bezier(0.22,0.61,0.36,1); will-change: transform; }

/* ── 본문 페이지 ── */
.reader-page {
  min-width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  overflow: hidden;
  position: relative;
  background: white;
}

/* ── 표지 페이지 ── */
.reader-page.cover-page {
  align-items: center;
  justify-content: flex-start; /* ★v126: 세로 중앙 → 상단 정렬 (시안2) */
  padding: 8vh 32px 40px; /* ★v131: 상단 4vh → 8vh, 제목이 헤더에 붙지 않게 살짝 내림 */
  background: white;
  overflow-y: auto;
}
.reader-cover-title { font-weight: 700; font-size: 36px; text-align: center; color: var(--navy-deep); margin-bottom: 4px; line-height: 1.15; }
.reader-cover-sub { font-family: 'Fraunces', serif; font-style: italic; font-size: 14px; color: var(--ink-soft); margin-bottom: 18px; }
.reader-cover-img {
  width: 100%;
  max-width: 480px;
  max-height: 65vh;
  object-fit: contain;          /* 사진 비율(4:5·4:3 등) 그대로, 잘리지 않게 */
  display: block;
  border-radius: 6px;
  box-shadow: 0 14px 28px -10px rgba(0,0,0,0.25);
  margin-bottom: 20px;
}
/* 사진이 없을 때 쓰는 플레이스홀더(📖)는 기존 4:3 틀 유지 */
.reader-cover-img.is-placeholder {
  aspect-ratio: 4/3;
}

/* ── 속표지(네이티브) "Your Korean So Far" — words to know와 같은 서체·색 ── */
.reader-page.intro-page {
  background: #fff;
  padding: 32px 24px 40px;
  justify-content: flex-start;
  align-items: stretch;
  overflow-y: auto;
}
.intro-header { text-align: center; margin-bottom: 26px; flex-shrink: 0; }
.intro-title {
  font-family: 'Fraunces', serif;
  font-style: italic;
  /* ★ v224: 부속 네 쪽 제목 공통 — 이탤릭 굵게(700).
     지금까지 400이었는데, 본문 Jua는 굵기 400 하나뿐인 "원래 통통한" 서체라
     같은 400이어도 본문이 훨씬 무거워 제목이 목록에 눌렸다. 본문을 낮추는 대신
     제목을 올려 균형을 잡는다.
     ⚠️ 이 700은 index.html 글꼴 URL의 `1,9..144,400..700`(이탤릭 400~700 범위)에
        딸려 온다. 그 범위를 지우면 브라우저가 가짜 볼드를 그려 획이 뭉갠다.
     ⚠️ opsz 96 — Fraunces는 글자 크기에 따라 자동으로 획 대비가 바뀌는데(기본 auto),
        26px면 본문용 굵기로 그려져 시안보다 밋밋하다. 시안대로 제목용 대비로 고정. */
  font-weight: 700;
  font-variation-settings: 'opsz' 96, 'wght' 700;
  font-size: var(--aux-title);
  color: #25394B;               /* ★ v222: 부속 페이지 제목 셋 공통 남색 */
  letter-spacing: 0.5px;
  margin-bottom: 6px;
}
/* ★ v222: 통째로 한글인데 Fraunces(한글 없음)로 선언돼 있어 늘 폴백으로 그려졌다
   — 안드로이드는 고딕, 아이폰은 애플 명조로 제각각. 이 쪽의 한글 글꼴로 못박는다. */
.intro-sub {
  font-family: 'Jua', sans-serif;
  font-size: var(--aux-sub);
  color: var(--aux-beige);
  letter-spacing: 0.5px;
}
/* ★ v222: 줄 사이를 gap이 아니라 "줄마다의 아래 여백 + 가는 선"으로 바꿨다.
   gap으로 띄우면 선을 넣을 자리가 없다. 선이 있으면 세 단계가 계단으로 읽힌다. */
.intro-band {
  flex: 0 0 auto;               /* 남은 높이를 채우지 않음 → 위에서부터 흐름 */
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  padding: 0;
  border-top: 1px solid rgba(168,152,120,0.25);
  border-bottom: 1px solid rgba(168,152,120,0.25);
}
.intro-row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 14px;
  padding: 20px 0;
  border-bottom: 1px solid #F1EFEA;
}
.intro-row:last-child { border-bottom: none; }
/* 레벨 표시 — 네모 상자 안에 자모, 상자 밑에 LEVEL.
   ★ v222: 알약에 "Level ㄱ"을 한 줄로 넣던 것을 바꿨다. 한 줄이면 자모가 라틴 글자
   사이에 끼어 크기를 키울 수 없었고(딱지가 통째로 커진다), 그래서 v221에서 자모만
   키워도 한계가 있었다. 상자로 떼어 놓으면 자모가 주인공이 되고 Level은 설명으로 내려간다. */
.intro-chip { display: flex; flex-direction: column; align-items: center; gap: 5px; }
.intro-lv-box {
  width: 46px; height: 46px; border-radius: 11px;
  border: 2px solid #25394B; background: #fff;
  display: flex; align-items: center; justify-content: center;
}
.intro-lv {
  font-family: 'Jua', sans-serif;   /* 한글이 있는 글꼴로 못박음 — Fraunces엔 한글이 없다 */
  font-size: 26px; line-height: 1; color: #25394B;
}
.intro-chip-lbl {
  font-family: 'Fraunces', serif; font-weight: 600; font-size: 9px;
  letter-spacing: 1.6px; text-transform: uppercase; color: #6C6457;
}
.intro-row.current .intro-lv-box { background: #FCF7E8; border-color: #856B2E; }
.intro-row.current .intro-lv { color: #856B2E; }
/* ★ v215: 같은 레벨이 이어지는 줄의 딱지 — 자리는 지키고 글자만 감춘다.
   display:none이면 한글 줄이 왼쪽으로 밀려 사다리가 흐트러진다. */
.intro-chip.cont { visibility: hidden; }
/* ★ v222: 여기 있던 `.intro-row.current .intro-chip { background }` 는 지웠다.
   .intro-chip이 알약 자체였을 땐 맞았지만, 이제는 상자+라벨을 감싸는 세로 열이라
   배경을 주면 LEVEL 글자 뒤까지 통째로 칠해진다(실제로 그렇게 나왔다).
   금색은 상자(.intro-lv-box)에만 준다 — 위쪽 규칙 참고. */
/* ★ v222: 한글을 Gowun Batang(명조) → Jua(둥근)로. 문법 두 쪽(v220)에 이어 부속 페이지를
   한 벌로 맞춘 것 — 속표지만 명조로 남으면 넘길 때 다른 책처럼 보인다.
   ⚠️ Jua는 굵기가 400 하나뿐이라 font-weight를 주면 가짜 볼드로 획이 뭉갠다. */
.intro-ko {
  font-family: 'Jua', sans-serif;
  font-size: var(--aux-ko);
  color: #3C7855;               /* words to know 한글과 동일 green */
  line-height: 1.25;
  /* ★ v226: 한국어는 기본값이면 글자 아무 데서나 끊긴다. 사다리 아래쪽 줄은
     길어져 두 줄이 되는데(ㄷ9 "고양이가 침대 안에 있어요."), 그대로 두면
     「있 / 어요」처럼 낱말 한가운데가 갈라진다. 띄어쓰기에서만 끊게 한다. */
  word-break: keep-all;
}
/* ★ v227: 어절 하나를 통째로 묶는다. word-break:keep-all은 기기마다 결과가 달랐다 —
   갤럭시는 제대로 끊겼는데 아이폰은 「있어 / 요」로 낱말 한가운데가 갈라졌다.
   nowrap span 안에서는 어떤 브라우저도 줄을 나눌 수 없으므로 CSS 지원에 기대지 않는다.
   ⚠️ 이 span은 app.js의 nbWords()가 만든다. 둘은 한 쌍이니 한쪽만 지우지 말 것. */
.nb-word { white-space: nowrap; }
.intro-row.current .intro-ko { color: #856B2E; }
.intro-en {
  font-family: 'Fraunces', serif;
  font-size: var(--aux-en);
  color: #5C544A;
  margin-top: 2px;
}
.intro-tagcol { text-align: right; white-space: nowrap; }
.intro-tag {
  font-family: 'Fraunces', serif;
  font-style: italic;
  font-size: var(--aux-tag);
  color: var(--aux-beige);
}
.intro-here {
  font-family: 'Fraunces', serif;
  font-weight: 600;
  font-size: var(--aux-tag);
  color: #856B2E;               /* ★ v222: 현재 레벨 금색 통일 */
  margin-top: 3px;
}
.intro-foot {
  text-align: center;
  font-family: 'Fraunces', serif;
  font-size: var(--aux-tag);
  color: var(--aux-beige);
  margin-top: 22px;
  flex-shrink: 0;
}
/* ★ v222: 여기 자모(ㄱ·ㅎ)도 딱지와 같은 함정에 있었다 — Fraunces에 한글이 없어
   시스템 글꼴로 떨어져 흐리게 찍혔다. Jua로 못박고 한 단계 진하게. */
.intro-foot-lv {
  font-family: 'Jua', sans-serif;
  font-size: 1.15em; line-height: 1; vertical-align: -0.06em;
  color: #6C6457;
}

/* ── 편집기: 속표지 밴드 입력 폼 ── */
.intro-band-empty {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  font-size: 12px; color: var(--ink-soft);
  border: 1px dashed var(--border); border-radius: 8px; padding: 10px 12px;
}
.intro-band-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: 6px; }
.intro-band-row { display: flex; align-items: center; gap: 5px; }
.intro-band-row select, .intro-band-row input {
  border: 1px solid var(--border); border-radius: 6px; padding: 6px 7px;
  font-size: 13px; background: #fff; min-width: 0;
}
.intro-band-lv { flex: 0 0 46px; text-align: center; }
.intro-band-ko { flex: 1 1 30%; }
.intro-band-en { flex: 1 1 28%; }
.intro-band-tag { flex: 1 1 26%; }
.intro-band-cur { flex: 0 0 auto; font-size: 11px; color: var(--ink-soft); display: inline-flex; align-items: center; gap: 3px; white-space: nowrap; }
.intro-band-del {
  flex: 0 0 auto; border: none; background: none; color: #c0392b;
  font-size: 15px; cursor: pointer; padding: 2px 5px; line-height: 1;
}
.intro-band-add {
  border: 1px solid var(--border); background: #fff; border-radius: 8px;
  padding: 7px 12px; font-size: 13px; color: var(--navy); cursor: pointer;
}
.intro-band-hint { font-size: 11px; color: var(--ink-soft); margin-top: 6px; line-height: 1.4; }

/* ── 편집기: 접이식 섹션(속표지·문법) — 기본 접힘 ── */
.edit-collapse { border: 1px solid var(--border); border-radius: 8px; margin-bottom: 8px; overflow: hidden; }
.edit-collapse-head {
  width: 100%; display: flex; align-items: center; gap: 8px;
  background: var(--paper-warm, #faf7f0); border: none; padding: 11px 12px;
  cursor: pointer; text-align: left;
}
.edit-collapse-arrow { color: var(--ink-soft); font-size: 11px; width: 12px; flex-shrink: 0; }
.edit-collapse-title { font-family: 'Fraunces', serif; font-size: 12px; font-weight: 700; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 1px; flex-shrink: 0; }
.edit-collapse-sum { margin-left: auto; font-size: 12px; color: var(--ink-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.edit-collapse-body { display: none; padding: 12px; border-top: 1px solid var(--border); }
.edit-collapse-body.open { display: block; }
.edit-collapse-hint { font-size: 11px; color: var(--ink-soft); margin-bottom: 10px; line-height: 1.4; }

/* ── 편집기: 문법 입력 폼 ── */
.gram-e-tmpl { display: flex; gap: 14px; margin-bottom: 10px; font-size: 13px; color: var(--ink); flex-wrap: wrap; }
.gram-e-tmpl label { display: inline-flex; align-items: center; gap: 4px; cursor: pointer; }
.gram-e-sub { font-size: 12px; font-weight: 700; color: var(--ink-soft); margin: 12px 0 6px; }
.gram-e-tag { flex: 0 0 44px; font-size: 11px; color: var(--ink-soft); white-space: nowrap; }
#grammarEditor .intro-band-row input { flex: 1 1 0; }
.gram-e-ko { min-width: 0; }
.gram-e-en { min-width: 0; }

/* ── 문법(네이티브) 리더 페이지 ──────────────────────────────
   ★ v220: 문법 두 쪽만 둥근 서체(Jua)·따뜻한 색 한 벌로 갈아입혔다. 문법은 "설명하는 쪽"이라
   본문·words to know의 세리프(Fraunces/Gowun Batang)보다 말랑한 인상이 맞다는 판단.
   ⚠ 색은 아래 --g-* 한곳에만 적는다. 규칙마다 흩어 쓰면 다음 조정 때 절반만 바뀐다.
   ⚠ Jua는 굵기가 400 하나뿐 — font-weight:700을 주면 브라우저가 가짜 볼드를 그려
     획이 뭉갠 것처럼 보인다. 이 블록 안에서 font-weight는 쓰지 말 것.
   ⚠ 페이지 배경은 흰색 그대로다(시안은 크림). 나머지 쪽과 톤을 맞추기 위한 의도적 차이이며,
     그래서 오른쪽 흰 카드는 배경에 묻히지 않도록 테두리(--g-box-bd)로 형태를 잡는다. */
/* ★ v232: 위 여백 20 → 32px. 부속 네 쪽 중 문법 두 쪽만 20px이라 이 쪽들만 제목이
   위에 붙어 보였다(속표지·words to know는 둘 다 32px). 넘길 때 제목이 같은 자리에
   있어야 한 권으로 읽힌다 — v203이 세로 가운데 정렬을 뺀 것과 같은 이유다.
   ⚠️ 아래는 20px 그대로. 속표지·words to know의 40px까지 따라가면 낱말 많은 책에서
      스크롤이 생긴다. 맞춰야 하는 건 "제목이 시작하는 높이"지 상하 여백 자체가 아니다. */
.reader-page.grammar-page {
  background: #fff;
  padding: 32px 20px 20px;
  justify-content: flex-start;
  align-items: stretch;
  overflow-y: auto;
  font-family: 'Jua', sans-serif;
  --g-ink:     #473623;   /* 글자 — 검정 대신 진한 갈색 */
  /* ★ v223: 2쪽 낱말 목록 전용, --g-ink보다 한 단계 연하게(대비 11.5:1 → 6.6:1).
     낱말이 13개까지 세로로 쌓이는 쪽이라 --g-ink로 두면 목록이 제목보다 무겁게 눌린다.
     1쪽은 낱말이 둘뿐이라 --g-ink 그대로 — 같은 색으로 맞추면 1쪽이 되레 힘을 잃는다.
     ⚠️ 아래 .bat 그라디언트의 위쪽 색도 이 값이어야 한다. 안 맞추면 한 글자가 두 색으로 잘린다. */
  --g-word:    #6E5A42;
  --g-red:     #BD6F52;   /* 강조(제목·뜻·어미·받침 있는 쪽) */
  /* ★ v230: 크림 바탕(--g-cream) 위에 얹는 테라코타. --g-red를 크림 위에 두면 대비가
     3.5:1밖에 안 나와, 흰 바탕의 --g-muted(4.6:1)보다 오히려 흐리다 — 밝은 데서는
     받침 "있는" 쪽 제목이 먼저 사라진다. 같은 색감으로 한 단계만 내려 4.6:1을 맞춘 값.
     ⚠️ 크림 카드 안의 작은 글자에만 쓸 것. 넓은 면적이나 흰 바탕에는 --g-red 그대로. */
  --g-red-deep:#A65A3E;
  --g-muted:   #867359;   /* 잔라벨(head / body / last letter) */
  --g-rom:     #B0A189;   /* 로마자 */
  --g-gray:    #BAAA8E;   /* 받침 없는 쪽의 밑줄·화살표 */
  --g-line:    #DACAA8;   /* 점선 */
  --g-cream:   #FDF5E2;   /* 받침 있는 쪽 카드 바탕 */
  --g-box-bd:  #E0D0AC;   /* 흰 칸 테두리 */
  --g-gold:    #FAE1AF;   /* 어미 칸 바탕 */
  --g-gold-bd: #DABA74;
  --g-tail:    #F7CB70;   /* tail 칸 — 이 쪽에서 가장 진한 금색 */
  --g-tail-bd: #D6A546;
}
/* ★ v210: 문법 쪽 세로 여백을 한 벌로 조였다(글자 크기는 그대로 — 상하 간격만).
   실측 56px(약 9%) 짧아진다. 값을 여기 한곳에 모아 두는 이유는 앞으로 만들 책이
   전부 같은 리듬을 갖게 하기 위해서다 — 책마다 따로 조정하지 말 것. */
.gram-header { text-align: center; margin-bottom: 14px; flex-shrink: 0; }
/* ★ v222: 제목만 Jua → Fraunces 이탤릭으로 되돌린다. 속표지 "Your Korean So Far",
   "Words to Know"와 같은 서체 — 부속 네 쪽의 제목이 한 목소리로 읽혀야 한 권으로 묶인다.
   본문(칸·낱말)은 Jua 그대로 둔다. 제목은 책의 목소리, 본문은 배우는 말이라 역할이 다르다.
   ★ v223: 색도 앞 두 쪽과 같은 남색으로 맞췄다(테라코타 → #25394B). 제목이 쪽마다
   다른 색이면 넘길 때 다른 책처럼 보인다 — 쪽의 개성은 본문 색이 내면 충분하다. */
.gram-title {
  font-family: 'Fraunces', serif; font-style: italic;
  font-weight: 700;
  font-variation-settings: 'opsz' 96, 'wght' 700;
  font-size: var(--aux-title); color: #25394B; letter-spacing: .5px;
}
.gram-band { margin-bottom: 12px; }
.gram-band:last-child { margin-bottom: 0; }
.gram-band-label {
  font-size: var(--aux-label); color: var(--g-muted);
  letter-spacing: 1px; text-transform: uppercase; text-align: center;
  margin-bottom: 11px; padding-bottom: 6px; border-bottom: 3px dotted var(--g-line);
}
/* 규칙 한 줄 — 시범을 다 보여준 "뒤"에 결론으로 놓는다 (v203).
   위에 제목처럼 걸면 아직 못 본 것을 미리 요약하는 꼴이라 그냥 지나친다. */
.gram-band-foot {
  font-size: var(--aux-en); color: var(--g-muted);
  text-align: center; margin-top: 26px; padding-top: 16px;
  border-top: 3px dotted var(--g-line);
}
/* 어미 색. 2쪽(Words in This Book)은 "red = 받침 / gold = 어미"라고 글로 적어 두었으므로
   금색 그대로 두고, 1쪽만 시안대로 테라코타로 쓴다. 두 쪽의 어미 색이 다른 셈인데,
   1쪽은 빨강(받침)을 쓰지 않아 헷갈릴 대상이 없고 2쪽은 설명 줄이 지켜진다. */
.grammar-page .amb { color: #B0761A; }
.grammar-page.sentence-page .amb { color: var(--g-red); }

/* 문장 칸 — v203부터 이 묶음이 1쪽을 통째로 쓴다. 받침은 제 쪽으로 갔다. */
/* 칸이 3~4개인 책에서는 flex-wrap으로 줄이 나뉜다 — 폭을 넘기지 않게 두는 안전장치 */
.gram-slots { display: flex; justify-content: center; align-items: stretch; gap: 10px; flex-wrap: wrap; }
.gram-slot { display: flex; }
/* 칸 = 한 장의 카드(글자 + 뜻). 아래 테두리만 두껍게 해서 살짝 도톰해 보이게 한다 —
   그림자 대신 테두리로 내는 입체감이라 캡처·인쇄에서도 그대로 남는다. */
.gram-slot-box {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  background: #fff; border: 3px solid var(--g-box-bd); border-bottom-width: 6px; border-radius: 18px;
  padding: 12px 16px 10px; min-width: 82px; text-align: center;
}
.gram-slot-word { font-size: 34px; color: var(--g-ink); line-height: 1.15; }
.gram-slot.focus .gram-slot-box { background: var(--g-gold); border-color: var(--g-gold-bd); }
/* 칸과 칸 사이의 ＋ — 칸의 세로 가운데에 붙는다. 잔글씨라 색을 낮춰 두 칸이 주인공으로 남게. */
.gram-slot-plus { align-self: center; font-size: 22px; color: #C5B395; line-height: 1; }
/* ★ v212: 칸이 셋인 책(ㄷ4 파란 하늘 이에요)은 폰에서 칸을 조금 줄인다.
   안드로이드 크롬은 시스템 글자 크기에 맞춰 "글자만" 키우고 여백(px)은 그대로 두므로,
   기본값으로는 여유가 9%뿐이라 배율 1.15만 되어도 마지막 칸이 아래로 내려갔다
   (아이폰은 한 줄, 갤럭시는 두 줄이 된 실제 원인). 줄이면 1.4배까지 한 줄로 버틴다.
   칸이 둘인 책(ㄷ1~ㄷ3)은 원래 크기 그대로 — 여긴 원래 여유가 넉넉하다. */
@media (max-width: 500px) {
  .gram-slots.n3 { gap: 7px; }
  .gram-slots.n3 .gram-slot-box { padding: 10px 10px 8px; min-width: 62px; }
  .gram-slots.n3 .gram-slot-word { font-size: 27px; }
  .gram-slots.n3 .gram-slot-en { font-size: 14px; }
  .gram-slots.n3 .gram-slot-plus { font-size: 18px; }
}
.gram-slot-en { font-size: 16px; color: var(--g-red); }
/* v205: 뜻 줄 위아래 여백을 34px → 12px로. 칸과 뜻은 "같은 문장의 조각과 결과"라
   멀리 떨어뜨릴 이유가 없었는데, 한 쪽에 두 묶음이 들어오면서 그 틈이 페이지를
   위아래로 밀어 꽉 차 보이게 했다. */
.gram-example { text-align: center; margin-top: 12px; }
.gram-ex-en { font-size: 21px; color: var(--g-ink); }

/* ★ v217: 설명 한 줄 — 칸 밑 라벨에 담을 수 없는 용어 설명(subject marker 등)을 둔다.
   라벨을 길게 쓰면 칸이 벌어져 글자를 키운 기기에서 줄이 밀린다(실측 확인).
   ★ v229: 문장 칸 아래 → 제목 바로 밑으로. 이 줄은 이제 쪽의 "부제"다.
   음수 margin-top은 .gram-header의 14px을 10px로 당겨 제목과 한 덩어리로 붙이는 것 —
   제목·부제 사이가 부제·본문 사이보다 좁아야 둘이 한 묶음으로 읽힌다. */
/* ── 설명 쪽 (How It Works) — 표가 아니라 «읽는 글» ────────────────────────
   ⚠️ 부속 네 쪽은 한 벌이라 색·서체는 문법 쪽 그대로 두되(--g-*, Jua),
      **정렬과 행간만** 읽는 글로 바꾼다 — 가운데 정렬은 두 줄만 넘어가도 못 읽는다.
   ⚠️⚠️ **스크롤이 아니라 쪽 넘김이다**(2026-09-01 사용자 결정) — 넘치면 안 되므로
      글자 크기를 화면 폭에 맞춰 살짝 줄인다. 쪽 나누기는 저자가 손으로 한다. */
.lesson-page { display: flex; flex-direction: column; }
.lesson-page .gram-header { position: relative; }
/* ⚠️ **한 쪽 안에서 스크롤한다**(2026-09-01 사용자 결정 — 3쪽 → 1쪽).
   바깥 리더는 `scroll-snap-type: y mandatory` 세로 넘김이라, 안쪽이 끝까지 가면
   그때 바깥이 다음 쪽으로 넘어간다(브라우저 기본 동작). */
.lesson-body { flex: 1; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch;
  text-align: left; padding-bottom: 8px; }
/* ⚠️⚠️ ★ 2026-09-03 — **이 쪽만 Jua를 벗는다.** 부속 네 쪽은 한 벌이라는 규칙의 예외다.
   Jua는 «딱지 서체»다 — 두세 낱말짜리 카드 라벨에는 좋지만 이 쪽은 **글이 1,000자**다.
   획 굵기가 한 가지뿐이라 긴 글에서 리듬이 안 생기고, 라틴 자형이 둥근 마커체라
   영어 문장이 «손글씨 메모»로 읽힌다. 읽는 글에는 읽는 서체를 준다.
   ⭐ `Gowun Batang` 은 **이미 앱 본문 서체**이고 한글·라틴을 한 벌로 갖는다 —
     새로 내려받는 것이 없고, 이 쪽이 「카드」가 아니라 「책이 말하는 자리」로 읽힌다.
   ⚠️ 제목(Fraunces 이탤릭)·색(--g-*)은 그대로다. 바꾸는 것은 **본문 서체 하나**뿐이라
      나머지 부속 쪽과 한 벌인 느낌은 유지된다. */
.lesson-main, .lesson-ko { font-family: 'Gowun Batang', serif;
  font-size: clamp(15.5px, 4.4vw, 18px); line-height: 1.8;
  white-space: pre-line; overflow-wrap: break-word; word-break: keep-all; }
/* ⭐ 한국어는 «곁줄»이 아니라 «바꿔 넣는 글»이다 — 보일 때는 본문과 똑같이 보인다.
   쌓으면 글이 두 배가 되어 계속 내려야 한다(읽는 글이라 더 그렇다). */
.lesson-main, .lesson-ko { color: var(--g-ink); }
/* 「한 / EN」 단추 — 리더의 번역 단추와 같은 몸짓이라 배울 것이 없다 */
.lesson-lang { position: absolute; right: 0; top: 50%; transform: translateY(-50%);
  min-width: 38px; padding: 5px 10px; border: 1px solid var(--g-line); border-radius: 100px;
  background: var(--g-cream); color: var(--g-muted); font-family: inherit; font-size: 13px; }
/* 금색(--g-gold) 밑줄로 예문을 짚는다 — 문법 쪽이 이미 쓰는 몸짓이다.
   ⚠️ 굵기는 400으로 **둔다.** Gowun Batang 은 700이 있어 굵게 할 수 있지만,
      금색 밑줄과 굵기를 함께 걸면 한 쪽에 강조가 열몇 군데라 글이 시끄러워진다.
      (Jua 시절엔 «400밖에 없어서» 그랬고, 지금은 «골라서» 그런다) */
.lesson-body strong { font-weight: 400; color: var(--g-ink);
  background: linear-gradient(transparent 60%, var(--g-gold) 60%); }

.gram-note { text-align: center; margin-top: -4px; margin-bottom: 18px; }
/* v220: 예전엔 영어(Fraunces) + 한글(Gowun Batang) 두 글꼴을 겹쳐 뒀다. Jua는 영문·한글을
   한 벌로 갖고 있어 겹칠 필요가 없어졌다 — 겹쳐 두면 오히려 한쪽만 바뀔 위험이 있다.
   ★ v229: 15px 잔글씨 색(--g-muted) → 17px 본문 색(--g-ink). 제목 밑으로 올려 놓고도
   각주 크기로 두면 여전히 그냥 지나친다. 다만 아래 뜻 줄(.gram-ex-en 21px)보다는 한 단계
   낮게 둔다 — 이 줄은 쪽이 무슨 이야기인지 알려주는 안내판이지 주인공이 아니다.
   ⚠️ 굵게 만들지 말 것. Jua는 굵기가 400 하나뿐이라 font-weight를 걸면 브라우저가
      글자를 부풀리는 가짜 볼드가 되어 「이 / 가」의 속이 메워진다. 세기는 크기와 색으로만. */
/* ⚠️ **줄바꿈을 살린다** (2026-09-01) — 설명이 「무엇을 하나 / 예문」 두세 줄이 되면서
   한 덩이로 붙어 버렸다. `pre-line` 이면 원문의 \n 만 살고 잉여 공백은 접힌다.
   ⭐ 예문은 «줄을 갈라야» 견줌이 보인다 — 「밥이 맛있어요」 ↔ 「밥을 먹어요」 */
.gram-note-en { font-size: 17px; color: var(--g-ink); line-height: 1.45; white-space: pre-line; }
/* 공식 줄(noun + 이 / 가 → subject)은 낱말 사이를 조금 벌린다 — 화살표가 앞 글자에
   달라붙어 보였다(한글 글꼴과 화살표 글꼴의 좌우 여백이 달라서). */
.gram-note-ko { font-size: var(--aux-tag); color: var(--g-rom); margin-top: 3px; word-spacing: .16em;
  white-space: pre-line; }

/* 받침 — 이에요 / 예요 세로 비교.
   v204에서 문장 칸과 한 쪽을 나눠 쓰게 되어, 두 묶음이 서로 다른 설명임을
   가는 선 하나로 구분한다(예전의 밴드 제목이 하던 일). */
/* ★ v213: 구분선 위아래만 다시 벌렸다(4/10 → 14/16). v210에서 쪽 전체를 조일 때
   여기까지 같이 조였더니 문장 칸과 받침 대조가 한 덩어리로 붙어 보여 부담스러웠다.
   묶음 "사이"의 간격은 묶음 "안"의 간격보다 넓어야 둘로 읽힌다 — 쪽을 짧게 만드는
   것보다 이 위계가 우선이다. 다른 여백은 v210 그대로 조인 값을 유지한다. */
.gram-band-cmp { margin-top: 14px; padding-top: 18px; border-top: 3px dotted var(--g-line); }
/* ★ v220: 가운데 세로줄 하나로 나누던 것을 카드 두 장으로 바꿨다. 받침 있는 쪽(.has)만
   크림색으로 채워, 어느 쪽이 "이에요가 붙는 쪽"인지 색만 봐도 알게 한다.
   min-width:0 — 없으면 격자/플렉스 칸이 내용 크기만큼 벌어져 긴 낱말이 화면을 넘는다. */
.gram-cmp { display: flex; align-items: stretch; justify-content: center; gap: 10px; }
/* 좌우 여백은 4px까지만. 카드가 되면서 칸 하나가 예전보다 좁아졌는데, 「할아버지예요」처럼
   여섯 자짜리 말이 들어오면 그 몇 px 때문에 두 줄로 접힌다(실측). 카드 느낌은 테두리와
   배경색이 내는 것이지 안쪽 여백이 내는 게 아니므로 여기를 깎는 편이 낫다. */
/* ★ v229: 카드 안 세로 여백을 한 벌로 조였다(gap 4→2, 안쪽 14/16→10/12). 이 카드가
   쪽의 절반을 넘게 쓰는데, gap은 자식 여덟 개 사이에 전부 끼어 있어서 2px만 줄여도
   14px이 빠진다. 글자 크기·구조는 그대로라 가르치는 내용은 바뀌지 않는다.
   ⚠️ 카드 "바깥"(.gram-band-cmp의 14/18px)은 건드리지 않았다 — v213에서 일부러 넓힌
      자리다. 묶음 사이는 묶음 안보다 넓어야 문장 칸과 받침 대조가 둘로 읽힌다. */
.gram-cmp-col {
  flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 10px 4px 12px; border-radius: 20px;
  background: #fff; border: 2.5px solid var(--g-box-bd);
}
.gram-cmp-col.has { background: var(--g-cream); border-color: var(--g-gold-bd); }
.gram-cmp-rule { font-size: 13px; color: var(--g-muted); margin-bottom: 6px; }
.gram-cmp-rule b { color: var(--g-ink); }
.gram-cmp-tag { font-size: 13px; color: var(--g-muted); }
.gram-cmp-tag .on { color: var(--g-red); }
/* ★ v251 틀 E — 「언제 어느 쪽」. 받침이 아니라 «뜻»으로 갈리는 자리.
   ⚠️ 카드 배치는 받침 대조와 똑같이 둔다 — 독자가 아는 모양이라야 «이번엔 뜻으로
   갈리는구나»가 대비로 읽힌다. 다만 「받침 있음/없음」 딱지 자리에 «조건»이 들어간다. */
.gram-two-col.on { background: var(--g-cream); border-color: var(--g-gold-bd); }
.gram-two-when {
  font-size: 17px; color: var(--g-ink); text-align: center; line-height: 1.3;
}
.gram-two-when-en {
  font-size: 11.5px; color: var(--g-rom); text-align: center; margin-top: 2px;
  font-family: 'Fraunces', 'Jua', serif; font-style: italic;
}
.gram-two-ex {
  font-size: 19px; color: var(--g-ink); text-align: center; line-height: 1.45;
  word-break: keep-all;
}
.gram-two-ex .amb { color: var(--g-red); }
@media (max-width: 420px) {
  .gram-two-when { font-size: 15px; }
  .gram-two-ex { font-size: 17px; }
}

/* 완성된 말 앞의 점선 — 위(글자 뜯어보기)와 아래(그래서 이렇게 붙는다)의 경계 */
.gram-cmp-sep { width: 80%; border-top: 3px dotted var(--g-line); margin: 9px 0 7px; }
.gram-cmp-word { font-size: 27px; color: var(--g-ink); line-height: 1.2; text-align: center; }
.gram-cmp-rom { font-size: var(--aux-rom); color: var(--g-rom); margin-top: 4px; }

/* 받침 낱자 칸 — 단어의 "마지막 글자"만 head(초성)·body(중성)·tail(종성)로 쪼개
   "마지막 조각이 있다/없다"를 눈으로 보임. 앞 글자는 흐리게 두어
   규칙이 단어 전체가 아니라 마지막 글자의 문제임을 드러낸다. */
/* ★ v229: 낱자 칸과 낱말을 한 단계씩 줄였다(칸 50→44, 낱말 30→28, 완성된 말 30→27).
   여백만으로는 6%밖에 안 짧아져 "쪽이 길다"는 느낌이 그대로였다. 여기까지 내려야
   눈에 띄게 짧아지는데, 낱자는 여전히 본문 글자보다 크므로 읽는 데는 지장이 없다. */
.gram-cmp-col { --jm-box: 44px; --jm-font: 25px; }
/* ★ v230: 카드 두 장의 "제목"이다 — 이 쪽이 받침 있는 쪽이냐 없는 쪽이냐가 이 카드가
   가르치는 것 자체인데, 14px(폰)이면 바로 밑 last letter(12px)와 두 단계 차이뿐이라
   제목으로 안 읽혔다. 17→19 / 폰 14→16px.
   ⚠️ 18px(폰) 이상으로 올리지 말 것. 「without a tail」이 「with a tail」보다 길어서
      한쪽만 두 줄로 접히면 카드 높이가 어긋난다. 360px 폰에서 안 접히는 한계는
      16px=1.47배 · 17px=1.39배 · 18px=1.31배인데, 안드로이드 「매우 크게」가 약 1.3배라
      18px은 거의 딱 붙는다(실측). 여유를 두고 16px에서 멈춘다.
   ⚠️ 굵게 만들지 말 것 — Jua는 굵기 400 하나뿐이라 가짜 볼드로 획이 뭉갠다. */
.gram-jm-head { font-size: 19px; color: var(--g-muted); margin-bottom: 3px; }
.gram-cmp-col.has .gram-jm-head { color: var(--g-red-deep); }
/* ★ v220: 앞 글자를 흐리게 두던 것(.pre)을 그만뒀다. 「커피」의 커가 회색이면 그 글자를
   못 배운 말처럼 읽는다 — 규칙이 마지막 글자의 문제라는 신호는 아래 밑줄이 이미 낸다.
   밑줄은 마지막 글자 폭만큼, 끝이 둥근 굵은 막대. border-bottom으로는 둥글게 못 해서
   ::after로 그린다(그래서 .last는 inline-block, 부모엔 막대가 앉을 아래 여백을 준다). */
.gram-jm-word { font-size: 28px; color: var(--g-ink); line-height: 1.25; padding-bottom: 11px; }
.gram-jm-word .last { position: relative; display: inline-block; }
.gram-jm-word .last::after {
  content: ''; position: absolute; left: 3%; right: 3%; bottom: -6px;
  height: 5px; border-radius: 3px; background: var(--g-gray);
}
.gram-cmp-col.has .gram-jm-word .last::after { background: var(--g-red); }
.gram-jm-caption { font-size: 13px; color: var(--g-muted); margin-top: 0; }
/* ★ v254 — 「받침」 밑의 뜻풀이 한 줄. ㄱ~ㄹ에서만 붙는다(app.js gramGloss).
   카드의 「큰 한글 / 작은 나라말」 짜임을 그대로 따른다 — .gram-two-when-en과 한 벌이다.
   ⚠️ 한글이 아니라 나라말이 들어오는 자리다. 태국어·러시아어가 길어 두 줄이 될 수 있어
   line-height를 조금 준다. */
.gram-jm-sub {
  font-size: 11.5px; color: var(--g-rom); margin-top: 1px; line-height: 1.25;
  font-family: 'Fraunces', 'Jua', serif; font-style: italic; font-weight: 400;
}
.gram-jm-sub-inline { font-size: 12px; color: var(--g-rom); font-style: italic; }
.gram-jm-arrow {
  width: 0; height: 0; margin: 3px 0 4px;
  border-left: 6px solid transparent; border-right: 6px solid transparent;
  border-top: 9px solid var(--g-gray);
}
.gram-cmp-col.has .gram-jm-arrow { border-top-color: var(--g-red); }
.gram-jm { display: flex; align-items: flex-start; justify-content: center; gap: 6px; }
/* 칸 아래마다 이름표가 붙으므로 행이 4줄이다:
   [head칸][body칸] / head  body / [tail칸 가로 전체] / tail */
.gram-jm-grid { display: grid; grid-template-columns: repeat(2, var(--jm-box)); column-gap: 6px; row-gap: 4px; }
.gram-jm-box {
  height: var(--jm-box); display: flex; align-items: center; justify-content: center;
  font-size: var(--jm-font); color: var(--g-ink);
  background: #FFFDF7; border: 3px solid var(--g-box-bd); border-bottom-width: 5px; border-radius: 12px;
}
.gram-jm-jong { grid-column: 1 / -1; margin-top: 5px; }
.gram-jm-jong.on { background: var(--g-tail); border-color: var(--g-tail-bd); }
.gram-jm-jong.empty { background: #F9F3E5; border: 3px dashed var(--g-line); }
/* head / body / tail — 초성·중성·종성이라는 용어를 대신하는 이름표.
   ★ "첫 조각·가운데 조각·마지막 조각"이라는 순서 개념이다. "위·가운데·아래"가 아니다 —
     소·무처럼 모음이 아래에 오는 글자에서 tail을 위치로 가르치면 오해한다. */
.gram-jm-label {
  font-size: 14px; color: var(--g-muted); text-align: center; letter-spacing: .3px; margin-top: 1px;
}
.gram-jm-label.wide { grid-column: 1 / -1; }
.gram-jm-label.on { color: var(--g-red); }
/* 카드 테두리·좌우 여백이 생긴 만큼(칸당 약 17px) 좁은 폰에서는 한 단계 더 줄인다.
   여기를 키우면 「커피예요」가 카드를 넘어 두 줄로 접힌다. */
@media (max-width: 430px) {
  .gram-cmp-col { --jm-box: 39px; --jm-font: 23px; padding: 9px 3px 11px; }
  .gram-jm-head { font-size: 16px; }
  .gram-jm-word { font-size: 25px; padding-bottom: 11px; }
  .gram-cmp-word { font-size: 22px; }
  .gram-jm-label { font-size: 13px; }
  .gram-jm-caption { font-size: 12px; }
}

/* ── 안 갈리는 조사 (틀 D · v225) ──────────────────────────────
   ㄷ9 「어디에 있어요?」처럼 조사가 받침과 무관하게 늘 같은 책. 카드 두 장 배치와
   좌우 색(.has = 크림+금테)은 받침 대조와 **똑같이 둔다** — 독자가 아는 틀이라야
   "이번엔 양쪽이 같네"가 대비로 들어온다. 다른 것은 카드 안 내용뿐이다.
   ⚠️ 여기 여백을 받침 대조와 다르게 잡지 말 것. 두 쪽이 같은 틀로 보여야 대비가 산다. */
.gram-same-w { font-size: 26px; color: var(--g-ink); margin-top: 2px; }
.gram-same-plus { font-size: 15px; color: var(--g-rom); margin: 5px 0 3px; line-height: 1; }
/* 조사 칸 — 받침 대조의 tail 칸과 같은 금색. "이 자리가 바뀌는 자리"라는 신호를
   그대로 쓰되, 양쪽이 같은 값이라 바뀌지 않는다는 것이 이 쪽의 내용이다. */
.gram-same-p {
  font-size: 26px; color: var(--g-ink);
  background: var(--g-tail); border: 3px solid var(--g-tail-bd); border-bottom-width: 5px;
  border-radius: 12px; padding: 2px 16px;
}
/* 결론 한 줄 — .gram-band-foot과 달리 윗선을 두지 않는다. 바로 위가 이미 카드라
   선을 또 그으면 칸이 셋으로 보인다. */
.gram-same-foot { text-align: center; font-size: 15px; color: var(--g-muted); margin-top: 16px; }
.gram-same-foot .amb { font-size: 1.05em; }
/* ★ v253 — 밑줄도 카드와 같이 두 줄로: 위는 한국어, 아래는 읽는 사람의 말.
   .gram-two-when / -when-en 짝과 크기·서체를 맞춰 한 화면이 한 규칙으로 읽히게 한다. */
.gram-foot-ko { color: var(--g-ink); line-height: 1.35; word-break: keep-all; }
.gram-foot-en {
  font-size: 11.5px; color: var(--g-rom); margin-top: 3px;
  font-family: 'Fraunces', 'Jua', serif; font-style: italic;
}
@media (max-width: 430px) {
  .gram-same-w, .gram-same-p { font-size: 23px; }
  .gram-same-p { padding: 2px 13px; }
  .gram-same-foot { font-size: 14px; }
}

/* 활용 */
.gram-conj { display: flex; flex-direction: column; gap: 14px; align-items: center; }
.gram-conj-row { font-size: 22px; color: var(--g-ink); display: flex; align-items: center; gap: 14px; }
.gram-conj-from { color: var(--g-muted); }
.gram-conj-arr { color: var(--g-gray); font-size: 18px; }

/* Words in This Book (마지막 쪽) — 왼쪽=이 책의 말(tail 있음), 오른쪽=다음에 배울 말 */
/* v203: 여기 있던 `justify-content: safe center`(세로 가운데)를 뺐다.
   속표지·words to know·문법 1~2쪽이 모두 위에서 시작하는데 이 쪽만 가운데면
   넘길 때마다 제목이 아래로 툭 내려갔다 올라온다. 허전함보다 일관성이 우선. */
.gram-wordcol-head .arr { color: var(--g-gray); }
.gram-wordcols { display: grid; grid-template-columns: 1fr 1px 1fr; align-items: start; }
/* ★ v209 min-width:0 — 이거 없으면 격자 칸(1fr)이 min-width:auto라서 긴 말덩이가
   들어올 때 칸이 그만큼 늘어나 글자가 화면 밖으로 삐져나간다(실제로 재현됨).
   0으로 막아야 칸이 폭을 지키고 긴 줄이 얌전히 접힌다. */
.gram-wordcol { display: flex; flex-direction: column; align-items: center; padding: 0 8px; min-width: 0; }
/* ★ v209: 칸 안 낱말도 시작을 세로로 맞춘다(덩어리 자체는 margin auto로 칸 가운데).
   한 덩어리 목록(.solo, v208)과 같은 원칙 — 훑어 내려가며 비교하는 목록은 왼쪽. */
.gram-wordcol .gram-wordlist { align-items: flex-start; width: max-content; max-width: 100%; margin: 0 auto; }
.gram-wordcol-div { align-self: stretch; background: var(--g-line); }
/* 칸 소제목 — "in this book" / "coming next". v204에서 잔글씨(11px 이탤릭)에서
   소제목 크기·굵기로 올렸다. 두 칸이 무엇으로 갈리는지가 이 쪽의 뼈대라서. */
.gram-wordcol-tag {
  font-size: 16px; color: var(--g-ink); letter-spacing: .3px; margin-bottom: 2px;
}
/* 두 줄 고정("with a tail" / "→ 이에요") — 한 줄로 두면 좁은 칸에서 조사가
   "이에 / 요"처럼 글자 중간에서 끊긴다. line-height로 두 줄 간격만 좁힌다. */
.gram-wordcol-head {
  font-size: var(--aux-en); color: var(--g-muted);
  margin: 2px 0 12px; padding-bottom: 8px; text-align: center; line-height: 1.5;
  border-bottom: 3px dotted var(--g-line); width: 100%;
}
.gram-wordlist { display: flex; flex-direction: column; align-items: center; gap: 9px; }
/* ★ v208: 한 덩어리 목록(다음에 배울 말이 없는 책)은 낱말의 시작을 세로로 맞춘다.
   가운데 정렬은 낱말 길이가 제각각이라(할아버지예요 ↔ 우리) 좌우가 다 들쭉날쭉했다.
   덩어리 자체는 width:max-content + margin auto로 여전히 화면 가운데에 앉는다 —
   페이지 왼쪽 끝에 붙이면 오른쪽이 통째로 비어 허전하다.
   두 칸(coming next) 화면은 칸 폭이 절반뿐이라 긴 말덩이가 넘칠 수 있어 그대로 둔다. */
.gram-wordlist.solo { align-items: flex-start; width: max-content; max-width: 100%; margin: 0 auto; }
.gram-word { font-size: var(--aux-ko); color: var(--g-word); }
/* 받침(tail)만 빨갛게 — 이에요가 붙는 이유를 낱자 하나로 지목.
   완성형 한글은 글자 하나가 통짜라 종성만 색칠할 수 없으므로, 글자 높이에
   그라디언트를 걸고 background-clip:text로 글자 획에만 입힌다.
   ⚠ background 단축속성을 쓰면 background-clip이 초기화되어 글자가 통째로
   사각형이 된다 — 반드시 background-image로 쓸 것.
   지원 안 하는 브라우저에선 아래 @supports가 통째로 무시되어 글자 전체가
   빨갛게만 보인다(글자가 사라지지 않음).
   ★ v204: 파랑(#2B6CA8) → 빨강. 파랑은 검은 본문 글자와 명도가 비슷해서
     "획 아래쪽만 색이 다르다"는 신호가 거의 안 보였다. 굵기는 이미 700(이 글꼴의
     최대)이라 더 굵게 할 수 없어, 눈에 띄게 만드는 몫은 전부 색이 맡는다. */
/* ★ v220: 글꼴이 Gowun Batang → Jua로 바뀌면서 경계값(62% / 68%)을 다시 잡았다.
   두 글꼴의 실제 자형을 재보니 Jua는 받침이 같은 글자에서 약 0.89배 높이에서 시작한다
   (밥 0.887 · 말 0.876 · 책 0.929 · 솝 0.899 · 못 0.906 · 곰 0.898 — 평균 ≈0.89).
   62 × 0.89 ≈ 55 / 68 × 0.89 ≈ 61. 글꼴을 또 바꾸면 이 두 값도 반드시 다시 잴 것 —
   그냥 두면 빨강이 받침 위/아래로 어긋나 획 하나가 두 색으로 잘린다. */
.gram-word .bat { color: #C62828; }
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .gram-word .bat {
    color: transparent; -webkit-text-fill-color: transparent;
    -webkit-background-clip: text; background-clip: text;
  }
  .gram-word .bat-v { background-image: linear-gradient(to bottom, var(--g-word) 0 55%, #C62828 55% 100%); }
  .gram-word .bat-h { background-image: linear-gradient(to bottom, var(--g-word) 0 61%, #C62828 61% 100%); }
}
.gram-words-note { font-size: var(--aux-tag); color: var(--g-rom); text-align: center; margin-top: 20px; }

/* v231에서 이 자리에 "낱말 목록을 98px 내려 words to know의 첫 낱말 높이에 맞추는"
   장치가 있었다. v232에서 뺐다 — 첫 낱말 높이는 맞았지만 words to know는 그 자리를
   Level 딱지와 NOUNS 이름표가 채우는 반면 이 쪽은 그냥 비어서, 제목과 예문 사이에
   구멍이 뚫린 것처럼 보였다. 어긋나 보인 진짜 원인은 쪽의 위 여백(20 vs 32px)이었고
   그건 .reader-page.grammar-page에서 고쳤다. 예문은 제목 바로 밑이 맞다. */
/* ★ v202: 여기 있던 .gram-word 17px / .gram-wordcol-head 13px 축소는 뺐다.
   폭 430px 이하가 사실상 대부분의 폰(아이폰 393px)이라, 이 축소가 살아 있으면
   같은 폰에서 words to know는 20px인데 문법 단어만 17px이 되어 통일이 무너진다.
   2열 폭 170px에 6글자(120px)까지 들어가므로 20px로도 넘치지 않는다. */
@media (max-width: 430px) {
  .gram-wordcol { padding: 0 4px; }
  .gram-words-note { font-size: 12px; }
}

/* ── 사진 영역: 내용 크기로 고정, 최대 화면의 절반 정도까지 ── */
.reader-photo-wrap {
  flex: 0 0 auto;
  min-height: 200px;
  max-height: 48vh;
  padding: 12px 20px 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: white;
  overflow: hidden;
}

/* 사진: 영역 안에서 비율 유지하며 꽉 채움 */
/* onload 발화 전에도 컨테이너를 넘지 않도록 width:100%를 기본값으로 둠.
   onload 후 .landscape / .portrait 클래스가 붙으면 그에 맞게 미세 조정됨. */
.reader-photo-img {
  display: block;
  border-radius: 10px;
  box-shadow: 0 3px 14px rgba(0,0,0,0.10);
  max-width: 100%;
  max-height: 100%;
  width: 100%;
  height: auto;
  object-fit: contain;
}

/* 가로형 사진 */
.reader-photo-img.landscape {
  width: 100%;
  height: auto;
  max-height: 100%;
}

/* 세로형 사진 */
.reader-photo-img.portrait {
  height: 100%;
  width: auto;
  max-width: 100%;
}

.reader-photo-placeholder {
  width: 100%;
  aspect-ratio: 4/3;
  max-width: 100%;
  max-height: 100%;
  border-radius: 10px;
  background: var(--paper-warm);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 56px;
  color: var(--ink-soft);
}

/* ── 텍스트 영역 (긴 본문 기본): 위에서부터 채우고 넘치면 스크롤 ── */
.reader-text-area {
  flex: 1 1 0;
  min-height: 0;
  padding: 20px 22px 128px;  /* 하단: 미니컨트롤+위쪽 흰색 페이드 가시영역 전체를 커버 */
  display: block;
  background: white;
  overflow-y: auto;          /* 넘칠 때만 스크롤(+iOS 바운스), 짧으면 스크롤 없음 */
  overscroll-behavior-y: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  width: 100%;
}
.reader-text-area::-webkit-scrollbar { width: 4px; }
.reader-text-area::-webkit-scrollbar-track { background: transparent; }
.reader-text-area::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.08); border-radius: 2px; }

/* ── 짧은 본문 페이지(is-short): 이미지+텍스트를 세로 중앙에 모으고 이미지를 키움 ── */
.reader-page.is-short { justify-content: center; padding-bottom: 8vh; } /* ★v128: 그림+텍스트를 살짝 위로 (하단 컨트롤 바 보정) */
.reader-page.is-short .reader-photo-wrap { flex: 0 0 auto; max-height: 58vh; }  /* 공간 여유분으로 이미지 키움 */
.reader-page.is-short .reader-text-area {
  flex: 0 0 auto;            /* 남는 공간 안 먹고 콘텐츠 크기만 */
  overflow: visible;         /* 짧으니 스크롤 불필요 */
  padding: 18px 22px 24px;   /* 하단 큰 패딩 불필요 (스크롤 안 함) */
}
/* 짧은 본문 가운데 정렬 — v149: 한 문단이 한 줄 안에 들어가는 경우에만(.is-oneline,
   app.js에서 실측 부여). 두 줄 이상 문단을 가운데 두면 좌우 끝이 모두 들쭉날쭉해짐
   ★ v177: 번역문(.reader-text-en)도 같은 규칙 — 예전엔 무조건 가운데라, 문단이 나뉘고 나니
   문단마다 시작점이 달라 지저분했고 한국어(왼쪽)와 조판이 달라 토글할 때 글이 튀었다. */
.reader-page.is-short .reader-text.is-oneline,
.reader-page.is-short .reader-text-en.is-oneline { text-align: center; }

/* ── 본문 텍스트 (한국어 / 영어 토글) ── */
.reader-text {
  font-family: 'Gowun Batang', serif;
  font-size: 22px;
  line-height: 1.6;
  color: var(--ink);
  text-align: left;
  word-break: keep-all;       /* 한국어를 어절(띄어쓰기) 단위로만 줄바꿈 */
  overflow-wrap: break-word;  /* 단어가 너무 길면 그때만 강제 줄바꿈 */
  width: 100%;
  transition: opacity 0.2s;
}
.reader-text.size-a { font-size: 24px; font-weight: 700; }
.reader-text.size-c { font-size: 20px; line-height: 1.65; }

/* 문단 블록 (v149): 편집기의 줄바꿈(\n)마다 하나. 한 문단 안의 문장들은 마침표에서
   끊지 않고 이어져 흐르므로 줄이 꽉 찬 사각형 문단이 된다. 문단 사이에만 여백. */
.reader-para { display: block; }
.reader-para:not(:last-child) { margin-bottom: 0.9em; }

/* ── 조판 미세조정 모드 (편집자 전용, app.js toggleTweakMode) ──
   문단별 letter-spacing을 수동 조정해 아랫줄로 밀린 어절을 윗줄로 끌어올림 */
body.tweak-mode #readerPages .reader-text .reader-para {
  outline: 1.5px dashed rgba(90, 74, 160, 0.35);
  outline-offset: 4px; border-radius: 4px; cursor: pointer;
}
body.tweak-mode #readerPages .reader-para.tweak-sel {
  outline: 2.5px solid var(--orange); background: rgba(255, 241, 168, 0.35);
}
.tweak-bar {
  position: fixed; left: 12px; right: 12px; bottom: 86px; z-index: 90;
  background: var(--navy-deep); color: #fff; border-radius: 16px;
  padding: 12px 14px 12px; box-shadow: 0 8px 28px rgba(0,0,0,0.3);
}
.tweak-bar.hidden { display: none; }
/* 닫기(✕): 바 우측 상단 모서리에 걸치는 배지 — 재생 바(.play-sheet-close)와 동일 규격 */
.tweak-close {
  position: absolute;
  top: -9px; right: -6px;
  width: 26px; height: 26px;
  border-radius: 50%;
  border: 2px solid rgba(255,255,255,0.9);
  background: rgba(26,58,92,0.95);
  display: flex; align-items: center; justify-content: center;
  padding: 0;
  cursor: pointer;
  z-index: 2;
  box-shadow: 0 2px 6px rgba(0,0,0,0.35);
  transition: transform 0.15s;
}
.tweak-close:active { transform: scale(0.88); }
.tweak-close svg { width: 13px; height: 13px; color: #fff; }
.tweak-hint { font-size: 12px; opacity: 0.85; margin-bottom: 10px; text-align: center; }
.tweak-controls { display: flex; gap: 8px; align-items: center; justify-content: center; flex-wrap: wrap; }
.tweak-btn {
  border: none; border-radius: 10px; background: rgba(255,255,255,0.16);
  color: #fff; font-size: 17px; font-weight: 700; padding: 9px 16px; cursor: pointer;
  line-height: 1;
}
.tweak-btn:active { background: rgba(255,255,255,0.32); }
.tweak-val { min-width: 58px; text-align: center; font-family: 'Fraunces', serif; font-size: 14px; font-weight: 600; opacity: 0.9; }
.tweak-reset { font-size: 13px; font-weight: 600; }
.tweak-save { background: var(--orange); font-size: 14px; }

/* 어절 묶음(구간) 반복 재생 — 현재 묶음 하이라이트
   ★ 가로 패딩은 반드시 같은 크기의 음수 마진으로 상쇄할 것: 상쇄하지 않으면 어절마다
   줄 폭이 늘어나 재생을 시작하는 순간 줄바꿈이 일반 화면과 달라진다(글이 다시 흐름).
   조판 미세조정(문단별 letter-spacing)도 그만큼 어긋나므로 이 규칙을 깨지 말 것.
   세로 패딩은 인라인 박스라 줄 높이에 영향 없음 → 그대로 둬도 안전. */
.reader-text .seg-word { transition: color 0.15s, background 0.15s; border-radius: 6px; padding: 1px 0; }
.reader-text .seg-word.seg-dim { color: #c4bdae; }
.reader-text .seg-word.seg-chunk { background: #FFF1A8; color: #1f1d1a; padding: 2px 6px; margin: 0 -6px; }
.reader-text .seg-word.seg-on { background: #B7F0C2; color: #1f1d1a; padding: 2px 6px; margin: 0 -6px; }
/* 어학기 상태 칩 */
.seg-chip {
  position: absolute; top: 8px; left: 50%; transform: translateX(-50%);
  background: var(--orange); color: #fff; font-size: 12px; font-weight: 600;
  padding: 4px 12px; border-radius: 20px; z-index: 30;
  box-shadow: 0 2px 6px rgba(0,0,0,0.15); opacity: 0; pointer-events: none;
  transition: opacity 0.2s; white-space: nowrap;
}
.seg-chip.show { opacity: 1; }

/* 영어 본문 (toggle 시 한국어 대신 표시) */
.reader-text-en {
  font-family: 'Fraunces', serif;
  font-size: 19px;
  line-height: 1.6;
  color: var(--ink);
  text-align: left;
  overflow-wrap: break-word;
  width: 100%;
  font-style: italic;
  display: none;
  transition: opacity 0.2s;
}

/* show-trans 모드: 한국어 숨김, 영어 표시 */
.reader-page.show-trans .reader-text { display: none; }
.reader-page.show-trans .reader-text-en { display: block; }

/* ── 페이지 번호 + 책 이름 (진행바와 겹쳐 숨김) ── */
.reader-page-meta {
  display: none;
}

/* ────────────────────────────────────────
   리더 EN 토글 (하단 미니 컨트롤 안, 진행바 왼쪽)
   ──────────────────────────────────────── */
.reader-en-toggle {
  flex-shrink: 0;
  pointer-events: auto;
  background: rgba(255,255,255,0.95);
  color: var(--navy);
  border: 1.5px solid var(--navy);
  font-family: 'Fraunces', serif;
  font-size: 11px;
  font-weight: 700;
  padding: 0 14px;
  border-radius: 100px;
  line-height: 1;
  letter-spacing: 0.5px;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  transition: all 0.15s;
  height: 34px;
  min-width: 46px;
  box-shadow: 0 1px 5px rgba(0,0,0,0.1);
  cursor: pointer;
}
.reader-en-toggle:active { transform: scale(0.95); }
.reader-en-toggle.active {
  background: var(--orange);
  color: white;
  border-color: var(--orange);
}
/* 표지/단어장 페이지에서는 EN 토글 숨김 */
.reader-wrap.hide-ctrl .reader-en-toggle { display: none; }

/* ────────────────────────────────────────
   리더 미니 컨트롤 (우측 하단 FAB + 진행바)
   ──────────────────────────────────────── */
.reader-mini-ctrl {
  position: absolute;
  bottom: max(24px, calc(env(safe-area-inset-bottom, 0px) + 4px)); /* ★v127: 컨트롤 바 살짝 위로 (기존 8~18px → 24~38px) */
  left: 14px;
  right: 14px;
  z-index: 9;
  display: flex;
  align-items: center;
  gap: 10px;
  pointer-events: none;  /* 빈 공간은 통과시켜 본문 탭 가능 */
}
/* 미니 컨트롤 위쪽으로 흰색 페이드 — 본문 글자가 자연스럽게 사라지도록 */
.reader-mini-ctrl::before {
  content: '';
  position: absolute;
  left: -14px;
  right: -14px;
  bottom: -16px;
  height: 100px;
  background: linear-gradient(to top, white 35%, rgba(255,255,255,0.9) 60%, rgba(255,255,255,0));
  pointer-events: none;
  z-index: -1;
}
.reader-mini-prog {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 8px;
  background: rgba(255,255,255,0.95);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-radius: 100px;
  padding: 7px 14px;
  pointer-events: auto;
  box-shadow: 0 1px 5px rgba(0,0,0,0.1);
}
.reader-mini-prog .reader-prog {
  flex: 1;
  height: 3px;
  background: rgba(0,0,0,0.1);
  border-radius: 100px;
  overflow: hidden;
}
.reader-mini-prog .reader-prog-fill {
  height: 100%;
  background: var(--orange);
  transition: width 0.4s;
}
.reader-mini-prog .reader-counter {
  font-family: 'Fraunces', serif;
  font-size: 11px;
  color: var(--ink-soft);
  font-weight: 600;
  letter-spacing: 0.5px;
  flex-shrink: 0;
}

/* FAB - 42px 직경, 오렌지 원형 */
.reader-fab {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background: var(--orange);
  color: white;
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 3px 10px rgba(232, 106, 58, 0.4), 0 1px 3px rgba(0,0,0,0.12);
  pointer-events: auto;
  flex-shrink: 0;
  cursor: pointer;
  transition: transform 0.15s, box-shadow 0.15s;
}
.reader-fab:active {
  transform: scale(0.92);
  box-shadow: 0 1px 4px rgba(232, 106, 58, 0.4);
}
.reader-fab svg { width: 20px; height: 20px; }

/* 재생 중일 때 FAB 살짝 펄스 */
.reader-fab.playing { animation: fabPulse 2s ease-in-out infinite; }
@keyframes fabPulse {
  0%, 100% { box-shadow: 0 3px 10px rgba(232, 106, 58, 0.4), 0 1px 3px rgba(0,0,0,0.12); }
  50% { box-shadow: 0 3px 14px rgba(232, 106, 58, 0.7), 0 1px 3px rgba(0,0,0,0.12); }
}

/* 표지/단어장 페이지에서는 미니 컨트롤 숨김 */
.reader-wrap.hide-ctrl .reader-mini-ctrl { display: none; }

/* ────────────────────────────────────────
   재생 컨트롤 바텀시트 (FAB 탭 → 열림)
   ──────────────────────────────────────── */
/* 반투명 재생 컨트롤 바 — 그림 위에 떠서 본문을 가리지 않음 */
.play-sheet {
  position: absolute;
  left: 16px; right: 16px;
  bottom: max(20px, calc(env(safe-area-inset-bottom, 0px) + 4px)); /* ★ 하단 고정 — 그림을 가리지 않음 (EN·진행·헤드폰 라인 자리에 덮음) */
  z-index: 12;                  /* 미니컨트롤(9)·탭존(3) 위, 옵션시트(600) 아래 */
  display: flex;
  justify-content: center;
  pointer-events: none;
}
.play-sheet.hidden { display: none; }
/* 컨트롤 바가 열리면 하단 EN/진행/헤드폰 라인 숨김 → X(닫기)로 복귀 */
.reader-wrap.bar-open .reader-mini-ctrl { display: none; }
.play-sheet-bg { display: none; }                 /* 어두운 오버레이 제거 */
.play-sheet-handle, .play-sheet-title { display: none; }
.play-sheet-body {
  position: relative;                /* 코너 X 버튼 기준 */
  pointer-events: auto;
  width: 100%;
  max-width: 360px;
  background: rgba(26,58,92,0.62);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border-radius: 18px;
  padding: 8px 10px;
  box-shadow: 0 6px 18px rgba(0,0,0,0.25);
  animation: barPop 0.18s ease;
}
/* 닫기(X): 바 우측 상단 라운드 코너의 작은 배지 */
.play-sheet-close {
  position: absolute;
  top: -9px; right: -6px;
  width: 26px; height: 26px;
  border-radius: 50%;
  border: 2px solid rgba(255,255,255,0.9);
  background: rgba(26,58,92,0.95);
  display: flex; align-items: center; justify-content: center;
  padding: 0;
  cursor: pointer;
  pointer-events: auto;
  z-index: 2;
  box-shadow: 0 2px 6px rgba(0,0,0,0.35);
  transition: transform 0.15s;
}
.play-sheet-close:active { transform: scale(0.88); }
.play-sheet-close svg { width: 13px; height: 13px; color: #fff; }
@keyframes barPop { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }
.play-sheet-grid {
  display: flex;
  align-items: flex-end;
  justify-content: space-around;
  gap: 4px;
}
.ps-btn {
  background: none;
  border: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 2px;
  cursor: pointer;
  flex: 1;
}
.ps-btn-circle {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: rgba(255,255,255,0.16);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.15s, background 0.15s;
}
.ps-btn-circle-large {
  width: 46px;
  height: 46px;
  background: var(--orange);
  box-shadow: 0 2px 8px rgba(232, 106, 58, 0.5);
}
.ps-btn:active .ps-btn-circle { transform: scale(0.92); background: rgba(255,255,255,0.28); }
.ps-btn:active .ps-btn-circle-large { background: var(--orange); }
.ps-btn-circle svg { width: 18px; height: 18px; color: #fff; }
.ps-btn-circle-large svg { width: 22px; height: 22px; color: white; }
.ps-btn#stopBtn .ps-btn-circle svg { color: #ffd9cc; }
.ps-btn-label {
  font-family: 'Fraunces', serif;
  font-size: 9px;
  color: rgba(255,255,255,0.85);
  letter-spacing: 0.2px;
}
.ps-btn-primary .ps-btn-label { font-weight: 700; color: #fff; }

.reader-vocab {
  padding: 0;  /* 좌우 여백 0 → 색 박스가 글자에 딱 맞음 (줄 밀림·이웃 글자 겹침·연속 하이라이트 병합 모두 방지) */
  border-radius: 3px;
  cursor: pointer;
  position: relative;
  transition: filter 0.15s;
  white-space: nowrap;  /* 하이라이트 단어는 줄바꿈 시 통째로 이동 */
  /* 안드로이드/모바일 터치 호환 */
  touch-action: manipulation;
  -webkit-tap-highlight-color: rgba(245, 158, 11, 0.3);
}
.reader-vocab:active { filter: brightness(0.88); }

/* ★ v168: 단어 span은 본문에 "항상" 들어 있고(A·B·C 전부), 보이기는 아래 클래스가 정한다.
   - 기본값 = 안 보임: 색·굵기 없음 + 탭도 안 먹음(pointer-events:none) → 평범한 글자와 똑같다.
     하이라이트를 끄면 읽기를 전혀 방해하지 않는다(가독성 저하 없음).
   - .reader-wrap.vocab-A|B|C|all 이 붙으면 해당 등급만 색이 켜지고 탭이 살아난다.
   전환이 CSS만으로 끝나므로 본문을 다시 렌더하지 않는다 → 글이 다시 흐르지 않고 조판도 유지된다. */
.reader-vocab, .reader-vocab-morph {
  background: transparent !important;
  border-bottom: none !important;
  color: inherit;
  font-weight: inherit;
  font-style: inherit;
  pointer-events: none;
}

/* 켜진 등급만 색 + 탭 복원.
   ⚠️ 굵게(font-weight)·기울임(font-style)은 절대 쓰지 않는다 — 글자 폭이 변해서
   하이라이트를 켜는 순간 줄바꿈이 달라진다(글이 다시 흐르고 조판 값도 어긋남).
   표시는 폭을 바꾸지 않는 배경색 + 밑줄로만 한다. (.seg-word 패딩 규칙과 같은 이유) */
.reader-wrap.vocab-all .reader-vocab,
.reader-wrap.vocab-A   .reader-vocab[data-grade="A"],
.reader-wrap.vocab-B   .reader-vocab[data-grade="B"],
.reader-wrap.vocab-C   .reader-vocab[data-grade="C"] {
  color: var(--navy-deep);
  pointer-events: auto;
}
.reader-wrap.vocab-all .reader-vocab-morph,
.reader-wrap.vocab-A   .reader-vocab-morph[data-grade="A"],
.reader-wrap.vocab-B   .reader-vocab-morph[data-grade="B"],
.reader-wrap.vocab-C   .reader-vocab-morph[data-grade="C"] {
  pointer-events: auto;
}
/* 등급별 색상 — 켜진 등급에만 */
.reader-wrap.vocab-all .reader-vocab[data-grade="A"],
.reader-wrap.vocab-A   .reader-vocab[data-grade="A"] { background:#FFF3CD !important; border-bottom:2px solid #f59e0b !important; }
.reader-wrap.vocab-all .reader-vocab[data-grade="B"],
.reader-wrap.vocab-B   .reader-vocab[data-grade="B"] { background:#D1FAE5 !important; border-bottom:2px solid #10b981 !important; }
.reader-wrap.vocab-all .reader-vocab[data-grade="C"],
.reader-wrap.vocab-C   .reader-vocab[data-grade="C"] { background:#DBEAFE !important; border-bottom:2px solid #3b82f6 !important; }
/* 활용형은 점선 밑줄로 구별 */
.reader-wrap.vocab-all .reader-vocab-morph[data-grade="A"],
.reader-wrap.vocab-A   .reader-vocab-morph[data-grade="A"] { border-bottom-style: dashed !important; }
.reader-wrap.vocab-all .reader-vocab-morph[data-grade="B"],
.reader-wrap.vocab-B   .reader-vocab-morph[data-grade="B"] { border-bottom-style: dashed !important; }
.reader-wrap.vocab-all .reader-vocab-morph[data-grade="C"],
.reader-wrap.vocab-C   .reader-vocab-morph[data-grade="C"] { border-bottom-style: dashed !important; }
/* 미지정(fallback) — 등급 없는 단어는 '전체'에서만 */
.reader-wrap.vocab-all .reader-vocab:not([data-grade]) { background:var(--highlight) !important; border-bottom:2px solid var(--orange) !important; }

/* ── 리더 어휘 버튼 + 등급 칩 (v168) ──
   버튼: 꺼짐이면 회색 '가', 켜지면 등급 글자(A/B/C/전체)가 강조색으로 */
/* ★ v172: 상단 바의 토글 알약 (번역 EN) — 꺼짐: 흐린 테두리 / 켜짐: 주황 알약 */
.topbar .topbar-pill {
  font-family: -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  font-size: 13px; font-weight: 600; letter-spacing: 0.02em;
  padding: 5px 11px; border-radius: 100px;
  border: 1px solid rgba(255,255,255,0.45); color: rgba(255,255,255,0.8);
  background: transparent; white-space: nowrap;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.topbar .topbar-pill.active { background: var(--orange); border-color: var(--orange); color: #fff; }
.topbar .topbar-pill:active { transform: scale(0.95); }

/* ★ v172: 하단 사전 버튼 — 'Dic' 글자, 상태는 색으로.
   꺼짐: 흰 알약에 흐린 글자 / 켜짐: 주황 알약 + 등급(Dic A · Dic 모두) */
.reader-dic-btn {
  font-family: -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  font-size: 13px; font-weight: 600; white-space: nowrap; padding: 0 12px;
}
.reader-dic-btn.active { background: var(--orange); border-color: var(--orange); color: #fff; }
/* ★ v169: 설정 화면과 같은 iOS 세그먼티드 컨트롤 + 화면 가운데 정렬.
   (v168의 오른쪽 정렬 칩은 화면 밖으로 밀려 나가 '모두' 칩이 우측 탭존(22%)과 겹쳤다 —
    그래서 누르면 페이지가 넘어갔다. 이제 탭 핸들러 제외 목록에도 .reader-vocab-picker가 있다.) */
.reader-vocab-picker {
  /* ★ v176: 미니 컨트롤 "위"(bottom:78px)에 띄우니 본문 마지막 줄을 덮었다.
     이제 미니 컨트롤과 같은 자리(같은 bottom)에 놓고, 열려 있는 동안 미니 컨트롤
     내용물을 감춘다 → 본문이 이미 비켜 둔 공간이라 겹침이 생기지 않는다. */
  position: absolute; left: 50%; transform: translateX(-50%);
  bottom: max(24px, calc(env(safe-area-inset-bottom, 0px) + 4px));
  z-index: 40;
  width: min(340px, calc(100% - 28px));
  display: flex; gap: 2px; padding: 2px;
  background: rgba(239,239,240,0.97);
  -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px);
  border-radius: 9px; box-shadow: 0 4px 16px rgba(0,0,0,0.18);
}
.reader-vocab-picker.hidden { display: none; }
/* 칩이 열린 동안: 미니 컨트롤 내용물만 숨김. .reader-mini-ctrl 자체는 남겨야
   위쪽 흰색 페이드(::before)가 유지돼 본문 글자가 자연스럽게 사라진다. */
.reader-wrap.picker-open .reader-mini-ctrl > * { visibility: hidden; }
.rv-chip {
  /* v176: 미니 컨트롤과 같은 높이(≈44px)로 맞춰 자리를 대신해도 하단이 들썩이지 않게 */
  flex: 1; border: none; background: transparent; border-radius: 7px; padding: 11px 0;
  font-family: -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  font-size: 13px; font-weight: 500; color: #000; white-space: nowrap;
  transition: background 0.15s, box-shadow 0.15s;
}
.rv-chip.active {
  background: #fff;
  box-shadow: 0 3px 8px rgba(0,0,0,0.12), 0 1px 1px rgba(0,0,0,0.04);
}
.reader-wrap.hide-ctrl .reader-vocab-picker { display: none; }

/* Phase 2-B-1: 활용형 표시 (점선 밑줄로 구별)
   ★ v168: 색·밑줄 규칙은 위의 .reader-wrap.vocab-* 블록으로 옮겼다.
   여기 있던 [data-grade] 색 규칙은 !important라서 "꺼짐"에서도 색이 남았을 것 —
   그래서 삭제했다. 여기에는 색과 무관한 것만 남긴다. */
.reader-vocab-morph {
  display: inline-block !important;
  touch-action: manipulation;
  -webkit-tap-highlight-color: rgba(245, 158, 11, 0.4) !important;
  user-select: none;
  -webkit-user-select: none;
  min-height: 24px;   /* 탭 영역 확보 — 켜고 끌 때 값이 변하지 않아야 줄 높이가 흔들리지 않는다 */
  position: relative;
  z-index: 1;
}
.reader-vocab-morph:active {
  filter: brightness(0.85);
  transform: scale(0.98);
}

/* 재생(듣기) 중에는 어휘 등급 하이라이트를 보이지 않게 → 페이지 전환 시 깜빡임 방지.
   어느 페이지가 어느 순간에 그려지든 재생 중에는 일반 텍스트로만 보인다. */
.reader-wrap.is-playing .reader-vocab,
.reader-wrap.is-playing .reader-vocab-morph {
  background: transparent !important;
  border-bottom: none !important;
}
.vocab-popup-morph {
  padding: 4px 8px;
  background: rgba(245, 158, 11, 0.1);
  border-radius: 4px;
  margin: 4px 0;
}

/* ─── 어휘 미리보기 페이지 (표지와 본문 사이) ─── */
/* ─── 단어장 페이지 (깔끔한 2줄 레이아웃 + 탭하여 펼치기) ─── */
.reader-page.vocab-preview-page {
  background: #fff;
  padding: 32px 24px 40px;
  justify-content: flex-start;
  align-items: stretch;
  overflow-y: auto;
}
.vocab-preview-header {
  text-align: center;
  margin-bottom: 28px;
  flex-shrink: 0;
}
.vocab-preview-title-en {
  font-family: 'Fraunces', serif;
  font-style: italic;
  font-weight: 700;
  font-variation-settings: 'opsz' 96, 'wght' 700;
  font-size: var(--aux-title);
  color: #25394B;               /* ★ v222: 속표지 제목과 동일 */
  letter-spacing: 0.5px;
  margin-bottom: 12px;
}
.vocab-preview-badges {
  display: inline-flex;
  gap: 6px;
  flex-wrap: wrap;
  justify-content: center;
}
.vocab-preview-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: 'Fraunces', serif;
  font-size: var(--aux-label);
  font-weight: 600;
  padding: 4px 12px;
  border-radius: 100px;
  letter-spacing: 0.5px;
}
.vocab-preview-badge.A { background: #E8E4F0; color: #5B4E7A; }
.vocab-preview-badge.B { background: #E0EBE0; color: #3D5C42; }
.vocab-preview-badge.C { background: #F0E4C8; color: #7A5A1F; }

.vocab-preview-box {
  flex: 1;
  padding: 0;
}

/* 단어가 많은 책은 한 단계 작게 (v202).
   기본 한글 20px로 한 화면에 들어오는 건 뜻이 붙은 단어 6~8개까지다. 9개부터
   app.js가 .is-dense를 붙이고 여기서 변수만 낮춘다.
   ★ 크기는 전부 var()로 쓰여 있으므로 이 세 줄만으로 페이지 전체가 따라 줄어든다.
   ※ 12~13개가 넘으면 어떤 크기로도 한 화면엔 못 담는다 — 스크롤을 없애는 게 아니라
     줄이는 장치다(옛 16px 고정 시절에도 8개가 한계였다). */
.reader-page.vocab-preview-page.is-dense {
  --aux-ko:  17px;
  --aux-en:  13px;
  --aux-rom: 13px;
}
.reader-page.vocab-preview-page.is-dense .vocab-b-row { padding: 10px 4px; }
.reader-page.vocab-preview-page.is-dense .vocab-pos-group { margin-bottom: 18px; }

/* 품사 그룹 */
.vocab-pos-group { margin-bottom: 24px; }
.vocab-pos-group:last-child { margin-bottom: 0; }

.vocab-pos-label {
  font-family: 'Fraunces', serif;
  font-size: var(--aux-label);
  font-style: italic;
  color: var(--aux-beige);
  letter-spacing: 1.5px;
  text-transform: uppercase;
  text-align: center;
  margin-bottom: 14px;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(168,152,120,0.25);
}

/* 행 — 한국어 단어 자체가 탭 영역 */
.vocab-b-row {
  padding: 14px 4px;
  border-bottom: 1px solid #F1EFEA;
  -webkit-tap-highlight-color: transparent;
}
.vocab-b-row:last-child { border-bottom: none; }

/* 메인 라인: [한국어 ─── 로마자] */
.vocab-b-main {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 4px;
}
/* 한국어 단어 — 탭하면 발음 재생 (teal 색으로 인터랙티브 표시) */
/* min-width: 64px → 한 글자 단어("또", "더" 등)도 약 3글자 너비 탭 영역 확보
   text-align: left → 글자는 왼쪽에 정렬되고 오른쪽 빈 공간이 투명한 탭 영역
   display: inline-block → button 요소에 min-width가 실제로 적용되도록
   border-radius + active background → 탭 시 옅은 teal 음영으로 탭 영역 시각화 */
.vocab-b-kor {
  /* ★ v222: 속표지·문법과 같은 Jua로. ⚠ Jua는 굵기 400 하나뿐 — font-weight 금지 */
  font-family: 'Jua', sans-serif;
  font-size: var(--aux-ko);
  color: #3C7855;
  letter-spacing: -0.2px;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: opacity 0.15s, background 0.15s;
  min-width: 64px;
  text-align: left;
  display: inline-block;
  border-radius: 4px;
}
.vocab-b-kor:active {
  opacity: 0.55;
  background: rgba(60, 120, 85, 0.08);
}
.vocab-b-rom {
  font-family: 'Fraunces', serif;
  font-style: italic;
  font-size: var(--aux-rom);
  color: var(--aux-beige);
  white-space: nowrap;
}

/* 영어 뜻 (두 번째 줄) */
.vocab-b-eng {
  font-family: 'Fraunces', serif;
  font-size: var(--aux-en);
  color: #5C544A;
  line-height: 1.45;
}

/* 행 재생 중 표시 */
.vocab-b-row.playing {
  background: rgba(60,120,85,0.05);
}
.vocab-b-row.playing .vocab-b-kor {
  opacity: 0.6;
}
.vocab-b-row.expanded {
  background: rgba(30,58,95,0.04);
}

/* 펼친 의역 영역 */
.vocab-b-note {
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  transition: max-height 0.3s ease, padding 0.3s ease, opacity 0.25s ease;
  /* ★ v222: 이 줄은 영어와 한글이 섞인다(예문). Fraunces엔 한글이 없어 한글만
     기기 기본 글꼴로 떨어졌다 — 뒤에 Jua를 받쳐 어느 기기에서나 같게 나오게 한다. */
  font-family: 'Fraunces', 'Jua', serif;
  font-size: var(--aux-rom);
  font-style: italic;
  color: #6B5F4F;
  line-height: 1.6;
  padding: 0;
  border-left: 2px solid rgba(30,58,95,0.2);
  margin-top: 0;
}
.vocab-b-row.expanded .vocab-b-note {
  max-height: 200px;
  padding: 8px 4px 4px 12px;
  margin-top: 8px;
  opacity: 1;
}

/* 어휘 팝업 카드 */
.vocab-popup {
  position: fixed;
  z-index: 800;
  background: white;
  border-radius: 16px;
  box-shadow: 0 8px 32px rgba(0,0,0,0.18), 0 2px 8px rgba(0,0,0,0.10);
  padding: 16px 20px 14px;
  min-width: 200px;
  max-width: 280px;
  text-align: center;
  pointer-events: auto;
  animation: vocabPop 0.18s cubic-bezier(0.34,1.56,0.64,1);
}
@keyframes vocabPop {
  from { opacity: 0; transform: scale(0.85) translateY(6px); }
  to   { opacity: 1; transform: scale(1) translateY(0); }
}
.vocab-popup-word {
  font-family: 'Gowun Batang', serif;
  font-size: 22px;
  font-weight: 700;
  color: var(--navy-deep);
  margin-bottom: 6px;
}
/* v245~ 미사용 — 로마자 줄을 «듣기»(.vp-speak)로 바꿨다. 되살리려면 app.js의
   #vp-romaji 줄만 복구하면 된다. 규칙은 남겨 둔다. */
.vocab-popup-romaji {
  font-family: 'Fraunces', serif;
  font-style: italic;
  font-size: 14px;
  color: var(--blue);
  margin-bottom: 4px;
  min-height: 20px;
}
.vocab-popup-english {
  font-family: 'Fraunces', serif;
  font-size: 15px;
  color: var(--ink-soft);
  margin-bottom: 10px;
  min-height: 20px;
}
.vocab-popup-loading {
  font-size: 12px;
  color: var(--ink-soft);
  font-family: 'Fraunces', serif;
  font-style: italic;
  opacity: 0.7;
  min-height: 18px;
}
/* ★ v244: 리더 하단 왼쪽을 비웠다.
   그 버튼이 하던 일은 «A·B·C 등급별 본문 하이라이트 켜기»뿐이었다. 등급은 국립국어원
   학습용 어휘 등급이라 읽는 사람에겐 아무 뜻이 없고, 한 쪽에 48곳까지 칠해져
   (그중 14곳은 「정했어요」·「한양」처럼 낱말 한가운데) 글을 가렸다.
   낱말 뜻은 이제 **본문 아무 데나 길게 누르면** 나온다 — 사전에 없는 말도 번역이 답한다.
   ⚠️ 기능과 코드는 그대로 남아 있다. 제작자가 검수하며 등급을 보려면 **이 한 줄만 지우면** 된다. */
.reader-dic-btn.admin-filter, .reader-vocab-picker.admin-filter,
.vocab-popup-grade.admin-filter { display: none; }

/* ── 사전 창의 «지금 읽는 말» · «다른 모습» (v243) ──────────────
   ⚠️ 한글이 오는 자리라 'Fraunces'를 단독으로 쓰지 말 것 — 그 글꼴엔 한글이 없어
   기기마다 다른 글꼴로 떨어진다(안드로이드 고딕 / 아이폰 명조). 겹쳐 쓴다. */
.vp-sec {
  margin-top: 10px;
  padding-top: 9px;
  border-top: 1px solid var(--border);
}
.vp-lbl {
  font-family: 'Fraunces', 'Gowun Batang', serif;
  font-size: 10px;
  letter-spacing: .07em;
  color: var(--ink-soft);
  opacity: .72;
  margin-bottom: 5px;
}
.vp-cur {
  font-family: 'Gowun Batang', serif;
  font-size: 17px;
  color: var(--navy-deep);
  line-height: 1.4;
}
.vp-cur b, .vp-cur .vp-say { color: var(--blue); font-weight: 700; }
.vp-cur em {
  font-style: normal;
  font-size: 12px;
  color: var(--ink-soft);
  margin-left: 7px;
}
.vp-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 3px 0;
  font-family: 'Gowun Batang', serif;
  font-size: 15px;
}
.vp-chip {
  flex: none;
  width: 22px;
  text-align: center;
  font-size: 11px;
  line-height: 1.55;
  border-radius: 4px;
  background: #e8eef4;
  color: var(--navy);
  border: 1px solid rgba(26, 58, 92, .18);
}
.vp-f { flex: 1; min-width: 0; color: var(--ink); }
.vp-t {
  flex: none;
  font-family: 'Fraunces', 'Gowun Batang', serif;
  font-size: 11.5px;
  color: var(--ink-soft);
  opacity: .75;
}
/* 아직 안 배운 한 줄 — 흐리게 두어 «앞이 있다»는 신호만 남긴다(사다리 유지) */
.vp-row.soon { opacity: .42; }
.vp-row.soon .vp-chip { background: #fff; border-style: dashed; }
.vocab-popup-grade {
  display: inline-block;
  font-size: 10px;
  font-family: 'Fraunces', serif;
  font-weight: 700;
  padding: 1px 7px;
  border-radius: 100px;
  margin-bottom: 8px;
  letter-spacing: 0.5px;
}
.vocab-popup-grade.A { background:#FFF3CD; color:#92400e; border:1px solid #f59e0b; }
.vocab-popup-grade.B { background:#D1FAE5; color:#065f46; border:1px solid #10b981; }
.vocab-popup-grade.C { background:#DBEAFE; color:#1e40af; border:1px solid #3b82f6; }
/* 설정 버튼 */
.vocab-grade-btn {
  padding: 7px 14px;
  border-radius: 100px;
  border: 1.5px solid var(--border);
  background: white;
  font-family: 'Gowun Batang', serif;
  font-size: 13px;
  color: var(--ink-soft);
  cursor: pointer;
  transition: all 0.15s;
}
.vocab-grade-btn.active {
  border-color: var(--navy);
  background: var(--navy);
  color: white;
  font-weight: 700;
}
.vocab-popup-close {
  position: absolute;
  top: 8px; right: 10px;
  background: none; border: none;
  font-size: 16px; color: var(--ink-soft);
  cursor: pointer; padding: 2px 6px;
  border-radius: 50%;
}
.vocab-popup-close:active { background: var(--paper-warm); }
/* ★ v245: 로마자 자리를 «듣기»가 대신한다. 소리는 로마자가 아니라 소리로 알려주는 게 맞다.
   ⚠️ 낱말은 기기 내장 음성(speechSynthesis)을 쓴다 — 즉시 나고 오프라인이며 서버 한도를 안 쓴다. */
.vp-speak {
  position: absolute;
  top: 7px; right: 38px;          /* ✕ 왼쪽 */
  width: 30px; height: 30px;
  display: flex; align-items: center; justify-content: center;
  background: none; border: none; padding: 0;
  color: var(--blue); cursor: pointer;
  border-radius: 50%;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
.vp-speak svg { width: 18px; height: 18px; }
.vp-speak:active { background: var(--paper-warm); }
.vp-speak.speaking { color: var(--orange); }
.vp-speak.speaking svg { animation: vpPulse .7s ease-in-out infinite; }
.vp-speak.vp-say-fail { color: var(--ink-soft); opacity: .45; }
@keyframes vpPulse { 0%,100% { transform: scale(1); } 50% { transform: scale(1.18); } }
/* 「지금 읽는 말」의 그 꼴도 눌러서 들을 수 있다 — 기본형과 소리가 꽤 다르다(돕다 ↔ 도와요) */
.vp-say {
  font-family: 'Gowun Batang', serif;
  font-size: inherit;
  color: var(--blue);
  background: none; border: none; padding: 0;
  cursor: pointer;
  border-bottom: 1px dotted rgba(46,110,158,.45);
  -webkit-tap-highlight-color: transparent;
}
.vp-say.speaking { color: var(--orange); border-bottom-color: transparent; }
/* 사전에 없는 말에도 «어미가 하는 일»만은 알려준다 — 기본형을 몰라도 이건 안다 */
.vp-hint {
  font-family: 'Fraunces', 'Gowun Batang', serif;
  font-size: 12.5px;
  color: var(--ink-soft);
  opacity: .8;
  margin-top: -4px;
}
/* 어절 안에서 조사만 도드라지게 — 「서울」과 「은」이 다른 것임을 눈으로 가른다 */
.vp-cur .vp-say i {
  font-style: normal;
  color: var(--orange);
  background: rgba(232, 106, 58, .10);
  border-radius: 3px;
  padding: 0 2px;
}
/* 조사 딱지는 레벨 딱지와 헷갈리지 않게 주황 계열로 */
.vp-chip.vp-p {
  width: auto;
  min-width: 22px;
  padding: 0 5px;
  background: rgba(232, 106, 58, .12);
  color: #a8471f;
  border-color: rgba(232, 106, 58, .35);
  font-family: 'Gowun Batang', serif;
}
.vp-say.vp-say-fail { color: var(--ink-soft); border-bottom-style: none; }
.vocab-popup-bg {
  position: fixed; inset: 0; z-index: 799;
}

/* 표지·단어장 페이지에서는 컨트롤 숨김 (FAB·진행바·EN 토글) */
.reader-wrap.hide-ctrl .reader-cover-img { max-height: 72vh; }

/* 재생 옵션 모달 */
.play-options-sheet {
  position: fixed; inset: 0; z-index: 600;
  display: flex; align-items: flex-end;
}
.play-options-sheet-bg {
  position: absolute; inset: 0;
  background: rgba(0,0,0,0.4);
}
.play-options-sheet-body {
  position: relative; width: 100%;
  background: white;
  border-radius: 20px 20px 0 0;
  padding: 20px 16px max(28px, env(safe-area-inset-bottom, 28px));
  max-width: 480px; margin: 0 auto;
}
.play-options-title {
  font-family: 'Fraunces', serif; font-weight: 700;
  font-size: 16px; color: var(--navy);
  margin-bottom: 18px;
  display: flex; justify-content: space-between; align-items: center;
}
.play-options-close {
  background: var(--paper-warm); border: none; border-radius: 50%;
  width: 28px; height: 28px; font-size: 14px; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.play-options-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0 4px;
}
/* 드럼롤 컬럼 */
.poc {
  display: flex; flex-direction: column; align-items: center;
}
.poc-label {
  font-family: 'Fraunces', serif; font-size: 10px;
  font-weight: 700; color: var(--ink-soft);
  letter-spacing: 0.5px; text-transform: uppercase;
  margin-bottom: 6px;
}
/* 드럼롤 뷰포트: 항목 3개 높이만 표시 */
.poc-drum {
  position: relative;
  width: 100%;
  height: 126px; /* 42px × 3 */
  overflow: hidden;
}
/* 가운데 선택 영역 하이라이트 */
.poc-drum::before, .poc-drum::after {
  content: '';
  position: absolute; left: 4px; right: 4px; z-index: 2;
  pointer-events: none;
}
.poc-drum::before {
  top: 0; height: 42px;
  background: linear-gradient(to bottom, white, rgba(255,255,255,0.3));
}
.poc-drum::after {
  bottom: 0; height: 42px;
  background: linear-gradient(to top, white, rgba(255,255,255,0.3));
}
/* 가운데 선택 라인 */
.poc-drum-line {
  position: absolute; left: 4px; right: 4px; z-index: 3;
  top: 42px; height: 42px;
  border-top: 1.5px solid var(--border);
  border-bottom: 1.5px solid var(--border);
  pointer-events: none;
}
/* 스크롤 영역 */
.poc-scroll {
  height: 100%;
  overflow-y: scroll;
  -webkit-overflow-scrolling: touch;
  scroll-snap-type: y mandatory;
  scroll-padding-top: 42px;   /* 첫 항목도 가운데 칸에 스냅되도록 기준선을 한 칸 내림 */
  scrollbar-width: none;
}
.poc-scroll::-webkit-scrollbar { display: none; }
/* 상하 패딩: 선택 항목이 가운데 오도록 */
.poc-pad { height: 42px; flex-shrink: 0; }
.poc-item {
  height: 42px;
  display: flex; align-items: center; justify-content: center;
  font-family: 'Gowun Batang', serif;
  font-size: 13px; color: var(--ink-soft);
  scroll-snap-align: start;
  cursor: pointer;
  transition: color 0.1s, font-size 0.1s, font-weight 0.1s;
  flex-shrink: 0;
}
.poc-item.sel {
  font-size: 18px; font-weight: 700;
  color: var(--navy);
}

.reader-prog { flex: 1; height: 3px; background: rgba(0,0,0,0.08); border-radius: 100px; overflow: hidden; }
.reader-prog-fill { height: 100%; background: var(--orange); transition: width 0.4s; }
.reader-audio-ctrl {
  background: none; border: none; color: var(--ink-soft);
  width: 32px; height: 32px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0; cursor: pointer; transition: color 0.15s;
}
.reader-audio-ctrl:active { color: var(--orange); }
.reader-audio-ctrl svg { width: 18px; height: 18px; }
.reader-counter { font-family: 'Fraunces', serif; font-size: 11px; color: var(--ink-soft); min-width: 30px; text-align: right; flex-shrink: 0; }
.tap-zone { position: absolute; top: 0; bottom: 0; width: 20%; z-index: 3; cursor: pointer; }
.tap-left { left: 0; }
.tap-right { right: 0; }

/* ─── SETTINGS (v167: iOS 설정 앱 스타일) ───
   이 화면에만 애플 시스템 글꼴/레이아웃을 쓴다. 책장·리더는 종이+명조 브랜드 그대로.
   아이폰에서는 -apple-system이 SF Pro로 잡히고, 맥/PC에서는 각 OS의 시스템 글꼴로 대체된다. */
.ios-settings {
  --ios-bg: #F2F2F7;          /* iOS 그룹 목록 배경 */
  --ios-card: #FFFFFF;
  --ios-sep: #C6C6C8;         /* 구분선 */
  --ios-label: #000000;
  --ios-secondary: #8E8E93;   /* 값·설명 회색 */
  --ios-tint: #007AFF;        /* 동작(파랑) */
  --ios-red: #FF3B30;         /* 파괴적 동작 */
  background: var(--ios-bg);
  font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', system-ui, 'Helvetica Neue', sans-serif;
  color: var(--ios-label);
  -webkit-font-smoothing: antialiased;
}
.ios-settings-inner { padding: 18px 0 32px; }

/* 그룹 제목 — 카드 위 회색 소문자 라벨 */
.ios-group-title {
  font-size: 13px; color: var(--ios-secondary); font-weight: 400;
  padding: 0 16px 6px; margin-top: 26px;
}
.ios-group-title:first-child { margin-top: 0; }

/* 흰 그룹 카드 */
.ios-group { background: var(--ios-card); border-radius: 10px; margin: 0 16px; overflow: hidden; }

/* 행 — 최소 44px (애플 권장 탭 영역) */
.ios-row {
  position: relative; display: flex; align-items: center; justify-content: space-between; gap: 12px;
  min-height: 44px; padding: 11px 16px; width: 100%;
  background: var(--ios-card); border: none; text-align: left; font: inherit; color: inherit;
}
/* 구분선: 마지막 행 제외, 왼쪽 16px 들여쓰기(라벨 시작선에 맞춤) — iOS 관행 */
.ios-row:not(:last-child)::after {
  content: ''; position: absolute; left: 16px; right: 0; bottom: 0;
  height: 1px; background: var(--ios-sep); transform: scaleY(0.5); transform-origin: bottom;
}
.ios-row-btn:active { background: #D1D1D6; }        /* 누르는 순간 회색 하이라이트 */
.ios-row-stack { flex-direction: column; align-items: stretch; gap: 10px; padding: 12px 16px; }

.ios-label { font-size: 17px; color: var(--ios-label); }
.ios-value { font-size: 17px; color: var(--ios-secondary); text-align: right;
             overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ios-sub   { font-size: 13px; color: var(--ios-secondary); line-height: 1.5; }
.ios-tint  { color: var(--ios-tint); }
.ios-destructive { color: var(--ios-red); }

/* 카드 아래 설명 푸터 — iOS는 설명을 카드 밖에 둔다 */
.ios-footer { font-size: 13px; color: var(--ios-secondary); line-height: 1.45; padding: 7px 16px 0; margin: 0 0 2px; }
.ios-footer strong { font-weight: 600; color: var(--ios-secondary); }

/* ─── 다이얼(휠 피커) 행 ───
   값 오른쪽에 꺾쇠(›)를 두고, 행 전체에 투명한 <select>를 겹친다.
   아이폰은 <select>를 탭하면 하단에서 다이얼을 올려주므로 직접 구현할 필요가 없다.
   ⚠️ select의 font-size는 16px 이상이어야 한다 — 그 미만이면 iOS Safari가 탭할 때 화면을 확대한다. */
.ios-picker { display: flex; align-items: center; gap: 2px; min-width: 0; }
.ios-picker-value { font-size: 17px; color: var(--ios-secondary); text-align: right;
                    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ios-picker-chevron { font-size: 19px; line-height: 1; color: #C7C7CC; flex-shrink: 0; }
.ios-picker-row select {
  position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; font-size: 16px;
  border: none; background: transparent; -webkit-appearance: none; appearance: none; cursor: pointer;
}
.ios-picker-row:active { background: #D1D1D6; }

/* ─── 세그먼티드 컨트롤 (어휘 등급) ─── */
.ios-segment {
  display: flex; gap: 2px; background: #EFEFF0; border-radius: 9px; padding: 2px;
}
.ios-segment .vocab-grade-btn, .ios-segment .seg-btn {
  flex: 1; border: none; background: transparent; border-radius: 7px; padding: 6px 0;
  font-family: inherit; font-size: 13px; font-weight: 500; color: var(--ios-label);
  transition: background 0.15s, box-shadow 0.15s;
}
.ios-segment .vocab-grade-btn.active, .ios-segment .seg-btn.active {
  background: #FFFFFF; box-shadow: 0 3px 8px rgba(0,0,0,0.12), 0 1px 1px rgba(0,0,0,0.04);
}

/* ─── 어휘 등급별 단어 수 타일 ─── */
.ios-tiles { display: flex; gap: 6px; }
.ios-tile { flex: 1; border-radius: 8px; padding: 8px 4px; text-align: center;
            display: flex; flex-direction: column; gap: 2px; }
.ios-tile-name { font-size: 11px; font-weight: 600; opacity: 0.85; }
.ios-tile-num  { font-size: 17px; font-weight: 600; font-variant-numeric: tabular-nums; }
.tile-a   { background: #FFF4E5; color: #B25000; }
.tile-b   { background: #E4F8EC; color: #12734A; }
.tile-c   { background: #E5F0FF; color: #17458F; }
.tile-all { background: #EFEFF0; color: #3C3C43; }

/* ─── MODAL ─── */
.modal-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.45); z-index: 150; display: none; align-items: flex-end; justify-content: center; }
.modal-overlay.show { display: flex; }
.modal { background: var(--paper); width: 100%; max-width: 480px; border-radius: 16px 16px 0 0; padding: 20px; padding-bottom: max(20px,env(safe-area-inset-bottom)); max-height: 70vh; overflow-y: auto; }
.modal-title { font-size: 18px; font-weight: 700; margin-bottom: 6px; }
.modal-text { font-size: 14px; color: var(--ink-soft); line-height: 1.5; margin-bottom: 18px; }
.modal-actions { display: flex; gap: 10px; }
.modal-btn { flex: 1; padding: 12px; border: none; border-radius: 8px; font-family: 'Gowun Batang', serif; font-size: 14px; font-weight: 600; }
.modal-btn.primary { background: var(--navy); color: white; }
.modal-btn.danger { background: var(--danger); color: white; }
.modal-btn.cancel { background: white; color: var(--ink-soft); border: 1px solid var(--border); }

/* ─── TOAST ─── */
.toast { position: fixed; bottom: 80px; left: 50%; transform: translateX(-50%); background: var(--navy-deep); color: white; padding: 10px 18px; border-radius: 100px; font-size: 13px; z-index: 200; opacity: 0; transition: opacity 0.3s; pointer-events: none; max-width: 90%; text-align: center; }
.toast.show { opacity: 1; }

/* ─── LOADER ─── */
.loader { position: fixed; inset: 0; background: var(--paper); display: flex; flex-direction: column; align-items: center; justify-content: center; z-index: 300; }
.loader-logo { font-family: 'Nanum Pen Script', cursive; font-size: 48px; color: var(--orange); margin-bottom: 8px; }
.loader-text { font-family: 'Fraunces', serif; font-size: 14px; color: var(--ink-soft); }
.spinner { width: 28px; height: 28px; border: 3px solid var(--border); border-top-color: var(--orange); border-radius: 50%; animation: spin 0.8s linear infinite; margin-top: 20px; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ─── USER CHIP ─── */
.user-chip { background: rgba(255,255,255,0.15); border-radius: 100px; padding: 3px 10px 3px 3px; display: flex; align-items: center; gap: 6px; }
.user-avatar { width: 24px; height: 24px; background: var(--orange); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 700; color: white; }

/* ─── INFO BOX ─── */
.info-box { background: #fff8e1; border-left: 3px solid var(--orange); padding: 12px 14px; font-size: 12px; color: var(--ink-soft); line-height: 1.6; border-radius: 0 6px 6px 0; }
.info-box strong { color: var(--orange); }

.hidden { display: none !important; }

/* ─── 책 메타 패널 (접을 수 있는 상단 정보) ─── */
.book-meta-panel {
  background: white;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.book-meta-header {
  padding: 12px 16px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  cursor: pointer;
  background: var(--paper-warm);
}
.book-meta-body {
  padding: 14px 14px 10px;
  transition: max-height 0.3s ease, opacity 0.3s;
  overflow: hidden;
}
.book-meta-body.collapsed {
  max-height: 0;
  padding: 0 14px;
  opacity: 0;
  pointer-events: none;
}

/* ─── 인라인 페이지 카드 ─── */
.page-editor-card {
  background: white;
  border-radius: 10px;
  box-shadow: 0 2px 10px rgba(0,0,0,0.07);
  margin-bottom: 14px;
  overflow: hidden;
  border: 2px solid transparent;
  transition: border-color 0.2s, box-shadow 0.2s, transform 0.15s;
}
.page-editor-card.active { border-color: var(--orange); }

/* 선택된 사진 추가 대상 카드 — 페이지/표지 모두 */
.page-editor-card.drop-target-selected {
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(46, 110, 158, 0.12),
              0 4px 16px rgba(46, 110, 158, 0.18);
}
.page-editor-card.drop-target-selected .page-editor-card-header {
  background: linear-gradient(135deg, #e8f1f8, #d4e6f3);
  border-bottom-color: var(--blue);
}
.page-editor-card.drop-target-selected .page-editor-card-num {
  color: var(--blue);
  font-weight: 700;
}
.page-editor-card.drop-target-selected .page-editor-card-num::before {
  content: '📌 ';
  margin-right: 2px;
}

/* ★v239: 썸네일·표지·본문의 «선택됨» 표시는 위 .page-editor-card.drop-target-selected
   한 벌로 끝난다. 예전엔 표지만 책 정보 패널 전체를 물들이는 별도 규칙이 있었는데,
   그러면 (가) 어느 칸에 붙여넣을지가 아니라 패널 전체가 켜져 자리를 알 수 없고
   (나) 썸네일은 아예 표시할 방법이 없었다. 패널 규칙은 지웠다.
   선택된 카드의 사진 칸도 옅게 물들여 «여기에 붙는다»를 분명히 한다. */
.page-editor-card.drop-target-selected .page-photo-strip {
  background: linear-gradient(135deg, #f0f6fb, #e3eef7);
  box-shadow: inset 0 0 0 2px var(--blue);
}

.page-editor-card-header {
  padding: 8px 12px;
  background: var(--paper-warm);
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-bottom: 1px solid var(--border);
}
.page-editor-card-num {
  font-family: 'Fraunces', serif;
  font-weight: 700;
  font-size: 11px;
  color: var(--ink-soft);
  letter-spacing: 1.5px;
  text-transform: uppercase;
}
/* ★v238: 썸네일·표지 카드의 한글 제목.
   ⚠️ Fraunces에는 한글이 없다 — 한글만 쓰는 이 자리에 그대로 두면 기기마다
   다른 글꼴로 떨어진다(안드로이드 고딕 / 아이폰 명조). 한글 글꼴을 겹쳐 쓴다.
   대문자 변환·넓은 자간은 라틴 글자용이라 한글에선 뺀다. */
.page-editor-card-num.ko {
  font-family: 'Fraunces', 'Gowun Batang', serif;
  font-size: 12px;
  letter-spacing: 0.3px;
  text-transform: none;
  color: var(--ink);
}
.page-editor-card-hint {
  font-family: 'Gowun Batang', serif;
  font-size: 11px;
  color: var(--ink-soft);
}
.page-editor-card-actions {
  display: flex;
  gap: 2px;
}
.page-editor-card-btn {
  background: transparent;
  border: none;
  padding: 4px 6px;
  color: var(--ink-soft);
  cursor: pointer;
  border-radius: 4px;
  display: flex;
  align-items: center;
}
.page-editor-card-btn:hover { background: var(--border); }
.page-editor-card-btn svg { width: 16px; height: 16px; }
.page-editor-card-btn.danger:hover { background: #ffe5e5; color: var(--danger); }

/* ─── 페이지 카드: 세로 1컬럼 레이아웃 ─── */
.page-editor-card-body {
  display: flex;
  flex-direction: column;
}

/* 사진 섹션: 가로 스크롤 가능한 사진 스트립 */
.page-photo-strip {
  position: relative;
  width: 100%;
  background: var(--paper-warm);
  border-bottom: 1px solid var(--border);
  transition: background 0.2s, box-shadow 0.2s;
}
.page-photo-strip.drag-over,
#coverPhotoStrip.drag-over {
  background: linear-gradient(135deg, #fff7ed, #fef3e0);
  box-shadow: inset 0 0 0 2px var(--orange),
              inset 0 0 24px rgba(232, 106, 58, 0.15);
}
.page-photo-strip.drag-over::after,
#coverPhotoStrip.drag-over::after {
  content: '여기에 놓아주세요';
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  background: var(--orange);
  color: white;
  padding: 6px 14px;
  border-radius: 100px;
  font-family: 'Fraunces', serif;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.3px;
  box-shadow: 0 4px 12px rgba(232, 106, 58, 0.4);
  pointer-events: none;
  z-index: 10;
  animation: ptr-bounce 0.6s ease-out;
}
@keyframes ptr-bounce {
  0% { transform: translate(-50%, -50%) scale(0.85); opacity: 0; }
  100% { transform: translate(-50%, -50%) scale(1); opacity: 1; }
}
#coverPhotoStrip {
  transition: background 0.2s, box-shadow 0.2s;
  position: relative;
}
/* 사진 없을 때 (★v240)
   상자와 버튼을 나눴다. 예전엔 상자 전체가 <label>이라 «어디를 눌러도» 파일 선택창이
   열려, 이 칸을 붙여넣기 대상으로 고를 방법이 아예 없었다.
   이제 상자를 누르면 카드가 선택되고(=Cmd+V 목적지), 파일창은 안쪽 알약만 연다. */
.page-photo-strip-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 14px 0;
  cursor: pointer;
}
.page-photo-strip-empty input { display: none; }
.page-photo-empty-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 16px;
  border-radius: 100px;
  background: white;
  border: 1px dashed var(--border);
  color: var(--ink-soft);
  font-size: 13px;
  /* ⚠️ 「사진 추가」는 한글이다. Fraunces에는 한글이 없어 혼자 두면
     기기마다 다른 글꼴로 떨어진다(안드로이드 고딕 / 아이폰 명조). 한글 글꼴을 겹친다. */
  font-family: 'Fraunces', 'Gowun Batang', serif;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.page-photo-empty-btn:hover {
  background: var(--paper);
  border-color: var(--orange);
  color: var(--orange);
}
.page-photo-empty-btn input { display: none; }
/* 이 카드가 붙여넣기 대상으로 골라졌을 때 — 이제 붙여넣어도 된다고 알려 준다 */
.page-editor-card.drop-target-selected .page-photo-strip-empty::after {
  content: '📋 이제 사진을 붙여넣을 수 있어요';
  font-family: 'Gowun Batang', serif;
  font-size: 11px;
  color: var(--blue);
}
/* 사진 있을 때: 가로 스크롤 썸네일 열 */
.page-photo-strip-row {
  display: flex;
  gap: 4px;
  padding: 8px 8px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  align-items: flex-start;
}
.page-photo-strip-row::-webkit-scrollbar { height: 0; }
/* 개별 사진 썸네일 (4:3 비율) */
.page-photo-item {
  position: relative;
  flex-shrink: 0;
  width: 120px;
  height: 90px;
  border-radius: 6px;
  overflow: hidden;
  background: var(--border);
  border: 2px solid transparent;
  transition: border-color 0.15s;
  cursor: pointer;
}
.page-photo-item.selected {
  border-color: var(--orange);
  box-shadow: 0 0 0 1px var(--orange);
}
.page-photo-item img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
/* 사진 위 버튼들 */
.page-photo-item-btns {
  position: absolute;
  top: 3px; right: 3px;
  display: flex;
  gap: 3px;
  z-index: 3;
}
.page-photo-item-btn {
  width: 22px; height: 22px;
  border-radius: 50%;
  border: none;
  background: rgba(0,0,0,0.6);
  color: white;
  font-size: 11px;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  line-height: 1;
}
.page-photo-item-btn.sel { background: var(--orange); }
/* 추가 버튼 (사진 있을 때 마지막에 표시) */
.page-photo-add-btn {
  flex-shrink: 0;
  width: 90px; height: 90px;
  border-radius: 6px;
  border: 2px dashed var(--border);
  background: white;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 4px;
  cursor: pointer;
  color: var(--ink-soft);
  font-size: 22px;
}
.page-photo-add-btn span {
  font-size: 10px;
  font-family: 'Fraunces', serif;
}
.page-photo-add-btn input { display: none; }

/* 오른쪽: 텍스트 편집 영역 */
.page-text-zone {
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.page-text-korean {
  font-family: 'Gowun Batang', serif;
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink);
  border: none;
  outline: none;
  width: 100%;
  resize: none;
  background: transparent;
  min-height: 52px;
  -webkit-user-select: text;
  user-select: text;
}
.page-text-korean::placeholder { color: var(--ink-soft); opacity: 0.6; }
.page-text-korean:focus {
  background: var(--paper-warm);
  border-radius: 4px;
  padding: 4px;
  margin: -4px;
}
.page-text-divider {
  height: 1px;
  background: var(--border);
  margin: 2px 0;
}
.page-text-english {
  font-family: 'Fraunces', serif;
  font-style: italic;
  font-size: 11px;
  color: var(--ink-soft);
  border: none;
  outline: none;
  width: 100%;
  resize: none;
  background: transparent;
  min-height: 28px;
  -webkit-user-select: text;
  user-select: text;
}
.page-text-english::placeholder { color: var(--ink-soft); opacity: 0.5; }
.page-text-english:focus { background: var(--paper-warm); border-radius: 4px; padding: 2px 4px; }
.page-vocab-tag.excluded {
  background: rgba(220, 50, 50, 0.15);
  color: var(--danger);
  text-decoration: line-through;
  opacity: 0.7;
  cursor: pointer;
}
.page-vocab-tag.included {
  background: var(--accent-soft);
  color: var(--accent);
  cursor: pointer;
}
.page-vocab-tag.included:hover {
  background: rgba(220, 50, 50, 0.1);
  text-decoration: line-through;
}
.page-vocab-tag.excluded:hover {
  background: var(--accent-soft);
  text-decoration: none;
  opacity: 1;
}
.page-vocab-excluded-section {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px dashed rgba(0,0,0,0.1);
  font-size: 10px;
  color: var(--ink-soft);
}
.page-vocab-row {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}
.page-vocab-tag {
  background: var(--highlight);
  border-radius: 100px;
  padding: 1px 8px;
  font-size: 11px;
  font-weight: 700;
  color: var(--navy-deep);
}
.page-vocab-input {
  border: none;
  border-bottom: 1px dashed var(--border);
  outline: none;
  font-family: 'Gowun Batang', serif;
  font-size: 11px;
  color: var(--ink-soft);
  background: transparent;
  width: 100px;
  -webkit-user-select: text;
  user-select: text;
}

/* 메모 (접힌 상태로 있다가 클릭 시 펼침) */
/* ★v233: 토글과 복사 버튼을 한 줄에. 위 테두리는 이제 줄(row)이 그린다 —
   토글에 그대로 두면 복사 버튼 쪽만 선이 끊긴다. */
.page-notes-row {
  display: flex;
  align-items: stretch;
  border-top: 1px solid var(--border);
}
.page-notes-row .page-notes-toggle { border-top: none; flex: 1; min-width: 0; }
/* ★v233 그림 프롬프트 복사 — 편집자가 쪽마다 누르는 버튼이라 손가락이 가는 자리에 크게.
   글자가 「복사 → ✅ 복사됨」으로 바뀌며 폭이 흔들리지 않게 min-width로 잡아 둔다. */
.page-notes-copy {
  flex: 0 0 auto;
  min-width: 74px;
  margin: 4px 8px 4px 0;
  padding: 5px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--paper-warm);
  font-family: 'Fraunces', serif;
  font-size: 11px;
  color: var(--ink-soft);
  cursor: pointer;
  white-space: nowrap;
  transition: background .15s, color .15s, border-color .15s;
}
.page-notes-copy:hover { background: var(--paper); }
.page-notes-copy:active { transform: translateY(1px); }
.page-notes-copy.copied { background: #E7F3EC; border-color: #8FC4A6; color: #2E6B4C; }
.page-notes-copy.wide { width: 100%; margin: 0; padding: 8px; font-size: 12px; }
.page-notes-copy.hidden { display: none; }

.page-notes-toggle {
  padding: 6px 12px;
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  background: transparent;
  border-left: none;
  border-right: none;
  border-bottom: none;
  width: 100%;
  text-align: left;
  font-family: 'Fraunces', serif;
  font-size: 11px;
  color: var(--ink-soft);
}
.page-notes-area {
  padding: 0 12px;
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.2s, padding 0.2s;
}
.page-notes-area.open {
  /* ★v257: 아래에 링크 칩 줄이 붙으므로 여유를 준다 */
  max-height: 320px;
  padding: 8px 12px;
}

/* ★v257: 메모에 적힌 «내려받을 주소»를 눌러서 열 수 있게 — textarea 안에서는 링크가 안 걸린다.
   출력지침 §6-9의 [사진] 표시에 딸려오는 [파일] 줄이 여기로 나온다. */
.page-notes-links {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 6px;
}
.page-notes-links:empty { display: none; }
.pn-link {
  display: inline-block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: 4px 9px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--paper);
  color: var(--ink-soft);
  font-size: 11px;
  text-decoration: none;
}
.pn-link:hover { background: var(--paper-warm); color: var(--ink); }
.pn-link:active { transform: translateY(1px); }
.page-notes-textarea {
  width: 100%;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px;
  font-family: 'Gowun Batang', serif;
  font-size: 12px;
  color: var(--ink-soft);
  background: var(--paper-warm);
  resize: none;
  min-height: 56px;
  -webkit-user-select: text;
  user-select: text;
}

/* 로마자 행 */
.page-romaji-input {
  border: none;
  outline: none;
  font-family: 'Fraunces', serif;
  font-style: italic;
  font-size: 11px;
  color: var(--blue);
  background: transparent;
  width: 100%;
  -webkit-user-select: text;
  user-select: text;
}
.page-romaji-input::placeholder { color: var(--blue); opacity: 0.4; }

/* ═══════════════════════════════════════════════════════════════
   책장(홈) 리디자인 — 틸 다크 배경 + 카드형 레이아웃 (2026-07)
   ※ 홈 화면 비주얼만 재테마. 로직/마크업 변경 없음.
   ═══════════════════════════════════════════════════════════════ */
/* ═══ Bright Playground (다크) — 딥틸 본문 + 틸 헤더 + 다크 카드 + 주황 강조 ═══ */
/* Jua 폰트는 <head>의 구글폰트 <link>에서 로드 */

/* 헤더: 틸 바 (본문보다 살짝 밝게) */
.topbar[data-topbar="home"] { background: #0b5e61; }
.topbar[data-topbar="home"] .topbar-title,
.topbar[data-topbar="home"] h1 { font-family: 'Jua', sans-serif; }

/* 본문 배경: 딥 틸 */
#screen-home { background: #0e2426; padding-bottom: 0; }
/* ★ 세로폰: 1열 · B 크기(좌우 여백 36 → 카드 ~318) · 넓은 세로에서도 카드 안 커지게 */
.book-grid { background: #0e2426; padding: 16px 36px 90px; gap: 20px; max-width: 400px; margin: 0 auto; }

/* ★v260 검색 줄 — 필터 바와 «같은 자리·같은 높이». 둘 중 하나만 보인다.
   높이를 맞춰야 열고 닫을 때 책 격자가 위아래로 튀지 않는다. */
.search-bar {
  position: sticky; top: 0; z-index: 51;
  display: flex; align-items: center; gap: 10px;
  background: #0e2426; border-bottom: 1px solid rgba(255,255,255,0.08);
  padding: 14px 16px;
}
.search-bar.hidden { display: none; }
.search-icon { width: 18px; height: 18px; color: #8fd0d0; flex-shrink: 0; }
.search-input {
  flex: 1; min-width: 0;
  background: #16393b; border: 0; border-radius: 999px;
  color: #eaf7f7; font-family: 'Jua', sans-serif; font-size: 15px;
  padding: 9px 16px; -webkit-appearance: none; appearance: none;
}
.search-input::placeholder { color: #6ba7a7; }
.search-input:focus { outline: 2px solid #ff8a3d; outline-offset: 1px; }
/* iOS 사파리가 type=search 에 붙이는 기본 ✕ — 우리 버튼과 겹치므로 뺀다 */
.search-input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
.search-close {
  background: transparent; border: 0; color: #8fd0d0;
  font-size: 18px; line-height: 1; padding: 8px; flex-shrink: 0;
}

/* 필터 바 — 알약 탭 + 주황 활성 (통통 튀는 키즈) */
.filter-bar {
  position: sticky; top: 0; z-index: 50;
  background: #0e2426; border-bottom: 1px solid rgba(255,255,255,0.08);
  padding: 14px 16px; gap: 9px;
}
.filter-tab {
  background: #16393b; border: 0; border-radius: 999px;
  color: #8fd0d0; font-family: 'Jua', sans-serif; font-weight: 400;
  font-size: 15px; padding: 9px 16px;
}
.filter-tab.active { background: #ff8a3d; color: #fff; box-shadow: 0 4px 0 #e26a1c; }
/* 관리자(검토중 등)·저자 칩: 알약 유지 + 색으로 구별 */
.filter-tab.admin-filter { background: #16393b; border: 1.5px dashed var(--orange); color: var(--orange); border-radius: 999px; font-size: 13.5px; padding: 8px 14px; }
.filter-tab.admin-filter.active { background: var(--orange); color: #fff; border-style: solid; box-shadow: 0 4px 0 #e26a1c; }
.filter-tab.author-filter { background: #16393b; border: 1.5px solid rgba(179,157,219,0.6); color: #cbb8ef; border-radius: 999px; font-size: 13.5px; padding: 8px 14px; }
.filter-tab.author-filter.active { background: #b39ddb; color: #221a3a; border-style: solid; box-shadow: 0 4px 0 #8f77c4; }
.filter-bar .filter-divider { background: rgba(255,255,255,0.18); }

/* 책 카드: 다크 라운드 카드 */
.book-card {
  background: #16393b; border-radius: 22px; overflow: hidden;
  padding: 12px; box-shadow: 0 10px 24px rgba(0,0,0,0.32);
}
.book-cover { border-radius: 16px; overflow: hidden; box-shadow: none; }
.book-info { padding: 12px 6px 4px; }
.book-title { color: #eafaf9; font-family: 'Jua', sans-serif; font-weight: 400; }
.book-meta { color: rgba(207,236,235,0.7); }
/* ★v234 상태 색 — 카드 배경이 #16393b(어두운 청록)라 밝은 배경용 색은 안 읽힌다.
   실제로 재보니 「대기」가 1.3:1, 「검수 대기」가 3.0:1이었다(2026-08-03 수정).
   아래 값은 모두 #16393b 대비 5.9:1 이상. */
.book-card .status-dot          { background: #9FB8B6; }
.book-card .status-dot.work     { background: #FF9F5A; }
.book-card .status-dot.check    { background: #6FC3E8; }
.book-card .status-dot.done     { background: #67D69A; }
.book-card .work-state.wait  .work-state-label { color: #9FB8B6; }
.book-card .work-state.work  .work-state-label { color: #FF9F5A; }
.book-card .work-state.check .work-state-label { color: #6FC3E8; }
.book-card .work-state.done  .work-state-label { color: #67D69A; }
.book-card .work-who {
  color: #CFECEB;
  background: rgba(255,255,255,0.10);
  border: 1px solid rgba(255,255,255,0.18);
}
/* 자음 배지: 주황 라운드 */
/* ⚠️ Jua는 굵기가 400 하나뿐이다. 위 .level-badge의 font-weight:700을 그대로 두면
   가짜 볼드가 되어 「ㄱ」의 획이 뭉갠다 — 14px로 키우면서 더 잘 보이게 됐다. */
.book-meta .level-badge {
  background: #ff8a3d; color: #fff; font-family: 'Jua', sans-serif;
  font-weight: 400;
  border-radius: 9px; border: 0;
}

/* 센티넬/빈 상태 — 다크 배경에 맞춤 (책 수 카운터는 v174에서 삭제) */
.book-grid-sentinel-spinner { background: rgba(255,255,255,0.08); color: #8fd0d0; }
.empty-state { color: #7fb8b8; }
.empty-title { color: #eafaf9; font-family: 'Jua', sans-serif; }

/* ═══════════════════════════════════════════════════════════════
   반응형 — 넓은 화면(가로폰·태블릿·데스크탑)에서 책장을 Raz-Kids처럼 확장.
   ★ #app[data-screen="home"]에만 적용 → 리더·편집기는 480px 컬럼 그대로(안전).
   카드는 세로폰보다 작아지지 않음(넓을수록 큼). 세로폰(≤799px)은 지금과 100% 동일.
   ═══════════════════════════════════════════════════════════════ */
@media (min-width: 800px) {
  #app[data-screen="home"] { max-width: 1280px; box-shadow: none; }
  /* 가로폰 + 태블릿: 2열 */
  #app[data-screen="home"] .book-grid {
    grid-template-columns: 1fr 1fr;
    max-width: 900px;
    gap: 28px;
    padding: 22px 40px 90px;
  }
  /* 칩(ㄱ~ㅎ)을 가운데로 시원하게 펼침 */
  #app[data-screen="home"] .filter-bar { justify-content: center; }
}
@media (min-width: 1240px) {
  /* 데스크탑: 최대 3열 */
  #app[data-screen="home"] .book-grid {
    grid-template-columns: 1fr 1fr 1fr;
    max-width: 1240px;
    gap: 32px;
  }
}

/* ═══════════════════════════════════════════════════════════════
   반응형 — "가로 방향 + 넓은 화면"에서만 리더 본문을 "그림 왼쪽 + 글 오른쪽"으로.
   ★ orientation:landscape 조건 → 세로로 세운 기기(세로폰·세로 아이패드)는 항상 그대로(위아래).
   ★ 본문(.body-page)만 좌우. 표지·속표지·어휘·문법은 가운데 유지.
   한 화면 = 한 페이지(세로로 안 늘림) → 스크롤 없음.
   ★ v194: min-height:560px 추가 — 아이패드·데스크탑 전용으로 못박는다.
     눕힌 폰은 폭이 850~930px라 폭만으론 아이패드와 구분되지 않지만, 높이는
     확연히 다르다(폰 375~430 / 아이패드 744~1024). 폰은 아래 별도 블록이 맡는다.
   ═══════════════════════════════════════════════════════════════ */
@media (min-width: 800px) and (orientation: landscape) and (min-height: 560px) {
  #app[data-screen="reader"] { max-width: 1120px; box-shadow: none; }

  /* 본문 페이지: 세로 스택 → 좌우 배치 (is-short/is-long 무관하게 강제) */
  .reader-page.body-page {
    flex-direction: row !important;
    align-items: stretch !important;
    justify-content: flex-start !important;
    padding-bottom: 0 !important;
  }
  /* 그림 — 왼쪽 약 56%. 하단 컨트롤 바+페이드(약 140px)를 피해 그림 전체가 보이게 */
  .reader-page.body-page .reader-photo-wrap,
  .reader-page.body-page.is-short .reader-photo-wrap {
    flex: 0 0 56% !important;
    max-height: none !important;
    height: 100%;
    padding: 24px 18px 148px 30px;   /* 하단 148px = 컨트롤 바+흰색 페이드 회피 */
    align-items: center;
  }
  .reader-page.body-page .reader-photo-img {
    max-height: min(100%, 700px);    /* 여백 안에 완전히 들어옴 + 700px 상한(아이패드 선명) */
    max-width: 100%;
    width: auto;
    height: auto;
  }
  /* 글 — 오른쪽. 그림과 같은 상하 여백(24/148) → 세로 가운데가 "그림 중앙선"에 맞음.
     글이 길면 위에서부터(safe center) + 이 칸만 스크롤 */
  .reader-page.body-page .reader-text-area,
  .reader-page.body-page.is-short .reader-text-area {
    flex: 1 1 0 !important;
    display: flex;
    flex-direction: column;
    justify-content: safe center;
    overflow-y: auto !important;
    padding: 24px 44px 148px 34px;
    border-left: 1px solid #f0efe9;
  }
  /* 넓은 공간 활용: 글자 크게 + 줄간격·문단간격 넓게 */
  .reader-page.body-page .reader-text { font-size: 27px; line-height: 1.95; }
  .reader-page.body-page .reader-text.size-a { font-size: 29px; }
  .reader-page.body-page .reader-text.size-c { font-size: 24px; line-height: 1.9; }
  .reader-page.body-page .reader-para:not(:last-child) { margin-bottom: 1.2em; }
  .reader-page.body-page .reader-text-en { font-size: 19px; line-height: 1.85; }
  /* 여러 줄: 왼쪽 / 한 줄 문장: 가운데 (왼쪽에 붕 뜨는 것 방지) */
  .reader-page.body-page .reader-text,
  .reader-page.body-page .reader-text-en { text-align: left; }
  .reader-page.body-page .reader-text.is-oneline,
  .reader-page.body-page .reader-text-en.is-oneline { text-align: center; }
  /* 페이지 정보(책 제목·쪽번호)는 글 아래 자연스럽게 */
  .reader-page.body-page .reader-page-meta { margin-top: 18px; }
}

/* ═══════════════════════════════════════════════════════════════
   v194 — 눕힌 스마트폰 전용 (가로 + 화면 높이 560px 미만).
   아이패드·데스크탑은 위 블록이 맡는다. 여기서는 건드리지 않는다.

   왜 따로 필요한가: 위 블록의 숫자(아래 148px 비우기 / 글자 27px / 줄간격 1.95)는
   높이 1000px인 아이패드 기준이다. 높이가 393px뿐인 폰에 그대로 적용되면
   여백만으로 화면의 38%가 사라져 그림이 눌리고 글이 3~4줄에서 잘렸다.
   ═══════════════════════════════════════════════════════════════ */
@media (orientation: landscape) and (max-height: 559px) {
  /* 480px 열 제한 해제 — 눕힌 화면을 가로로 다 쓴다 */
  #app[data-screen="reader"] { max-width: 100%; box-shadow: none; }

  /* ── 노치(카메라 구멍)·둥근 모서리 회피 ──
     세로로 들면 노치가 위에 있어 문제가 없지만, 눕히면 화면 옆구리로 온다.
     좌우 끝에 붙은 글자가 그대로 가려지므로 안전영역만큼 밀어 준다.
     (보라색 상단 바는 화면 끝까지 채우고, 그 안의 글자만 밀린다) */
  .topbar {
    padding-left: max(16px, env(safe-area-inset-left));
    padding-right: max(16px, env(safe-area-inset-right));
  }
  .reader-mini-ctrl {
    left: max(14px, env(safe-area-inset-left));
    right: max(14px, env(safe-area-inset-right));
  }
  /* ★ 재생 컨트롤러를 그림이 있는 왼쪽으로 옮긴다.
     세로에서는 화면 아래 가운데에 떠도 글을 살짝 가릴 뿐이지만, 가로에서는
     글이 오른쪽 절반에 몰려 있어 가운데 컨트롤러가 읽는 줄을 정면으로 덮는다.
     왼쪽 그림 칸 위에 놓으면 글은 한 글자도 가리지 않는다. */
  /* ★ 폭(width:44%)이 아니라 오른쪽 끝(right)으로 가둔다.
     width로 잡으면 왼쪽 노치 여백(59px)만큼 통째로 밀려서 오른쪽 끝이
     그림 칸을 넘어가고, 닫기(✕) 버튼이 글자 위에 얹힌다.
     +10px은 ✕가 패널 밖으로 6px 튀어나오는 몫. */
  .play-sheet {
    left: max(16px, env(safe-area-inset-left));
    right: calc(56% + 10px);
    width: auto;
  }

  /* ── ① words to know: 2열 ──
     한국어를 맨 왼쪽, 로마자를 맨 오른쪽에 붙이는 1열 구조는 폭 850px에서
     가운데가 텅 빈다. 2열로 나누면 8단어가 한 화면에 들어와 스크롤이 사라진다.
     ★ 열 나누기는 품사 그룹별이 아니라 목록 전체(.vocab-preview-box)에 건다.
       그룹별로 걸면 NOUNS 다음에 ADVERBS가 아래로 밀려 화면 밖으로 나간다. */
  /* 높이가 393px뿐이라 세로 여백을 한 줄씩 아껴야 4단어가 다 보인다.
     아래 64px은 Words 버튼·진행바가 덮는 자리 */
  /* ★ v202: 세로에서 키운 글자(한글 20 / 영어 15)를 그대로 쓰면 높이 393px에
     4단어가 안 들어온다. 눕혔을 때만 한 단계 낮춰 원래의 "4단어 한 화면"을 지킨다. */
  .reader-page.vocab-preview-page {
    padding: 8px max(24px, env(safe-area-inset-right)) 64px max(24px, env(safe-area-inset-left));
    --aux-ko:  17px;
    --aux-en:  13px;
    --aux-rom: 13px;
  }
  .vocab-preview-header { margin-bottom: 8px; }
  .vocab-preview-title-en { font-size: 20px; margin-bottom: 4px; }
  .vocab-preview-box {
    columns: 2;
    column-gap: 44px;
  }
  .vocab-pos-group { margin-bottom: 12px; }
  .vocab-pos-label {
    break-after: avoid;           /* 품사 이름만 열 바닥에 홀로 남지 않게 */
    -webkit-column-break-after: avoid;
    margin-bottom: 4px;
    padding-bottom: 4px;
  }
  .vocab-b-row {
    break-inside: avoid;          /* 한 단어가 두 열에 쪼개지지 않게 */
    -webkit-column-break-inside: avoid;
    padding: 5px 4px;
  }
  .vocab-b-main { margin-bottom: 1px; }
  .vocab-b-eng { line-height: 1.35; }

  /* ── ② 본문: 그림 왼쪽 + 글 오른쪽 (폰 크기에 맞춘 값) ──
     배치는 아이패드와 같지만 숫자가 다르다.
     아래 여백 148→96px, 글자 27→19px, 줄간격 1.95→1.65.
     → 그림 높이 171→231px, 한눈에 보이는 글 3.2줄→7.2줄.
     글자를 "줄이는" 이유: 눕히면 한 줄이 길어지는데 줄 간격까지 넓으면
     눈이 다음 줄 첫 글자를 못 찾고 헤맨다. */
  .reader-page.body-page {
    flex-direction: row !important;
    align-items: stretch !important;
    justify-content: flex-start !important;
    padding-bottom: 0 !important;
  }
  /* 44% — 그림은 높이로 제한되므로(가로 그림 기준 299×224) 이 칸을 52%→44%로
     줄여도 그림은 조금도 작아지지 않는다. 그림 오른쪽 빈 공간만 글칸으로 넘어가
     한 줄이 길어지고 줄 수가 8→7로 준다. */
  .reader-page.body-page .reader-photo-wrap,
  .reader-page.body-page.is-short .reader-photo-wrap {
    flex: 0 0 44% !important;
    min-height: 0;
    max-height: none !important;
    height: 100%;
    padding: 16px 14px 96px max(20px, env(safe-area-inset-left));
    align-items: center;
  }
  .reader-page.body-page .reader-photo-img {
    max-height: 100%;
    max-width: 100%;
    width: auto;
    height: auto;
  }
  /* 아래 76px = Words 버튼·진행바가 덮는 66px + 여유 10px.
     재생 컨트롤러는 위에서 왼쪽으로 옮겼으므로 이 칸을 침범하지 않는다. */
  .reader-page.body-page .reader-text-area,
  .reader-page.body-page.is-short .reader-text-area {
    flex: 1 1 0 !important;
    display: flex;
    flex-direction: column;
    justify-content: safe center;
    overflow-y: auto !important;    /* 글 많은 책은 이 칸만 스크롤 */
    padding: 12px max(30px, env(safe-area-inset-right)) 76px 26px;
    border-left: 1px solid #f0efe9;
  }
  /* ★ 세로와 같은 글자 크기(A 24 / B 22 / C 20). 눕혔다고 글이 작아지지 않는다.
     줄 간격만 세로(1.6~1.65)보다 좁힌다 — 가로는 한 줄이 길어서 간격까지 넓으면
     눈이 다음 줄을 찾지 못한다. */
  .reader-page.body-page .reader-text { font-size: 22px; line-height: 1.5; }
  .reader-page.body-page .reader-text.size-a { font-size: 24px; }
  .reader-page.body-page .reader-text.size-c { font-size: 20px; line-height: 1.5; }
  .reader-page.body-page .reader-para:not(:last-child) { margin-bottom: 0.9em; }
  .reader-page.body-page .reader-text-en { font-size: 13px; line-height: 1.55; }
  .reader-page.body-page .reader-text,
  .reader-page.body-page .reader-text-en { text-align: left; }
  .reader-page.body-page .reader-text.is-oneline,
  .reader-page.body-page .reader-text-en.is-oneline { text-align: center; }
  .reader-page.body-page .reader-page-meta { margin-top: 12px; }
}

/* ═══════════════════════════════════════════════════════════════
   📷 사진 출처 페이지 (v264~) — 할일 §5
   부속 다섯째 쪽. 속표지·words to know·문법 두 쪽과 «한 벌»이다 —
   제목은 Fraunces 이탤릭 700 + opsz 96, 한글은 Jua, 제목 남색 #25394B.
   ⚠️ 한 쪽만 고치지 말 것. 넷이 같은 옷을 입고 있다.
   ⚠️ Fraunces에는 한글이 없다. 한글이 오는 자리는 반드시 Jua를 명시한다.
   ═══════════════════════════════════════════════════════════════ */
.reader-page.photo-credits-page {
  background: #fff;
  padding: 24px 18px 28px;
  justify-content: flex-start;
  align-items: stretch;
  overflow-y: auto;
}
.pc-inner { max-width: 520px; margin: 0 auto; width: 100%; }
.pc-title {
  font-family: 'Fraunces', serif;
  font-style: italic;
  font-weight: 700;
  font-variation-settings: 'opsz' 96, 'wght' 700;
  font-size: var(--aux-title);
  color: #25394B;
  letter-spacing: 0.5px;
  text-align: center;
  margin: 0 0 6px;
}
.pc-sub {
  font-family: 'Jua', sans-serif;
  font-size: var(--aux-sub);
  color: var(--aux-beige);
  letter-spacing: 0.5px;
  text-align: center;
  margin-bottom: 10px;
}
.pc-list { list-style: none; margin: 0; padding: 0; }
/* ★ v267: 한 사진이 «한 줄». 쪽번호 | 제목+장소 | 촬영자 —
   전에는 두 줄이라 세로로 길어 스크롤이 생기고 오른쪽이 비었다. */
.pc-row {
  display: grid;
  /* ⚠️ 30px이었는데 「표지·책장·5」 같은 합친 딱지가 옆 칸을 뚫고 나왔다(v268 수정).
     nowrap까지 걸려 있어 줄바꿈도 못 했다. 넓히고 줄바꿈을 허용한다. */
  grid-template-columns: 56px 1fr auto;
  align-items: baseline;
  gap: 8px;
  padding: 7px 2px;
  border-bottom: 1px solid rgba(37,57,75,0.08);
}
.pc-row:last-child { border-bottom: none; }
.pc-no {
  font-family: 'Jua', sans-serif;
  font-size: 11.5px;
  color: var(--aux-beige);
  text-align: right;
  line-height: 1.3;
  word-break: keep-all;   /* 「목록·표지」가 한 글자씩 갈라지지 않게 */
}
.pc-mid { min-width: 0; }
.pc-what {
  font-family: 'Jua', sans-serif;
  font-size: 14px;
  color: #25394B;
}
.pc-where {
  font-family: 'Jua', sans-serif;
  font-size: 11.5px;
  color: var(--aux-beige);
  margin-left: 6px;
  white-space: nowrap;
}
.pc-who {
  font-family: 'Jua', sans-serif;
  font-size: 11.5px;
  color: var(--ink-soft);
  white-space: nowrap;
}
.pc-how {
  font-family: 'Jua', sans-serif;
  font-size: 11.5px;
  color: var(--aux-beige);
  text-align: center;
  margin-bottom: 12px;
}
.pc-foot {
  margin-top: 16px;
  text-align: center;
  font-family: 'Jua', sans-serif;
  font-size: 12px;
  color: var(--aux-beige);
  line-height: 1.7;
}
.pc-foot-en { font-family: 'Fraunces', serif; font-style: italic; }

/* ═══ 🔊 소리 페이지 (v270) — ㄱ·ㄴ(발음·낱말 레벨)의 «문법 카드» 자리 ═══
   문법 페이지와 한 벌이다(.grammar-page 의 --g-* 색·Jua 를 그대로 쓴다).
   ⚠️ Jua 는 굵기가 400 하나뿐 — 여기서 font-weight 를 쓰면 가짜 볼드로 획이 뭉갠다. */
.reader-page.sound-page .snd-band { margin-top: 18px; }
.reader-page.sound-page .snd-head {
  display: grid; grid-template-columns: 1fr 32px 1fr; align-items: center;
  font-family: 'Fraunces', serif; font-style: italic; font-size: 13px;
  color: var(--g-muted); letter-spacing: .04em; padding: 0 4px 6px;
}
.reader-page.sound-page .snd-head span:last-child { text-align: right; }
.reader-page.sound-page .snd-row {
  display: grid; grid-template-columns: 1fr 32px 1fr; align-items: center;
  gap: 2px 0; padding: 11px 4px; border-top: 1px solid var(--g-line);
}
.reader-page.sound-page .snd-write,
.reader-page.sound-page .snd-say {
  font-family: 'Jua', sans-serif; font-size: 21px; line-height: 1.35;
  color: var(--g-ink);
}
.reader-page.sound-page .snd-say { text-align: right; color: var(--g-red-deep); }
.reader-page.sound-page .snd-arrow { text-align: center; color: var(--g-muted); font-size: 15px; }
/* ⭐ 뜻은 «적는 쪽» 밑, 로마자는 «소리 나는 쪽» 밑 — 가운데로 몰면 어느 낱말 것인지 모호하다 */
.reader-page.sound-page .snd-cell { min-width: 0; }
.reader-page.sound-page .snd-right { text-align: right; }
.reader-page.sound-page .snd-sub {
  margin-top: 3px;
  font-family: 'Fraunces', serif; font-size: 12px; color: var(--g-muted);
}

/* 「왜 그렇게 되나」 — 짝 위에 놓는다. 규칙을 먼저 읽고 보기로 확인하는 차례. */
.reader-page.sound-page .snd-rule { margin-top: 14px; text-align: center; }
.reader-page.sound-page .snd-rule-en {
  /* ⚠️⚠️ Fraunces 에는 한글이 없다 — 「ㅇ은 …」처럼 한글이 섞이면 기기마다 다른 글꼴로
     떨어져 «기호 ○»처럼 보인다(2026-08-30 실제로 그랬다). 반드시 한글 글꼴을 겹쳐 쓸 것. */
  font-family: 'Fraunces', 'Jua', serif; font-size: 14px; line-height: 1.5; color: var(--g-ink);
}
.reader-page.sound-page .snd-rule-ko {
  margin-top: 4px; font-family: 'Jua', sans-serif; font-size: 14px;
  line-height: 1.55; color: var(--g-muted);
}
/* 한눈에 보는 표 — 여러 글자가 한 소리로 모이는 것 */
.reader-page.sound-page .snd-map {
  margin: 14px auto 0; padding: 10px 14px; max-width: 320px;
  background: var(--g-cream); border: 1px solid var(--g-box-bd); border-radius: 10px;
}
.reader-page.sound-page .snd-map-row {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  padding: 3px 0; font-family: 'Jua', sans-serif; font-size: 16px; color: var(--g-word);
}
.reader-page.sound-page .snd-map-from { letter-spacing: .12em; }
.reader-page.sound-page .snd-map-arrow { color: var(--g-gray); font-size: 13px; }
.reader-page.sound-page .snd-map-to { color: var(--g-red-deep); letter-spacing: .12em; }

/* 🔤 연음 — 글자 상자가 «옮겨 가는 것»을 보인다 (문법 페이지 head/body/받침 상자와 한 말투) */
.reader-page.sound-page .snd-move { margin: 16px auto 0; text-align: center; }
.reader-page.sound-page .snd-move-line {
  display: flex; align-items: flex-start; justify-content: center; gap: 10px;
}
.reader-page.sound-page .snd-move-plus { align-self: center; color: var(--g-gray); font-size: 15px; }
.reader-page.sound-page .snd-move-down { color: var(--g-gray); font-size: 16px; margin: 6px 0; }
.reader-page.sound-page .snd-syl { display: inline-block; }
.reader-page.sound-page .snd-jm-grid {
  display: grid; grid-template-columns: 34px 34px; gap: 3px; justify-content: center;
}
.reader-page.sound-page .snd-jm-box {
  font-family: 'Jua', sans-serif; font-size: 17px; color: var(--g-word);
  background: #fff; border: 1px solid var(--g-box-bd); border-radius: 7px;
  padding: 4px 0; min-height: 28px;
}
.reader-page.sound-page .snd-jm-box.wide { grid-column: 1 / -1; }
.reader-page.sound-page .snd-jm-box.empty { border-style: dashed; background: transparent; }
/* 옮겨 가는 글자 — 위아래 두 줄에서 같은 금색이라 눈이 따라간다 */
.reader-page.sound-page .snd-jm-box.moved {
  background: var(--g-tail); border-color: var(--g-tail-bd); color: var(--g-ink);
}
/* 소리 없는 ㅇ — 자리는 있는데 비어 있다는 뜻으로 흐리게 */
.reader-page.sound-page .snd-jm-box.silent { color: var(--g-gray); border-style: dashed; }
.reader-page.sound-page .snd-syl-ko {
  margin-top: 4px; font-family: 'Jua', sans-serif; font-size: 19px; color: var(--g-ink);
}

/* 설명글 안의 홀로 선 낱자 — 따옴표로 감싸 «기호가 아니라 글자»임을 보인다.
   ⚠️ 한글 글꼴을 반드시 박을 것(Fraunces 에는 한글이 없다). */
.reader-page.sound-page .snd-jamo {
  font-family: 'Jua', sans-serif; color: var(--g-red-deep); padding: 0 1px;
}
.reader-page.sound-page .snd-jamo::before { content: '\201C'; color: var(--g-gray); }
.reader-page.sound-page .snd-jamo::after  { content: '\201D'; color: var(--g-gray); }

/* 🧱 「받침이 뭔가」 — 낱말을 쓰기 전에 자리를 보인다 */
.reader-page.sound-page .snd-parts { margin: 14px 0 4px; text-align: center; }
.reader-page.sound-page .snd-parts-labels {
  display: grid; grid-template-columns: 34px 34px; gap: 3px; justify-content: center;
  margin-top: 3px; font-family: 'Fraunces', serif; font-size: 11px; color: var(--g-muted);
}
.reader-page.sound-page .snd-parts-tail {
  margin-top: 4px; font-family: 'Fraunces', 'Jua', serif; font-size: 12px; color: var(--g-red-deep);
}

/* 되살리기 딱지 — 새로 배우는 것과 갈라 보이게 작고 흐리게 */
.reader-page.sound-page .snd-again {
  margin: 14px 0 -8px; text-align: center;
  font-family: 'Fraunces', serif; font-style: italic; font-size: 11px;
  letter-spacing: .04em; color: var(--g-gray);
}

/* ═══ 🎨 그림체 투표 (2026-08-31) ═══
   ⚠️⚠️ **책장(.book-grid)은 «격자»다** — 그 안에 머리글을 넣으면 «격자 칸» 하나가 되어
      왼쪽에 밀리고 세로 가운데로 간다(2026-08-31 실제로 그랬다).
      투표 모드에서는 책장을 블록으로 되돌리고, 격자는 안쪽 .style-grid 가 맡는다.
      또 .book-grid 는 max-width:400px 라 그림체 칸이 한 줄에 둘밖에 안 들어간다 — 넓힌다. */
body.style-vote .book-grid { display: block; max-width: 1100px; padding-left: 16px; padding-right: 16px; }
/* 「나는 누구」와 진행은 늘 보여야 한다 — 스크롤해도 위에 붙어 있게 */
body.style-vote .style-head { position: sticky; top: 0; z-index: 20;
  background: #0e2426;                     /* 책장 배경(#screen-home)과 같은 색이라야 붙어 보인다 */
  margin: 0 -16px; padding: 12px 16px 14px;
  box-shadow: 0 6px 12px -6px rgba(0,0,0,.5); }
/* 어두운 책장 위에 얹히므로 글자·칸을 밝은 쪽으로 */
body.style-vote .voter-lbl { color: rgba(255,255,255,.7); }
body.style-vote .style-stats { background: rgba(255,255,255,.06); border-color: rgba(255,255,255,.14); }
body.style-vote .sstat .k { color: rgba(255,255,255,.6); }
body.style-vote .sstat .v { color: #eaf2f2; }
body.style-vote .style-filters .fbtn,
body.style-vote .voter-btn { background: rgba(255,255,255,.08); color: #eaf2f2;
  border-color: rgba(255,255,255,.2); }
body.style-vote .style-filters .fbtn.on,
body.style-vote .voter-btn.active { background: #fff; color: #0e2426; border-color: #fff; }

   ⚠️ 제작자 전용이다 — 설정에서 끄면 책장이 그대로 돌아온다(데이터는 안 바뀐다). */
.style-head { padding: 4px 2px 14px; display: grid; gap: 12px; }
/* ⚠️ 「찬성·반대」는 «무엇에» 찬성인지 헷갈린다 — 무엇을 정하는 일인지 한 줄로 못 박는다 */
.vote-hint { font-size: 12.5px; line-height: 1.6; color: var(--ink-soft); }
.vote-hint b { color: var(--ink); }
.vote-hint .dim { opacity: .75; }
body.style-vote .vote-hint { color: rgba(255,255,255,.68); }
body.style-vote .vote-hint b { color: #fff; }
.voter-row { display: flex; align-items: center; gap: 8px; }
.voter-lbl { font-size: 13px; color: var(--ink-soft); }
.voter-btn { border: 1px solid var(--border); background: #fff; color: var(--ink);
  border-radius: 100px; padding: 6px 15px; font-size: 14px; font-family: inherit; }
.voter-btn.active { background: var(--navy); color: #fff; border-color: var(--navy); }
.style-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px;
  background: #fff; border: 1px solid var(--border); border-radius: 12px; padding: 11px 12px; }
.sstat { display: grid; gap: 1px; }
.sstat .k { font-size: 11px; color: var(--ink-soft); }
.sstat .v { font-family: 'Fraunces', serif; font-weight: 700; font-variation-settings: 'opsz' 48;
  font-size: 20px; font-variant-numeric: tabular-nums; line-height: 1.2; }
.sstat .v small { font-size: 12px; font-weight: 400; color: var(--ink-soft); }
.sstat .v.mine { color: var(--blue); } .sstat .v.done { color: var(--navy); }
.sstat .v.pass { color: var(--green); } .sstat .v.fail { color: var(--danger); }
.style-filters { display: flex; gap: 7px; flex-wrap: wrap; }
.style-filters .fbtn { border: 1px solid var(--border); background: #fff; color: var(--ink);
  border-radius: 100px; padding: 6px 13px; font-size: 13px; font-family: inherit; }
.style-filters .fbtn.on { background: var(--navy); color: #fff; border-color: var(--navy); }
/* ⚠️ 예전엔 이 버튼이 «그림을 뗀다»라 빨강이었다. 지금은 «판을 넘긴다»라 되돌릴 수 있다 —
   빨강으로 두면 무서워서 아무도 안 누른다. (2026-09-01) */
.round-cta { width: 100%; background: var(--navy); color: #fff; border: 0; border-radius: 12px;
  padding: 13px; font-family: inherit; font-size: 15px; font-weight: 700; line-height: 1.4; }
.round-wait { text-align: center; font-size: 12.5px; color: var(--ink-soft);
  background: var(--paper-warm); border-radius: 10px; padding: 9px 12px; }
/* 규칙별로 몇 가지가 살아남나 — 고를 수 있는 숫자를 보여 준다 */
.rule-row { font-size: 12.5px; color: var(--ink-soft); line-height: 1.7;
  border-top: 1px dashed var(--border); padding-top: 9px; }
.rule-row b { color: var(--navy); font-variant-numeric: tabular-nums; }
.style-note { grid-column: 1 / -1; background: var(--paper-warm); border: 1px solid var(--border);
  border-radius: 12px; padding: 18px 20px; font-size: 14px; line-height: 1.8; }

.style-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 14px; }
.style-card { position: relative; background: #fff; border: 1px solid var(--border);
  border-radius: 14px; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,.06); }
.style-card.voted .book-cover { opacity: .5; }
.style-name { font-size: 13px; font-weight: 700; line-height: 1.4; }
.style-books { font-size: 11.5px; color: var(--ink-soft); margin-top: 2px; }
.sbadge { position: absolute; top: 8px; left: 8px; font-size: 11px; font-weight: 700;
  padding: 3px 9px; border-radius: 100px; color: #fff; }
.sbadge.pass { background: var(--green); } .sbadge.fail { background: var(--danger); }
.sbadge.hold { background: #b08829; }
/* ⭐ 채워짐은 «누가 찍었나»(늘 보임) · 색은 «무엇을 찍었나»(내가 찍은 뒤에만) */
.style-card .who { position: absolute; top: 8px; right: 8px; display: flex; gap: 3px;
  background: rgba(255,255,255,.92); padding: 4px 6px; border-radius: 100px; }
.style-card .who i { width: 8px; height: 8px; border-radius: 50%; display: block;
  border: 1.5px solid var(--ink-soft); background: transparent; }
.style-card .who i.v { background: var(--ink-soft); border-color: transparent; }
.style-card .who i.y { background: var(--green); border-color: transparent; }
.style-card .who i.h { background: #b08829; border-color: transparent; }
.style-card .who i.n { background: var(--danger); border-color: transparent; }
.svote { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; padding: 0 10px 10px; }
.svote .vbtn { border: 1.5px solid var(--border); background: #fff; border-radius: 10px;
  padding: 6px 0 7px; font-size: 11px; font-family: inherit; color: var(--ink);
  display: grid; gap: 1px; line-height: 1.15; }
.svote .vbtn b { font-size: 15px; font-weight: 400; }
.svote .vbtn.on-y { background: var(--green); border-color: var(--green); color: #fff; }
.svote .vbtn.on-h { background: #b08829; border-color: #b08829; color: #fff; }
.svote .vbtn.on-n { background: var(--danger); border-color: var(--danger); color: #fff; }

/* 🖍 아직 한 장도 안 그린 그림체 — 찍을 것이 없어 투표에서 뺐다(★ 2026-09-03).
   ⚠️ «안 보이게» 숨기지 않는다. 「그림 없음」 칸에서 목록으로 보이고, 그림이 붙으면 저절로 돌아온다.
   빗금 바탕으로 «빈자리»임을 보인다 — 📖 하나만 두면 «사진을 못 불러온 카드»와 구별이 안 된다. */
.style-card.noimg { background: var(--paper-warm); }
.style-card.noimg .book-cover {
  background-image: repeating-linear-gradient(45deg, transparent 0 8px, rgba(0,0,0,.04) 8px 16px); }
.style-card.noimg .style-name { color: var(--ink-soft); }
.snone { font-size: 11px; line-height: 1.5; color: var(--ink-soft); padding: 0 10px 10px; }

/* 리더 위에 뜨는 투표 줄 — 그림을 다 본 자리에서 바로 찍는다 */
.style-bar { position: fixed; left: 12px; right: 12px; bottom: 14px; z-index: 60;
  background: rgba(255,255,255,.97); border: 1px solid var(--border); border-radius: 16px;
  box-shadow: 0 6px 24px rgba(0,0,0,.18); padding: 11px 12px; display: grid; gap: 8px;
  max-width: 520px; margin: 0 auto; }
.style-bar .sb-name { font-size: 12.5px; color: var(--ink-soft); text-align: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.style-bar .sb-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 7px; }
.style-bar .vbtn { border: 1.5px solid var(--border); background: #fff; border-radius: 11px;
  padding: 10px 0; font-size: 14px; font-family: inherit; color: var(--ink); }
.style-bar .vbtn.on-y { background: var(--green); border-color: var(--green); color: #fff; }
.style-bar .vbtn.on-h { background: #b08829; border-color: #b08829; color: #fff; }
.style-bar .vbtn.on-n { background: var(--danger); border-color: var(--danger); color: #fff; }
.style-bar .sb-who { display: flex; align-items: center; justify-content: center; gap: 7px;
  font-size: 11.5px; color: var(--ink-soft); }
.style-bar .sb-who .who { display: flex; gap: 3px; }
.style-bar .sb-who .who i { width: 8px; height: 8px; border-radius: 50%; display: block;
  border: 1.5px solid var(--ink-soft); background: transparent; }
.style-bar .sb-who .who i.v { background: var(--ink-soft); border-color: transparent; }
.style-bar .sb-who .who i.y { background: var(--green); border-color: transparent; }
.style-bar .sb-who .who i.h { background: #b08829; border-color: transparent; }
.style-bar .sb-who .who i.n { background: var(--danger); border-color: transparent; }

/* 세 사람이 각각 어디까지 왔나 — 누가 마쳤는지 한눈에 */
.who-row { display: grid; gap: 6px; }
.who-one { display: grid; grid-template-columns: 44px 1fr 62px; align-items: center; gap: 9px;
  font-size: 12px; color: var(--ink-soft); }
.who-one .wn { font-weight: 700; color: var(--ink); }
.who-one .wbar { height: 7px; border-radius: 99px; background: rgba(0,0,0,.08); overflow: hidden; }
.who-one .wbar i { display: block; height: 100%; background: var(--blue); border-radius: 99px; }
.who-one .wc { text-align: right; font-variant-numeric: tabular-nums; }
.who-one.fin .wc { color: var(--green); font-weight: 700; }
.who-one.fin .wbar i { background: var(--green); }
.fin-btn { width: 100%; background: #fff; color: var(--ink); border: 1.5px solid var(--border);
  border-radius: 12px; padding: 11px; font-family: inherit; font-size: 14px; }
.fin-btn.on { background: var(--green); border-color: var(--green); color: #fff; }
.sstat .v.hold { color: #b08829; }
/* 어두운 책장 위 */
body.style-vote .who-one { color: rgba(255,255,255,.62); }
body.style-vote .who-one .wn { color: #eaf2f2; }
body.style-vote .who-one .wbar { background: rgba(255,255,255,.12); }
body.style-vote .fin-btn { background: rgba(255,255,255,.08); color: #eaf2f2;
  border-color: rgba(255,255,255,.2); }
body.style-vote .fin-btn.on { background: var(--green); border-color: var(--green); color: #fff; }

/* ⚠️ .hidden 은 전역 클래스가 아니었다 — 비밀번호 재설정 두 단계에 쓰려고 넣는다 */
#resetStep1.hidden, #resetStep2.hidden, #resetResendRow.hidden { display: none; }

/* 비밀번호 재설정 — 코드 확인이 끝났음을 또렷이 알린다 */
.reset-ok { background: rgba(46,122,74,.1); border: 1px solid rgba(46,122,74,.35);
  color: var(--green); border-radius: 10px; padding: 10px 12px; margin-bottom: 16px;
  font-size: 14px; text-align: center; font-family: 'Fraunces', 'Gowun Batang', serif; }
