/* Reader layout, typography, floating controls, and formatting blocks */

  #v-read{display:none;}
  #v-read.on{display:flex;}
  #readmain{position:relative; flex:1; min-width:0;}

  /* ================= 읽는 동안의 셸 =================

     읽는 동안 문서는 화면에 못 박히고, 스크롤은 `#reader-scroll` 하나가 합니다.
     상단바·진행줄·단추·시트는 그 칸 바깥에 떠 있습니다.

     얻는 것이 셋입니다.

     하나. 글이 처음부터 노치 옆까지 뻗습니다. 예전 상단바는 `sticky` 라 문서
     흐름 안에 제 자리를 차지했고, 걷어도 그 자리는 남았습니다. 글이 위까지 온
     것처럼 보였던 것은 "스크롤을 그 높이만큼 지나가서 바가 글을 덮은" 상태를
     투명하게 만든 것뿐이라, 스크롤이 위로 돌아오면 다시 막혔습니다. 이제는
     흐름 밖이라 막힐 자리가 없습니다.

     둘. 종이를 벌려도 떠 있는 것들은 제 크기입니다. 확대가 `#original-zoom`
     안쪽 일이라 바깥은 애초에 안 커집니다 — 되돌리는 계산이 사라집니다.

     셋. 읽는 화면에는 상단바가 뜨지 않습니다. 떠 있는 것은 조작 조각 셋
     (`#readchrome`)과 진행줄 하나뿐이고, 그것들은 스크롤을 따라 걷히지도
     흐려지지도 않습니다 — 스크롤은 글을 옮기는 일일 뿐입니다. */
  html.reading, body.reading{height:100%; overflow:hidden; overscroll-behavior:none;}
  body.reading #app{position:fixed; inset:0;}
  /* 읽는 동안에는 상단바를 감춥니다. Breeze·Home·Words·Settings 는 서재에서
     만나는 것들이고, 여기서 필요한 것은 `#readchrome` 의 세 조각뿐입니다.
     **지우지 않고 감춥니다** — 넓은 화면에서는 예전 상단바를 고정형으로 다시
     세울 수 있고, 그날 되돌릴 것이 이 한 줄이면 되게 하려는 것입니다. 상단바의
     DOM·navigation·걷힘 규칙은 전부 제자리에 있습니다.
     (`--topbar-h` 는 여기서 0 이 되지 않습니다 — 재는 자리가 보이는 동안에만
     적기 때문입니다. scripts/ui/preferences.js 의 `syncTopbarH`) */
  body.reading #topbar{display:none;}
  /* 읽는 화면의 표시 글자는 Breeze가 다룹니다. 단어는 탭, 문장은 꾹 누르기이며
     iOS의 native selection은 이 화면의 interaction이 아닙니다. 실제로 고치는
     control만 명시적으로 되돌려 cursor·복사·붙여넣기를 보존합니다. */
  body.reading #v-read{-webkit-user-select:none; user-select:none; -webkit-touch-callout:none;}
  body.reading #v-read input, body.reading #v-read textarea,
  body.reading #v-read [contenteditable]{-webkit-user-select:text; user-select:text;
    -webkit-touch-callout:default;}
  body.reading #v-read.on{position:absolute; inset:0;}
  /* 높이만 채웁니다. `position:absolute` 로 못 박으면 흐름에서 빠져서, 옆에
     서야 할 낱말 패널이 유일한 흐름 안 칸이 되어 왼쪽으로 갑니다. */
  body.reading #readmain{height:100%;}
  /* `pan-x pan-y` 는 미는 것은 그대로 두고 브라우저의 벌리기·두 번 눌러 확대만
     뺍니다. 벌리기는 이제 우리가 그립니다 (`scripts/reader/pdf-pinch.js`).

     이 계약을 absolute 스크롤러 한 곳에만 맡기지 않습니다. iOS WebKit에는
     absolute positioned element의 `touch-action`을 double-tap zoom에서 놓치는
     알려진 경로가 있습니다. 그래서 실제 종이를 품는 static 경계에도 같은 값을
     둡니다. Text는 `#readwrap`, PDF·EPUB은 `#originalwrap`을 반드시 지나므로
     OS나 포맷별 예외 없이 같은 교집합을 만듭니다. `manipulation`은 native pinch를
     다시 허용하므로 쓰지 않습니다. */
  #reader-scroll{position:absolute; inset:0; overflow:auto; overscroll-behavior:contain;
    -webkit-overflow-scrolling:touch; touch-action:pan-x pan-y;}
  #readwrap,#originalwrap{touch-action:pan-x pan-y;}
  /* ---- 스크롤 막대는 가늘게 ----
     맥에서 "스크롤 막대 항상 표시"를 켜 두면 이 칸의 막대가 15px 를 차지합니다.
     그 자리가 하필 글과 낱말 창 사이라, 두 칸을 가르는 굵은 선처럼 보였습니다.
     자리를 6px 로 줄이고 바탕은 비웁니다 — 남는 것은 손잡이 하나입니다.
     **없애지는 않습니다.** 긴 책에서 손잡이를 잡아 단숨에 옮기는 길이 여기 말고는
     없습니다.

     마우스 화면에서만 합니다(`pointer:fine`). 손으로 미는 화면의 막대는 원래
     떴다 사라지는 것이라 자리를 안 차지하는데, 모양을 적는 순간 늘 서 있는
     막대로 바뀝니다 — 폰과 태블릿은 손대지 않는 편이 맞습니다.

     `::-webkit-scrollbar` 와 `scrollbar-width` 는 함께 못 씁니다. 크롬은 둘 다
     있으면 표준 쪽을 따르는데 거기서 가장 가는 값이 11px 이라, 6px 이 조용히
     무시됩니다. 그래서 `::-webkit-scrollbar` 를 모르는 브라우저에만 표준 쪽을
     남깁니다(파이어폭스 — 거기서는 `thin` 이 가장 가는 값입니다). */
  @media (pointer:fine){
    #reader-scroll::-webkit-scrollbar{width:6px; height:6px;}
    #reader-scroll::-webkit-scrollbar-track{background:transparent;}
    #reader-scroll::-webkit-scrollbar-thumb{background:var(--sb-thumb); border-radius:3px;}
    #reader-scroll::-webkit-scrollbar-thumb:hover{background:var(--sb-thumb-strong);}
    #reader-scroll::-webkit-scrollbar-corner{background:transparent;}
    @supports not selector(::-webkit-scrollbar){
      #reader-scroll{scrollbar-width:thin; scrollbar-color:var(--sb-thumb) transparent;}
    }
  }
  .iconbtn{border:none; background:none; border-radius:8px; padding:5px 9px; cursor:pointer; font-size:13.5px; color:var(--soft);}
  .iconbtn:hover{background:var(--hover-quiet);}
  #readwrap,#originalwrap{transition:opacity .22s ease,filter .22s ease;}
  body.reader-mode-transition #readwrap,body.reader-mode-transition #originalwrap{opacity:.72; filter:saturate(.9);}
  /* 모드를 바꿨을 때 "여기 있었어요" 하고 짚어 주는 자리. Breeze 라서 로고 그라디언트의
     바람색(#4DAED6)을 씁니다 — 초록은 이 앱 어디에도 없는 색이었습니다. */
  ::highlight(breeze-mode-cue){background:var(--cue); color:inherit;}
  .reader-mode-cue-dom{position:absolute; z-index:38; display:block; pointer-events:none;
    border-radius:4px; background:var(--cue); animation:reader-mode-cue-out 10s ease forwards;}
  /* Aa settings popover */
  /* Aa 단추가 오른쪽 위로 올라갔으므로 창도 그 밑에서 열립니다. */
  #aa-pop{position:fixed; right:14px; top:calc(env(safe-area-inset-top) + 54px); z-index:96; background:var(--sheet); border:1px solid var(--sheet-line);
    border-radius:16px; padding:16px 18px; width:240px; box-shadow:var(--shadow); display:none;}
  #aa-pop.on{display:block;}
  .aa-legend{display:flex; flex-direction:column; gap:5px; font-size:11.5px; color:var(--soft);
    padding-bottom:10px; margin-bottom:4px; border-bottom:1px solid var(--line);}
  .aa-legend i{display:inline-block; width:9px; height:9px; border-radius:2px; margin-right:6px; vertical-align:0;}
  .aa-row{display:flex; align-items:center; justify-content:space-between; padding:8px 0;}
  .aa-row.stack{flex-direction:column; align-items:stretch; gap:7px;}
  .aa-label{font-size:13.5px; color:var(--soft); font-weight:500;}
  /* 좌우 여백 — 세 칸짜리 띠. 글 폭이 바뀌므로 글자 화면에서만 뜹니다. */
  .aa-seg{display:flex; padding:3px; gap:2px; border:1px solid var(--line); border-radius:11px;}
  .aa-seg button{flex:1; border:0; background:transparent; color:var(--soft); border-radius:8px;
    padding:7px 0; cursor:pointer; font:600 12px/1 var(--ui);}
  .aa-seg button:hover{background:var(--sky);}
  .aa-seg button.on{background:var(--seg-on); color:var(--seg-on-ink);}
  .aa-label small{display:block; margin-top:2px; font-size:10.5px; color:var(--soft2); font-weight:400;}
  .aa-size{display:flex; align-items:center; gap:10px;}
  .aa-size button{border:1px solid var(--line); background:none; border-radius:9px; padding:5px 11px;
    cursor:pointer; font-size:13px; color:var(--ink); font-family:var(--ui);}
  .aa-size button:hover{background:var(--sky);}
  #aa-fs{font-size:13.5px; min-width:24px; text-align:center; color:var(--ink);}
  /* PDF 원본을 열었을 때만 켭니다 — updateOriginalZoomControls() 가 켜고 끕니다.
     `.aa-row{display:flex}` 가 저작 스타일이라 UA 의 `[hidden]{display:none}` 을
     덮어써서, 여기서 다시 명시해야 실제로 접힙니다. */
  #aa-pdfzoom[hidden]{display:none;}
  #aa-pdfzoom-pct{font-size:13.5px; min-width:34px; text-align:center; color:var(--ink);}
  .aa-size button:disabled{opacity:.35; cursor:default;}
  .aa-size button:disabled:hover{background:none;}
  .aa-toggle{width:46px; height:26px; border-radius:13px; border:none; background:var(--toggle-off); cursor:pointer;
    position:relative; transition:background .2s;}
  .aa-toggle i{position:absolute; top:3px; left:3px; width:20px; height:20px; border-radius:50%;
    background:var(--toggle-knob); transition:left .2s; box-shadow:var(--shadow-knob);}
  .aa-toggle.on{background:var(--blue);}
  .aa-toggle.on i{left:23px;}
  body.reader-original .aa-text-only{display:none;}
  /* 어두운 화면의 색은 여기 없습니다 — styles/tokens.css 의 `body.dark` 가
     같은 이름을 다시 선언하는 것으로 끝납니다. 여기 남은 두 줄은 색이 아니라
     "어두운 화면에서는 이 규칙이 통째로 없다/다르다"는 이야기입니다. */
  body.dark .page{box-shadow:none;}
  body.dark .sm-btn.ghost:hover{background:var(--ghost-btn-hover);}
  /* ---- 읽는 동안 떠 있는 조각 ----
     상단바를 감추고 남긴 것은 셋입니다 — 왼쪽 위에 나가는 길, 오른쪽 위에 보기
     설정과 글자↔원본. 스크롤과는 아무 관계가 없습니다: 자리도 진하기도 늘
     같습니다. 예전에는 읽어 내려가면 상단바가 걷히고 단추가 흐려졌는데, 그것은
     "읽는 중"이라는 상태를 하나 더 두는 일이었고 그 상태 때문에 노치 옆이
     막혔다 열렸다 했습니다. 이 조각들에는 그 상태가 걸리지 않습니다.

     위치와 크기는 Reader 조작에 맞춘 채, 재질은 낱말·문장 Lookup과 같은 Breeze
     Glass를 씁니다. 서로 다른 기능이라도 한 화면에서 같은 표면처럼 읽혀야 합니다. */
  .control-dock{position:fixed;inset:auto 0 0;height:calc(env(safe-area-inset-bottom) + 59px);z-index:70;pointer-events:none;}
  #readchrome, .control-bar{position:absolute; bottom:calc(env(safe-area-inset-bottom) + 15px); left:0; right:0; z-index:70;
    display:flex; align-items:center; justify-content:space-between;
    padding:0 14px;
    /* 조각 사이의 빈 자리는 본문의 것입니다 — 손짓이 여기서 막히면 안 됩니다. */
    pointer-events:none;}
  #readchrome > *, .control-bar > *{pointer-events:auto;}
  .control-glass{isolation:isolate; overflow:hidden;
    border:1px solid var(--sentence-glass-line); background:var(--sentence-glass-solid);
    box-shadow:var(--sentence-glass-shadow-pill),inset 0 -1px 0 rgba(0,0,0,.05);
    color:var(--sentence-glass-ink);}
  .control-glass::before{content:""; position:absolute; z-index:-1;
    inset:0; pointer-events:none; border-radius:inherit;
    background:linear-gradient(145deg,rgba(255,255,255,.30) 0%,rgba(255,255,255,.07) 44%,rgba(255,255,255,.16) 100%);
    box-shadow:inset 0 1px 0 rgba(255,255,255,.42);}
  body.dark .control-glass::before{
    background:linear-gradient(145deg,rgba(255,255,255,.15) 0%,rgba(255,255,255,.025) 46%,rgba(255,255,255,.07) 100%);
    box-shadow:inset 0 1px 0 rgba(255,255,255,.14);}
  @supports ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
    .control-glass{background:var(--sentence-glass-pill);
      backdrop-filter:blur(19px) saturate(122%); -webkit-backdrop-filter:blur(19px) saturate(122%);}
  }
  /* 왼쪽 원과 오른쪽 조각은 **같은 높이·같은 윗변**입니다(36px · 안전 영역 + 10px).
     둘이 한 줄에 나란히 서는 물건이라, 한쪽만 1px 달라도 줄이 어긋나 보입니다.
     아래 `#readfabs` 의 높이도 같은 36px 이어야 합니다. */
  #readback,#aafab, .control-circle{position:relative; width:42px; height:42px; border-radius:50%; padding:0;
    display:flex; align-items:center; justify-content:center; cursor:pointer;}
  /* 그림은 상자 한가운데 놓여 있지만, 화살표의 **잉크**는 그렇지 않습니다.
     `<` 는 24칸 중 8~14.2 만 차지해서 잉크의 한가운데가 11.1 — 상자 한가운데(12)
     보다 0.9칸(19px 로 그리면 0.71px) 왼쪽입니다. 뾰족한 끝이 열린 쪽보다 가볍게
     보이는 것까지 더해 1px 만 오른쪽으로 밉니다. 상자는 그대로입니다 — 옮기는
     것은 그림 하나입니다. */
  #readback svg{width:19px; height:19px; transform:translateX(1px);}
  /* 보이는 것은 작게, 누르는 자리는 넉넉하게. 그림을 키우면 종이 위에서 무거워
     지고, 자리를 줄이면 걸어가며 못 누릅니다 — 둘을 따로 정합니다. */
  #readback::after{content:''; position:absolute; inset:-6px;}
  #aafab{font:600 15px var(--ui);}
  #readpill, .control-pill{position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
    width:min(56vw,400px); height:44px; border-radius:24px;
    display:flex; align-items:center; justify-content:center; padding:4px 12px; overflow:hidden;}
  #readpill{transition:width .26s cubic-bezier(.2,.75,.25,1),height .26s cubic-bezier(.2,.75,.25,1),
      padding .26s cubic-bezier(.2,.75,.25,1),border-radius .26s cubic-bezier(.2,.75,.25,1),
      box-shadow .34s ease;}
  #readpill-progress,#home-resume-progress{position:absolute; inset:0; pointer-events:none;
    background:var(--chrome-progress); transform:scaleX(0); transform-origin:left center;
    will-change:transform;}
  #readpill-title,#readpill #modefab{position:relative; z-index:1;}
  #readpill-title{border:0; background:none; color:inherit; cursor:default;
    min-width:0; max-width:100%; padding:0 5px; overflow:hidden; text-overflow:ellipsis;
    white-space:nowrap; font:600 13px var(--ui);}
  #readpill #modefab{flex:none; width:34px; height:38px; padding:0; border:0;
    background:none; color:inherit; display:flex; align-items:center; justify-content:center;
    cursor:pointer; overflow:hidden; opacity:1;
    transition:width .3s ease,opacity .18s ease,margin .3s ease;}
  #readpill #modefab[hidden]{display:none;}
  #sentence-pill-status{position:relative; z-index:2; width:100%; min-width:0;
    display:flex; align-items:center; justify-content:center; gap:9px;
    color:var(--sentence-glass-ink); font:600 13px var(--ui); white-space:nowrap;}
  #sentence-pill-status[hidden]{display:none;}
  .sentence-spinner{width:14px; height:14px; flex:none; border:2px solid var(--sentence-glass-spinner);
    border-top-color:var(--sentence-glass-spinner-on); border-radius:50%; animation:sentence-spin .8s linear infinite;}
  @keyframes sentence-spin{to{transform:rotate(1turn)}}
  body.sentence-pill-waiting #readpill,
  body.sentence-pill-waiting.chrome-hidden #readpill{width:min(calc(100vw - 28px),520px); height:48px;
    border-radius:26px; background:var(--sentence-glass-solid); border-color:var(--sentence-glass-line);
    box-shadow:var(--sentence-glass-shadow-pill); transition-duration:var(--sentence-transition);}
  @supports ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
    body.sentence-pill-waiting #readpill,
    body.sentence-pill-waiting.chrome-hidden #readpill{background:var(--sentence-glass-pill);
      backdrop-filter:blur(16px) saturate(115%); -webkit-backdrop-filter:blur(16px) saturate(115%);}
  }
  body.sentence-pill-waiting #readpill-progress,
  body.sentence-pill-waiting #readpill-title,
  body.sentence-pill-waiting #readpill #modefab{display:none;}
  body.sentence-pill-waiting #readback,
  body.sentence-pill-waiting #aafab{opacity:0; visibility:hidden; pointer-events:none;
    transform:translateY(6px) scale(.94);}
  #readback,#aafab{transition:opacity var(--sentence-transition) ease,
    transform var(--sentence-transition) cubic-bezier(.2,.7,.25,1),visibility 0s;}
  body.chrome-hidden #readpill{width:min(36vw,180px); height:34px; padding:2px 8px; border-radius:18px;}
  body.chrome-hidden #readpill #modefab{width:0; opacity:0; visibility:hidden; pointer-events:none;}
  body.chrome-hidden #readback,body.chrome-hidden #aafab{
    opacity:0; transform:translateY(8px); visibility:hidden; pointer-events:none;
    transition:opacity .2s ease,transform .3s ease,visibility 0s .3s;}
  body.chrome-hidden #readpill-title{cursor:pointer;}
  #readback:active, #aafab:active, #readpill button:active, .control-glass:active{background:var(--chrome-press);}
  @media (hover:hover){
    #readback:hover, #aafab:hover, .control-circle:hover{background:var(--chrome-press);}
  }
  /* 넓은 화면에서도 정보 구조는 같습니다 — 왼쪽에 나가는 길, 오른쪽에 둘.
     데스크톱 전용 길은 만들지 않습니다. 넓어진 만큼 조각이 가장자리에서 조금
     더 떨어지고, 마우스로 보는 화면에서는 들린 자국을 아예 지웁니다. */
  /* 들린 자국은 넓은 화면에서도 남깁니다. 어두운 화면에서 조각의 종이색은 바탕과
     같은 색(`--paper`)을 옅게 깐 것이라, 자국까지 지우면 조각이 통째로 사라집니다 —
     글자가 없는 왼쪽 여백 위의 back 이 특히 그렇습니다. */
  @media (min-width:761px){
    #readchrome, .control-bar{padding:0 22px;}
  }
  @media (prefers-reduced-motion:reduce){
    #readpill,#readback,#aafab,#readpill #modefab{transition-duration:var(--sentence-transition);
      transition-property:opacity,visibility,background-color;}
    .sentence-spinner{animation-duration:1.25s;}
  }
  /* 여기 있던 서른 줄은 "벌리면 커진 만큼 다시 줄여 놓는" 보정이었습니다 —
     `--vv-k`(배율의 역수)와 `--vv-x`·`--vv-y`·`--vv-dx`·`--vv-dy`(보이는 화면이
     문서의 어디에 있나)를 매 프레임 읽어 단추·시트·상단바에 되걸었습니다.

     그 값은 늘 한 박자 늦었습니다. 벌어지는 그림은 컴포지터가 혼자 그리고
     자바스크립트는 그 뒤를 따라가므로, 벌리는 내내 단추가 딸려 다니다 손을 뗀
     뒤에야 제자리를 찾았습니다. 배율이 미끄러져 돌아오는 마지막 한 번은 아무
     이벤트도 없이 끝나는 일이 있어서, 단추 둘만 벌리던 도중의 배율에 굳기도
     했습니다.

     이제 확대는 `#original-zoom` 안쪽에서 끝납니다. 이 단추들은 그 바깥이라
     애초에 안 커집니다 — 되돌릴 것이 없으니 보정도 없습니다. */

  /* 원본 ↔ 글자 — 글자 하나 없이 지금 모드의 반대쪽을 그립니다.
     종이(모서리 접힌 문서)면 원본으로, 글줄이면 글자 화면으로 갑니다. */
  #modefab svg{width:21px; height:21px;}
  #modefab svg g{transform-origin:12px 12px; transition:opacity .22s ease, transform .22s ease;}
  #modefab .mf-text{opacity:0; transform:scale(.8);}
  body.reader-original #modefab .mf-original{opacity:0; transform:scale(.8);}
  body.reader-original #modefab .mf-text{opacity:1; transform:none;}

  /* PDF 확대 −/+ 는 이제 Aa popover 안, `.aa-size` 한 줄입니다 — 뜨는 조각을
     늘리지 않으려고 따로 띄우던 자리를 없앴습니다. 버튼이 부르는
     `changeOriginalZoom` 과 그 안의 배율·범위·저장은 그대로입니다
     (scripts/reader/reader-scroll.js). */

  /* ---- 상단바는 읽는 방향을 따릅니다 (지금 읽는 화면에서는 잠자코 있습니다) ----
     내려 읽으면 걷히고, 올리거나 글머리에 닿으면 돌아옵니다. 읽는 화면에서는
     상단바가 `display:none` 이라 이 규칙들이 걸릴 자리가 없습니다 — 넓은 화면에서
     예전 상단바를 다시 세우는 날 그대로 쓸 수 있게 남겨 둡니다.

     **새 조작 조각(`#readchrome`)에는 이 규칙이 하나도 걸리지 않습니다.** 자리도
     진하기도 늘 같아야 하기 때문입니다 — 예전의 `body.chrome-hidden #readfabs`
     (읽어 내려가면 흐려짐)는 그래서 여기서 지웠습니다. PDF 확대는 이제 Aa
     popover 안에 살아서 애초에 스크롤 걷힘과 무관합니다. 진행줄도 이제 한
     자리에 고정입니다.

     밀지 못했던 것은 `position:sticky` 인 칸이 아이폰에서 스크롤과 같은 층에
     있어서, `transform` 을 얹으면 옛 그림 한 장이 노치 옆에 남았기 때문입니다.
     상단바가 흐름 밖(`fixed`)으로 나오면서 그 층이 갈라졌습니다. 흐림 층만 미리
     끕니다 — `backdrop-filter` 는 밀려난 자리에 흐림만 남기는 일이 있습니다. */
  #topbar{transition:transform .24s cubic-bezier(.4,0,.2,1), opacity .18s ease, visibility 0s;}
  body.chrome-hidden #topbar{
    transform:translateY(-100%); opacity:0; visibility:hidden; pointer-events:none;
    backdrop-filter:none; -webkit-backdrop-filter:none;
    transition:transform .24s cubic-bezier(.4,0,.2,1), opacity .18s ease, visibility 0s linear .24s;}
  @media(prefers-reduced-motion:reduce){
    #topbar{transition:none;}
    body.chrome-hidden #topbar{transition:none;}
  }
  /* 글 폭과 좌우 여백은 Aa 안에서 고릅니다. 스크롤에 따라 바뀌지는 않습니다 —
     읽는 도중 줄바꿈이 흔들리면 보던 자리를 놓칩니다.

     위 여백은 조작 조각이 **자리를 차지해서**가 아니라, 첫 줄이 처음부터 그
     밑에 깔려 있으면 안 되기 때문입니다. 읽어 내려가면 글은 조각 밑으로 그대로
     지나갑니다 — 조각은 자리를 뺏지 않고 떠 있을 뿐입니다(`#readchrome`). */
  #readwrap{max-width:var(--readw,700px); margin:0 auto;
    padding:calc(env(safe-area-inset-top) + 24px) var(--readpad,26px) 50vh;}
  #rtitle{font-family:var(--serif); font-size:clamp(24px,3.4vw,30px); color:var(--ink); padding-bottom:18px; overflow-wrap:anywhere;
    border-bottom:1px solid var(--line); margin-bottom:8px;}
  /* 기사에는 연결할 원본 파일이 없습니다. 원문으로 가는 길만 남겨 둡니다. */
  #rsource,#rdiscovery{display:block; font-size:12.5px; color:var(--soft2); text-decoration:none; margin:-2px 0 8px;}
  #rsource:hover,#rdiscovery:hover{color:var(--blue);}
  #rsource[hidden],#rdiscovery[hidden]{display:none;}
  #r-attribution{margin:30px 0 24px;padding-top:12px;border-top:1px solid var(--line);font:12px/1.65 var(--ui);color:var(--soft2);}
  #r-attribution summary{cursor:pointer;user-select:none;list-style:none;opacity:.8;}
  #r-attribution summary::-webkit-details-marker{display:none;}
  #r-attribution summary::after{content:'＋';margin-left:7px;font-size:11px;}
  #r-attribution[open] summary::after{content:'−';}
  #r-attribution .r-attribution-body{padding-top:8px;overflow-wrap:anywhere;}
  #r-attribution p{margin:0 0 4px;}
  #r-attribution a{color:var(--soft2);text-decoration:underline;text-underline-offset:2px;}
  #rhint{font-size:13px; color:var(--soft2); margin-bottom:26px; display:flex; align-items:center; gap:8px;}
  #rhint svg{flex-shrink:0;}
  /* 본문 낱말은 탭·꾹 누르기라는 리더의 손짓입니다. native selection 정책은
     위 `body.reading #v-read` 경계가 Text·PDF·사전·문장 창에 함께 적용합니다. */
  #rtext{font-family:var(--serif); font-size:var(--fs,19px); line-height:1.9; color:var(--ink-body); overflow-wrap:anywhere;}
  #rtext p{margin-bottom:1.2em;}
  #rtext .toc-entry{font-size:.92em; line-height:1.55; margin:.45em 0; color:var(--soft);}
  #rtext .section-break{margin-top:2.5em;}
  /* 부 · 장 · 절 — 위계가 눈에 보여야 종이책처럼 읽힙니다 */
  #rtext h2{font-size:1.62em; font-weight:600; letter-spacing:-.5px; line-height:1.35;
    margin:2.2em 0 1.5em; padding-bottom:.5em; border-bottom:1px solid var(--line);
    color:var(--ink); text-align:center;}
  #rtext h3{font-size:1.24em; font-weight:600; margin:2em 0 1em; color:var(--ink); line-height:1.4;}
  #rtext h4{font-size:1.02em; font-weight:700; margin:1.7em 0 .7em; color:var(--ink);
    letter-spacing:.01em;}
  #rtext h2:first-child, #rtext h3:first-child, #rtext h4:first-child{margin-top:.2em;}
  /* 인용문 · 편지 — 본문에서 한 발 물러나게 */
  #rtext .blk{margin:1.6em 0; }
  #rtext .blk.quote{padding:.2em 0 .2em 1.2em; border-left:3px solid var(--quote-line);}
  #rtext .blk.quote p{font-size:.95em; color:var(--soft); font-style:italic; margin-bottom:.8em;}
  #rtext .blk.quote p:last-child{margin-bottom:0;}
  /* 활동 상자 · 역주 — 원서에서 테두리 상자로 조판되던 것 */
  #rtext .blk.note{background:var(--note-bg); border:1px solid var(--note-line); border-radius:14px;
    padding:18px 20px;}
  #rtext .blk.note p{font-size:.93em; margin-bottom:.7em; color:var(--ink-body);}
  #rtext .blk.note p:last-child{margin-bottom:0;}
  #rtext .blk.note p:first-child{font-weight:700; font-family:var(--ui); font-size:.86em;
    letter-spacing:.02em; color:var(--chiptx); margin-bottom:.9em;}
  @media(max-width:760px){ #rtext .blk.note{padding:15px 16px;} }
  /* 붙여넣은 README 의 코드. 긴 줄은 상자 안에서만 옆으로 밀립니다 — 쪽이
     통째로 넓어지면 본문 줄바꿈이 흔들려서 보던 자리를 놓칩니다. */
  #rtext .blk.code{background:var(--code-bg); border:1px solid var(--note-line); border-radius:12px;
    padding:14px 16px; margin:0 0 1.1em; overflow-x:auto; -webkit-overflow-scrolling:touch;
    font:13px/1.65 var(--mono); color:var(--ink-body);
    white-space:pre;}
  @media(max-width:760px){ #rtext .blk.code{padding:12px 13px; font-size:12px;} }
  .page{background:var(--page); border:1px solid var(--page-line); border-radius:20px;
    padding:40px var(--pagepad,44px); overflow:hidden;
    box-shadow:var(--page-shadow);}
  .pageno{text-align:center; color:var(--pageno); font-size:12px; margin:18px 0 26px; font-family:var(--serif); user-select:none;}
  #rtext figure{margin:1.5em 0; text-align:center;}
  #rtext figure.story-illustration{margin:1.8em 0 2em;}
  #rtext figure.story-illustration img{display:block; width:100%; height:auto; aspect-ratio:3/2;}
  #rtext .story-scene-break{text-align:center;letter-spacing:.3em;color:var(--soft2);margin:2.5em 0;}
  /* 그림을 꾹 누르면 Safari 는 그것을 집어 옮기려 합니다. 그 끌기가 시작되면
     읽는 손짓이 더 이상 오지 않아 화면이 굳은 것처럼 됩니다 — 홈의 표지 카드가
     이미 같은 선언을 갖고 있습니다(styles/home.css). 판정 계층도 `dragstart` 를
     한 번 더 막습니다(scripts/reader/gesture.js): 막는 것과 지우는 것은 서로의
     대체가 아니라 서로의 뒷받침입니다. */
  #rtext figure img{max-width:100%; border-radius:10px; box-shadow:var(--shadow);
    -webkit-user-drag:none; -webkit-touch-callout:none;}
  .w{cursor:pointer; border-radius:5px; padding:0 1px; margin:0 -1px; transition:background .12s;
    /* 저장한 색이 아닌데 잠깐 회색 네모가 생기는 것은 Safari/Chrome의 기본 탭 표시입니다.
       단어 자체가 클릭 단추라 이 브라우저 효과는 남길 이유가 없습니다. */
    -webkit-tap-highlight-color:transparent;}
  /* Text에서 실제로 연타를 받는 단어만 double-tap zoom 후보에서 뺍니다.
     PDF/EPUB 표면과 공용 gesture controller에는 이 실험을 넓히지 않습니다. */
  #rtext .w{touch-action:manipulation;}
  /* iOS는 터치한 낱말에도 hover를 남겨 두고, 다음 스크롤에서야 지웁니다.
     저장하지 않은 낱말이 회색 상자로 남아 보이던 원인이라 마우스 환경에서만
     hover 색을 씁니다. */
  @media (hover:hover) and (pointer:fine){
    .w:hover{background:var(--word-hover);}
  }
  .w.s1{background:var(--mark1);}
  .w.s2{background:var(--mark2);}
  .w.s3{background:var(--mark3);}
  .w.reader-mode-cue-word{background:var(--cue)!important; box-shadow:0 0 0 2px var(--cue-ring);}
  [data-pi].reader-mode-cue-block{background:var(--cue-block); border-radius:5px;}
  .w.sel{background:var(--sky2); box-shadow:0 0 0 3px var(--sky2); border-radius:6px;}
  .legend{display:flex; gap:12px; font-size:12px; color:var(--soft);}
  .legend i{display:inline-block; width:10px; height:10px; border-radius:3px; margin-right:4px; vertical-align:-1px;}

  /* ================= original document mode ================= */
  /* 폭 제한과 좌우 여백은 확대되는 층 **안쪽**(.original-content)으로 옮겼습니다.
     바깥이 폭을 정하면 벌릴 때마다 종이의 왼쪽 끝이 움직여서, 손가락 아래 있던
     줄을 붙들어 둘 기준점이 사라집니다. 안쪽에 두면 여백도 종이와 함께 커집니다
     — 진짜 PDF 뷰어가 그렇습니다. */
  #originalwrap{padding:calc(env(safe-area-inset-top) + 24px) 0 45vh;}
  #originalwrap[hidden]{display:none;}
  #original-selection-hint{width:max-content; max-width:calc(100% - 12px); margin:0 auto 12px; padding:6px 11px;
    border:1px solid var(--line); border-radius:14px; background:var(--paper2); color:var(--soft2);
    font:11px/1.3 var(--ui); text-align:center;}
  /* 확대된 종이가 차지할 자리. 크기는 자바스크립트가 적습니다 (기준 크기 × 배율).
     이 칸이 넓어지면 스크롤 칸 안에 가로로 밀 거리가 생깁니다 — 문서 폭은
     한 픽셀도 안 변하므로 폰 브라우저가 화면을 축소할 이유가 없습니다. */
  body.reader-original #reader-scroll:has(.pdf-original){overflow-anchor:none;}
  #original-stage{position:relative;}
  #original-stage.pinching{overflow:clip;}
  #original-stage.pinching #original-zoom{will-change:transform;}
  /* 종이 자체. 레이아웃 폭은 늘 기준 폭이고 커지는 것은 `transform` 뿐입니다.
     그래서 벌려도 글이 다시 흐르지 않습니다 — PDF 캔버스가 보는 `clientWidth`
     가 그대로이기 때문입니다. */
  /* `width:100%` 는 자바스크립트가 재기 전까지의 값입니다. `position:absolute` 인
     칸은 폭을 안 적으면 내용에 맞춰 쪼그라들어서, 첫 그림이 좁게 그려집니다. */
  #original-zoom{position:absolute; top:0; left:0; width:100%; transform-origin:0 0;}
  .original-content{width:100%; max-width:980px; margin:0 auto; padding:0 24px;}
  .original-loading{min-height:55vh; display:flex; flex-direction:column; align-items:center; justify-content:center;
    gap:14px; color:var(--soft); font-size:14px;}
  .original-loading i{width:28px; height:28px; border:3px solid var(--line2); border-top-color:var(--blue);
    border-radius:50%; animation:original-spin .8s linear infinite;}
  @keyframes original-spin{to{transform:rotate(360deg)}}
  .original-empty{max-width:520px; margin:8vh auto 0; padding:42px 34px; text-align:center; background:var(--field-soft);
    border:1px solid var(--field-line); border-radius:22px; box-shadow:var(--shadow);}
  .original-empty-icon{font-size:38px; color:var(--blue); margin-bottom:14px;}
  .original-empty h2{font-size:21px; margin-bottom:12px; color:var(--ink);}
  .original-empty p{font-size:14px; line-height:1.75; color:var(--soft);}
  .original-empty button{display:block; margin:22px auto 12px; border:0; border-radius:22px; padding:11px 22px;
    background:var(--blue); color:var(--on-color); cursor:pointer; font:600 14px var(--ui);}
  .original-empty small{display:block; color:var(--soft2); font-size:11.5px;}

  .pdf-original{display:flex; flex-direction:column; align-items:center; gap:22px;}
  /* 쪽은 언제나 글 폭에 꽉 찹니다. 확대는 손가락이 합니다 — 쪽마다 제 가로
     스크롤 칸을 주던 구조를 걷어 냈습니다. 칸이 있으면 한 줄을 읽으려고 옆으로
     민 자리가 다음 쪽에서 풀려서, 쪽을 넘길 때마다 같은 손짓을 다시 해야
     했습니다. 이제 문서 전체가 종이 한 장처럼 같은 축에서 움직입니다. */
  /* 쪽 전체가 눌러서 뜻을 보는 자리입니다 — 글자 화면의 `.w` 와 같은 커서를
     줍니다. 스캔본은 그림이라 그냥 두면 화살표라서, 마우스가 있는 화면에서는
     여기서 무엇을 할 수 있는지 알려 주는 것이 커서밖에 없습니다. */
  .pdf-source-page{position:relative; width:100%; background:var(--source-page);
    box-shadow:var(--source-shadow); overflow:hidden; isolation:isolate; cursor:pointer;}
  .pdf-source-page canvas{position:absolute; inset:0; display:block; width:100%!important; height:100%!important;}
  .pdf-page-loading{position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
    color:var(--source-wait); font:13px var(--ui); background:var(--source-page);}
  /* Multiply preserves dark PDF ink while retaining the existing fill colors.
     Page isolation keeps blending inside the paper, including in dark mode. */
  .pdf-source-page>.breeze-original-word{mix-blend-mode:multiply;}
  .pdf-source-page>.original-selection-marker{position:absolute; z-index:3; display:block; box-sizing:border-box;
    color:transparent; background:var(--pick-fill); border:1px solid var(--pick-line);
    border-radius:3px; pointer-events:none; overflow:hidden; white-space:nowrap;}
  .pdf-source-page>.original-selection-marker.s1{background:var(--pick1-fill); border-color:var(--pick1-line);}
  .pdf-source-page>.original-selection-marker.s2{background:var(--pick2-fill); border-color:var(--pick2-line);}
  .pdf-source-page>.original-selection-marker.s3{background:var(--pick3-fill); border-color:var(--pick3-line);}
  /* 저장한 단어는 원본에서도 글자 화면과 똑같이 블록으로 칠합니다.
     밑줄·끄기 두 가지를 더 고를 수 있었지만, 설정을 위한 설정이었습니다. */
  .pdf-source-page>.original-saved-marker{position:absolute; z-index:3; display:block; box-sizing:border-box;
    color:transparent; pointer-events:none; border:0; border-radius:3px;
    overflow:hidden; white-space:nowrap;}
  .pdf-source-page>.original-saved-marker.s1{background:var(--saved1);}
  .pdf-source-page>.original-saved-marker.s2{background:var(--saved2);}
  .pdf-source-page>.original-saved-marker.s3{background:var(--saved3);}
  .pdf-source-page>.reader-mode-cue{position:absolute; z-index:2; display:block; pointer-events:none;
    box-sizing:border-box; border-radius:4px;
    background:var(--cue-block); animation:reader-mode-cue-out 6s ease forwards;}
  @keyframes reader-mode-cue-out{0%,58%{opacity:1}100%{opacity:0}}

  .epub-original{display:flex; flex-direction:column; gap:20px;}
  .epub-source-chapter{width:100%; background:var(--source-page); box-shadow:var(--source-shadow-soft); overflow:hidden;
    position:relative;}
  .epub-chapter-frame{display:block; width:100%; min-height:80px; border:0; background:var(--source-page);}
  /* ---- 장 위에 덮는 살갗 ----
     책은 대본을 못 돌게 막은 iframe 이고, 그 한 마디 때문에 iOS 는 그 문서로
     입력을 아예 배달하지 않습니다(까닭과 잰 값은 scripts/reader/epub-original.js).
     그래서 손가락은 우리 문서의 이 빈 겹이 받습니다. 틀과 같은 자리를 덮으므로
     장이 자라면 함께 자랍니다.

     `user-select:none` 은 여기 **살갗에** 답니다 — 책의 글자에 달면 caret 이
     함께 죽습니다. 고를 글자가 없는 빈 상자를 꾹 누르면 iOS 가 상자 전체를
     골라 버리는 것은 스캔본 종이와 낱말 시트 바깥에서 이미 겪은 그 버릇입니다.
     배경은 투명하고 자리도 차지하지 않으므로 그림에는 아무 일도 없습니다.

     책 안의 글에는 `cursor:pointer` 가 붙어 있지만(위 `safety`), 마우스가 닿는
     것은 그 글이 아니라 이 살갗입니다 — 그래서 데스크톱에서 본문 위의 커서가
     화살표로 남았습니다. "여기를 누르면 뜻이 뜬다"를 커서가 말해 주지 못하면
     원본 화면만 다른 앱처럼 보입니다. 살갗이 손가락의 임자이므로 커서의 임자도
     살갗입니다. 스캔본 종이(`.pdf-source-page`)가 쪽 전체에 같은 커서를 다는
     것과 같은 규칙이고, 손짓 판정에는 아무것도 더하지 않습니다. */
  .epub-touch-skin{position:absolute; inset:0; background:transparent; cursor:pointer;
    -webkit-user-select:none; user-select:none; -webkit-touch-callout:none;
    -webkit-tap-highlight-color:transparent;}

  @media(max-width:760px){
    /* 좌우 여백은 확대되는 층 안쪽으로 내려갑니다 — 바깥이 폭을 정하면 벌릴 때
       종이의 왼쪽 끝이 움직여서 손가락 아래를 붙들 기준이 사라집니다. */
    #originalwrap{padding:calc(env(safe-area-inset-top) + 24px) 0 45vh;}
    .original-content{padding:0 6px;}
    .pdf-original{gap:10px;}
    .original-empty{margin:6vh 10px 0; padding:34px 22px;}
  }
  @media(prefers-reduced-motion:reduce){
    #readwrap,#originalwrap{transition:none;}
    .pdf-source-page>.reader-mode-cue{animation:none;}
  }

/* Shared completion treatment for the Reader and Home resume capsule. */
.completion-badge{position:relative;z-index:1;display:flex;align-items:center;gap:4px;flex:none;font:600 11px var(--ui);white-space:nowrap;}
.completion-badge[hidden]{display:none;}
.completion-badge svg{width:22px;height:22px;color:var(--completion-blue);flex:none;}
#home-controls #primary-nav .completion-badge svg{width:22px;height:22px;stroke:none;}
.is-complete .completion-badge{animation:completion-reveal .55s cubic-bezier(.2,.8,.2,1);}
body.sentence-pill-waiting #readpill .completion-badge{display:none;}
@keyframes completion-reveal{0%{opacity:0;transform:scale(.35) rotate(-18deg)}65%{opacity:1;transform:scale(1.12) rotate(4deg)}100%{transform:scale(1) rotate(0)}}
@media(prefers-reduced-motion:reduce){.is-complete .completion-badge{animation:none;}}

/* One light material for Reader and Home. Dark mode intentionally uses the existing rules. */
body:not(.dark) .control-glass{
  border-color:var(--control-light-line);box-shadow:var(--control-light-shadow);
}
body:not(.dark) .control-glass::before{
  background:var(--control-light-reflection);box-shadow:var(--control-light-edge);
  z-index:2; /* Reflection sits above the progress tint, never beneath it. */
}
@supports ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  body:not(.dark) .control-glass{background:var(--control-light-surface);}
}
body:not(.dark) :is(#readpill-progress,#home-resume-progress){
  background:var(--control-light-progress);box-shadow:var(--control-light-progress-edge);
}
body:not(.dark) :is(#readback,#aafab,#readpill button,.control-glass):active{background:var(--chrome-press);}

/* Notices share only the title slot; mode/back/settings keep their input targets.
   The title remains in the layout and restores without rewriting book state. */
#reader-notice,#home-notice{position:absolute;inset:4px 12px;z-index:2;pointer-events:none;
  display:flex;align-items:center;justify-content:center;overflow:hidden;
  font:600 12px/1.35 var(--ui);text-align:center;overflow-wrap:anywhere;}
#reader-notice[hidden],#home-notice[hidden]{display:none;}
body.home-notice-visible #home-resume .home-resume-copy{opacity:0;}
body.home-notice-visible #home-resume .completion-badge{visibility:hidden;}
body.reader-notice-visible #readpill-title{opacity:0;}
body.reader-notice-visible #readpill .completion-badge{visibility:hidden;}
body.reader-notice-visible #readpill:has(#modefab:not([hidden])) #reader-notice{left:48px;}
body.reader-notice-visible.chrome-hidden #readpill{width:min(56vw,400px);height:44px;}
body.reader-notice-visible.chrome-hidden #readpill #reader-notice{left:12px;}
body.sentence-pill-waiting #reader-notice{display:none;}

/* Imported semantic blocks use Breeze typography, never publisher CSS. */
#rtext .article-list-item{padding-inline-start:1.4em;position:relative}
#rtext .article-list-item::before{content:attr(data-marker);position:absolute;inset-inline-start:0;opacity:.65}
#rtext .article-caption{font-size:.8em;opacity:.7}
#rtext .article-table-row{font-family:monospace;overflow-wrap:anywhere}
#rtext .article-links{display:flex;flex-wrap:wrap;gap:.5em 1em;font-size:.7em;margin:-.5em 0 1.4em}
#rtext .article-links a{color:inherit;text-decoration:underline;overflow-wrap:anywhere}
