/* ============================================================================
   Gass Bilingual Reader — reader.css
   Epic 1: ch05 vertical slice.
   Typography follows Bringhurst-school rules (R2/TC-003/TC-010/TC-011/TC-012).
   ============================================================================ */

/* --- Design tokens (theme-driven) --- */
:root {
  --font-serif: "Literata", "PT Serif", "Cormorant", Georgia, serif;
  --font-mono: ui-monospace, "SF Mono", Menlo, monospace;
  --font-size: 18px;

  /* Chinese (zh) text — Songti/Noto Serif SC subset, self-hosted per book in
     fonts/ (operator decision via font pilot 2026-09-07: variant 2 Songti).
     url() resolves against the page URL (CSS is embedded), so each book
     carries its own subset under <slug>/fonts/. */
  --font-zh: "Noto Serif SC", "Songti SC", "STSong", 宋体, serif;
}

/* Scoped to zh-marked text only; other-language books never fetch these. */
[lang="zh"] { font-family: var(--font-zh); }

@font-face {
  font-family: "Noto Serif SC";
  src: url("fonts/noto-serif-sc-regular.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Noto Serif SC";
  src: url("fonts/noto-serif-sc-bold.woff2") format("woff2");
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Noto Serif SC";
  src: url("fonts/noto-serif-sc-bold.woff2") format("woff2");
  font-weight: 700; font-style: normal; font-display: swap;
}

  /* Day theme (default) */
  --bg: #fbf7ef;
  --fg: #1f1d1a;
  --fg-muted: #6a645b;
  --accent: #6b4f1d;
  --hover-bg: rgba(107, 79, 29, 0.08);
  --hover-fg: #1f1d1a;
  --partner-bg: rgba(107, 79, 29, 0.04);
  --pin-bg: rgba(192, 84, 22, 0.14);
  --pin-bar: #c05416;
  --partner-pin-bg: rgba(192, 84, 22, 0.08);
  --focus-ring: #2563a8;
  --rule: rgba(31, 29, 26, 0.12);
}

/* Sepia theme */
[data-theme="sepia"] {
  --bg: #f0e6d2;
  --fg: #3a2a14;
  --fg-muted: #7a6242;
  --accent: #6e4a1a;
  --hover-bg: rgba(110, 74, 26, 0.12);
  --hover-fg: #2a1d0f;
  --partner-bg: rgba(110, 74, 26, 0.06);
  --pin-bg: rgba(170, 70, 14, 0.18);
  --pin-bar: #aa460e;
  --partner-pin-bg: rgba(170, 70, 14, 0.10);
  --focus-ring: #6e4a1a;
  --rule: rgba(58, 42, 20, 0.16);
}

/* Green theme (Kindle “Page Color” green — operator 2026-08-22) */
[data-theme="green"] {
  --bg: #bcd6bf;
  --fg: #25382b;
  --fg-muted: #4f6355;
  --accent: #2e5238;
  --hover-bg: rgba(46, 82, 56, 0.12);
  --hover-fg: #142017;
  --partner-bg: rgba(46, 82, 56, 0.06);
  --pin-bg: rgba(46, 120, 70, 0.18);
  --pin-bar: #2e7846;
  --partner-pin-bg: rgba(46, 120, 70, 0.10);
  --focus-ring: #2e5238;
  --rule: rgba(37, 56, 43, 0.16);
}

/* Night theme */
[data-theme="night"] {
  --bg: #1b1b1f;
  --fg: #e7e3da;
  --fg-muted: #9a948a;
  --accent: #d9c07a;
  --hover-bg: rgba(217, 192, 122, 0.14);
  --hover-fg: #fff;
  --partner-bg: rgba(217, 192, 122, 0.06);
  --pin-bg: rgba(217, 122, 80, 0.20);
  --pin-bar: #d97a50;
  --partner-pin-bg: rgba(217, 122, 80, 0.10);
  --focus-ring: #88b5d8;
  --rule: rgba(231, 227, 218, 0.14);
}

/* Chrome frame — single authoritative block (TC-010). Mobile overrides live
   in the @media (max-width: 50em) query below. */
.chrome-frame {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 28;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  background: var(--bg);
  border-bottom: 1px solid var(--rule);
  transition: max-height .35s cubic-bezier(0.4, 0, 0.2, 1), opacity .25s ease;
  max-height: 320px;
  opacity: 1;
  overflow: hidden;
}
body.chrome-collapsed .chrome-frame {
  max-height: 0;
  opacity: 0;
  padding-top: 0;
}

/* Theme radios render a circular swatch of each theme’s page color so the
   control is self-explanatory (Kindle Page Color, operator 2026-08-22).
   Swatch values mirror each [data-theme] --bg — keep in sync when adding a theme. */
.rbs-menu .rbs-themebtn { display: inline-flex; align-items: center; justify-content: center; padding: 8px 12px; }
.rbs-menu .rbs-themebtn::before {
  content: ""; width: 1.5em; height: 1.5em; border-radius: 50%;
  background: var(--swatch); border: 1px solid var(--rule);
}
.rbs-menu .rbs-themebtn[data-t="day"]   { --swatch: #fbf7ef; }
.rbs-menu .rbs-themebtn[data-t="sepia"] { --swatch: #f0e6d2; }
.rbs-menu .rbs-themebtn[data-t="green"] { --swatch: #bcd6bf; }
.rbs-menu .rbs-themebtn[data-t="night"] { --swatch: #1b1b1f; }
/* Active theme = ring around the swatch, not a full accent fill (swatch must stay visible). */
.rbs-menu .rbs-themebtn.active { background: transparent; color: var(--fg); }
.rbs-menu .rbs-themebtn.active::before { box-shadow: 0 0 0 2px var(--focus-ring); }

/* Respect OS preference on first paint (user override wins once they pick a theme). */
/* TC-016: keep in sync with the [data-theme="night"] block above — this copy
   exists for the prefers-color-scheme/first-paint context and must mirror it. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    --bg: #1b1b1f;
    --fg: #e7e3da;
    --fg-muted: #9a948a;
    --accent: #d9c07a;
    --hover-bg: rgba(217, 192, 122, 0.14);
    --partner-bg: rgba(217, 192, 122, 0.06);
    --pin-bg: rgba(217, 122, 80, 0.20);
    --pin-bar: #d97a50;
    --partner-pin-bg: rgba(217, 122, 80, 0.10);
    --focus-ring: #88b5d8;
    --rule: rgba(231, 227, 218, 0.14);
  }
}

/* --- Reset / base --- */
* { box-sizing: border-box; }
html, body {
  margin: 0;
  padding: 0;
  height: 100vh; /* fallback first — always safe */
}
/* dvh fixes RC-4 (Android 100vh extends behind URL/gesture bars). Gate the
   dynamic-viewport lock-down behind @supports so engines without dvh (or the
   grid/flex scroll model) keep natural document scroll and still reach the
   WHOLE book — never a clipped, unscrollable page. */
@supports (height: 100dvh) {
  html, body {
    height: 100dvh;
    overflow: hidden; /* the .reader scrolls internally, not the body */
  }
}

/* --- Access gate (closed-circle consent + one-time PIN) ---
   Book-reading pages only. Reader content hidden until consent given.
   Rendered in the canonical bottom sheet (.access-gate-sheet via openSheet,
   dismissable:false — TC-017). Only content styles live here; the shell
   (overlay/card/scroll) belongs to .mobile-sheet. */
body.gate-locked .reader,
body.gate-locked .chrome-frame,
body.gate-locked .chrome-toggle,
body.gate-locked .reading-progress,
body.gate-locked .reader-crumbs,
body.gate-locked .tap-zone,
body.gate-locked .fab-cluster { display: none !important; }
.access-gate-sheet .mobile-sheet-body {
  font-family: var(--font-serif, Georgia, serif);
  color: #1f1d1a;
}
.access-gate-icon { font-size: 1.8rem; margin-bottom: 0.5rem; }
.access-gate-legal {
  font-size: 0.85rem;
  line-height: 1.55;
  color: #4a453e;
  margin: 0 0 0.75rem;
}
.access-gate-consent { font-size: 0.85rem; font-weight: 600; margin: 0 0 0.4rem; }
.access-gate-list {
  margin: 0 0 1rem;
  padding-left: 1.2rem;
  font-size: 0.85rem;
  line-height: 1.5;
  color: #4a453e;
}
.access-gate-form { margin: 0; }
.access-gate-form { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.access-gate-input {
  flex: 1;
  min-width: 8rem;
  padding: 0.6rem 0.8rem;
  font-size: 1rem;
  border: 1px solid rgba(31, 29, 26, 0.25);
  border-radius: 8px;
  background: #fbf7ef;
  color: #1f1d1a;
}
.access-gate-input:focus { outline: 2px solid #6b4f1d; border-color: transparent; }
.access-gate-btn {
  padding: 0.6rem 1rem;
  background: #6b4f1d;
  color: #fff;
  border: none;
  border-radius: 8px;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
}
.access-gate-btn:active { opacity: 0.85; }
.access-gate-error {
  margin: 0.75rem 0 0;
  font-size: 0.8rem;
  color: #a1260e;
  font-weight: 600;
}

/* --- Breadcrumb row — lives INSIDE the chrome-frame curtain (top row).
   Not a separate fixed strip: when the curtain is collapsed the crumbs hide
   with it (operator: crumbs must be PART of the nav panel, never a floating
   layer conflicting with the ≡ sandwich). --- */
.reader-crumbs {
  display: flex;
  align-items: center;
  margin: 0;
  gap: 0.35rem;
  padding: 0.25rem 3.2rem 0.25rem 0.6rem; /* right padding reserves space for ≡ */
  font-size: 0.75rem;
  font-family: var(--font-serif);
  color: var(--fg-muted);
  border-bottom: 1px solid var(--rule);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.reader-crumbs a {
  color: var(--accent);
  text-decoration: none;
  font-weight: 500;
  white-space: nowrap;
}
.reader-crumbs a:hover { text-decoration: underline; }
.reader-crumbs .crumb-home { font-size: 0.95rem; }
.reader-crumbs .crumb-sep { color: var(--rule); font-size: 0.7rem; }
.reader-crumbs .crumb-current { color: var(--fg-muted); font-weight: 400; overflow: hidden; text-overflow: ellipsis; }
/* On mobile, keep it compact */
@media (max-width: 50em) {
  .reader-crumbs { font-size: 0.7rem; padding: 0.15rem 0.4rem; }
  .reader-crumbs .crumb-current { max-width: 8rem; }
}
body {
  background: var(--bg, #fbf7ef);
  color: var(--fg, #1f1d1a);
  font-family: var(--font-serif, Georgia, serif);
  font-size: var(--font-size, 1.05rem);
  line-height: 1.65;
  font-feature-settings: "kern" 1, "liga" 1, "onum" 1;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  display: flex;
  flex-direction: column;
}

/* --- Reader chrome --- */
.reader-header {
  margin: 0 auto;
  padding: 3rem 1.5rem 1.5rem;
  text-align: center;
}
.reader-kicker {
  margin: 0 0 0.5rem;
  font-size: 0.85rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--fg-muted);
}
.reader-title {
  font-size: 1.9rem;
  font-weight: 500;
  margin: 0 0 0.25rem;
  letter-spacing: -0.01em;
}
.reader-title [lang="ru"] {
  font-style: italic;
  font-weight: 400;
  color: var(--fg-muted);
}
.reader-meta {
  margin: 0;
  font-size: 0.85rem;
  color: var(--fg-muted);
}

/* --- Two-column reader layout ---
   Pure dynamic weighting: grid is `1fr 1fr`, no fixed floor or ceiling.
   The viewport decides the per-column measure; below the collapse breakpoint
   we drop to a single column so neither side becomes unreadable. */
.reader {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
  margin: 0 auto;
  padding: 1rem 1.5rem 0;  /* bottom padding is in .column — no wasted space */
  column-gap: 3rem;
  flex: 1;            /* take all remaining vertical space (H8 — maximize text) */
  min-height: 0;      /* critical for flex children that scroll internally */
  overflow: hidden;
}

.column {
  min-width: 0;
  overflow-y: auto;
  padding-bottom: 1rem;  /* breathing room at the bottom of the scroll area */
  /* No CSS scroll-behavior: JS animateScroll() provides iOS-momentum easing. */
  /* Shared baseline grid (TC-011) — both columns share line-height + spacing. */
}

.column-label {
  font-size: 0.8rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg-muted);
  font-weight: 500;
  margin: 0 0 1.5rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--rule);
}

/* --- Newspaper headline (Ep07 Aeolus unique formatting) ---
   ALL-CAPS section headers that precede short paragraphs, mimicking
   the newspaper layout Joyce used in the original edition. */
.headline {
  font-size: 0.85em;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-align: center;
  text-indent: 0;
  margin: 2.2em 0 1.2em;
  color: var(--fg);
  line-height: 1.4;
}
.headline:first-of-type { margin-top: 0; }
.headline-empty { min-height: 1em; }

.paragraph {
  margin: 0 0 1.4em; /* paragraph spacing — clearly visible break between paragraphs */
  text-indent: 1.5em;
  /* Left gutter so the pin accent-bar (inset 3px on .is-pinned) never sits on
     top of the text. Bar lives in this gutter; text never reflows on pin. */
  padding-left: 1.5rem;
}
.paragraph:first-of-type { text-indent: 0; }

/* The first paragraph after a column label starts flush. */
.column > .paragraph:first-of-type { margin-top: 0; }

/* --- Epigraph (paragraph-level type='epigraph') ---
   Operator: "this is a quote at the front of the chapter, separate from the flow"
   Visual: large centred opening quote, indented italic verse, separated from body. */
.epigraph {
  margin: 0 0 2rem;
  padding: 0;
  text-indent: 0;
  position: relative;
  border-bottom: 1px solid var(--rule);
  padding-bottom: 1.5rem;
}
.epigraph-mark {
  display: block;
  font-family: var(--font-serif);
  font-size: 3rem;
  line-height: 1;
  font-style: italic;
  font-weight: 500;
  color: var(--fg-muted);
  text-align: center;
  margin: 0 0 0.5rem;
  user-select: none;
}
.epigraph .sentence {
  display: block;
  font-style: italic;
  font-size: 0.95em;
  color: var(--fg);
  padding-left: 2rem;
  padding-right: 2rem;
  text-align: left;
}
/* In poetry lines, keep line-height tighter than prose */
.epigraph .poem-line,
.poem .poem-line {
  display: block;
}

/* --- Generic poem block (for in-body verse like Margaret, Borges, etc.) --- */
.poem {
  margin: 1.5rem 0;
  padding: 0.5rem 1.5rem 0.5rem 1.5rem; /* symmetric horizontal padding so the right edge breathes like the left */
  border-left: 3px solid var(--rule);
  font-style: italic;
  font-size: 0.95em;
  color: var(--fg);
}
.poem .sentence,
.poem .poem-line {
  display: block;
}

/* --- Enumeration block (labelled a./b./c./d. lists, like Gass's
   "organizing principles of lists" in ch05). Indented block, each
   lettered item on its own visual line, lead-in and coda flow inline. --- */
.enumeration {
  margin: 1.4em 0;
  padding-left: 2em;     /* gutter for the a./b./c./d. labels */
}
/* Each item gets its own line. Items indent by 2em so wrapped lines
   align under the text (NOT under the letter label). The letter label
   is at the start of the line, in the gutter.
   No hanging indent — avoids column-overflow clipping. */
.enumeration .sentence {
  display: block;
  margin-left: 2em;
  text-indent: 0;
}
/* Lead-in: first sentence — flush with the block's left edge, no indent */
.enumeration > .sentence:first-of-type {
  margin-left: 0;
  margin-bottom: 0.4em;
}
/* Coda: last sentence — flush with the block's left edge */
.enumeration > .sentence:last-of-type {
  margin-left: 0;
  margin-top: 0.4em;
}
/* Letter labels (a./b./c./d.) — bold so they read as list markers,
   not as part of the prose flow. */
.enumeration .enum-label {
  font-weight: 700;
  margin-right: 0.3em;
}

/* --- Sentences --- */
.sentence {
  cursor: pointer;
  border-radius: 2px;
  padding: 0 1px;       /* tiny breath so highlight rect isn't cramped */
  margin: 0 -1px;
  transition: background-color 120ms ease, color 120ms ease;
  /* contain-intrinsic-size keeps scrollbar stable under content-visibility (TC-029) */
  content-visibility: auto;
  contain-intrinsic-size: auto 1.65em;
}

/* Space between adjacent sentences inside a paragraph. */
.sentence + .sentence::before { content: " "; }

/* --- Glossary annotated proper names (H6 Recognition) ---
   Only the FIRST occurrence of a term is underlined (.glossary-first); later
   occurrences stay plain, tappable prose. Iron rule: underline a tessera at
   its first mention only, never after. Hover tint still marks every term. */
.glossary-term {
  cursor: help;
  color: inherit;
  font-style: inherit;
  border-radius: 2px;
  padding: 0 1px;
  transition: background-color 120ms ease;
}
.glossary-term.glossary-first {
  border-bottom: 1px dotted var(--accent);
}
.glossary-term:hover {
  background: var(--hover-bg);
}
.glossary-term:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

/* --- Glossary modal (H6 — context in-place, not alt-tab to Wikipedia) --- */
/* Glossary / tessera card — rendered inside the unified bottom sheet
   (.mobile-sheet.glossary-sheet) via openSheet() (TC-004). The shell
   (overlay/handle/close/drag) is canonical; only CONTENT styles live here.
   Desktop presents the same sheet as a centered card via the sheet media query. */

/* Tessera image (optional, e.g. 1987 Count Chocula box). */
.glossary-modal-figure {
  margin: 0 0 1rem 0;
  padding: 0;
  text-align: center;
}
.glossary-modal-img {
  max-width: 100%;
  max-height: 40vh;
  border-radius: 6px;
  border: 1px solid var(--rule);
  object-fit: contain;
}
.glossary-modal-caption {
  margin-top: 0.4rem;
  font-size: 0.8rem;
  color: var(--fg-muted);
  font-family: var(--font-sans, system-ui, sans-serif);
  line-height: 1.4;
}

/* Tessera audio player (optional, e.g. "So Lonesome I Could Cry"). */
.glossary-modal-audio {
  display: block;
  width: 100%;
  max-width: 28rem;
  margin: 0 auto 1rem;
  height: 2.4rem;
}

/* Term name renders as the core .mobile-sheet-title — accent italic style. */
.glossary-sheet .mobile-sheet-title {
  font-size: 1.3rem;
  font-weight: 500;
  color: var(--accent);
  font-style: italic;
  font-family: var(--font-serif);
}

.glossary-sheet .mobile-sheet-body {
  font-size: 0.95rem;
  text-align: justify;
  hyphens: auto;
}
.glossary-sheet .mobile-sheet-body p {
  margin: 0 0 0.85rem;
}
.glossary-sheet .mobile-sheet-body p:last-child {
  margin-bottom: 0;
}
.glossary-sheet .glossary-article-link {
  display: block;
  margin: 12px 0 0;
  padding: 10px 12px;
  text-align: center;
  border: 1px solid var(--rule, rgba(0,0,0,.18));
  border-radius: 10px;
  color: var(--accent);
  font-size: .95rem;
  text-decoration: none;
}

/* Hover (transient) — source + partner both lit.
   Applies to BOTH .paragraph (new books, paragraph-level) and
   .sentence (legacy books, sentence-level). */
.paragraph.is-hover, .sentence.is-hover {
  background: var(--hover-bg);
  color: var(--hover-fg);
}
.paragraph.is-partner-hover, .sentence.is-partner-hover {
  background: var(--partner-bg);
}

/* Pin (persistent) — stronger, with left bar accent. */
.paragraph.is-pinned, .sentence.is-pinned,
.paragraph.is-partner-pinned, .sentence.is-partner-pinned {
  background: var(--pin-bg);
  box-shadow: inset 3px 0 0 var(--pin-bar);
}
.paragraph.is-partner-pinned, .sentence.is-partner-pinned {
  background: var(--partner-pin-bg);
}

/* Both pinned + hovered at once. */
.paragraph.is-pinned.is-hover, .sentence.is-pinned.is-hover {
  background: var(--pin-bg);
}

/* Paragraphs are interactive — cursor pointer + focus ring. */
.paragraph[data-pid] {
  cursor: pointer;
  border-radius: 2px;
}
.paragraph[data-pid]:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

/* Off-screen partner indicator — REMOVED in Epic 2 v2 (Nielsen H8: didn't earn
   its place in the independent-column-scroll architecture). */

/* --- Reading progress bar (H1 Visibility) --- */
.reading-progress {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 50;
  width: 100vw;
  height: 4px;
  border: none;
  background: var(--rule); /* faint track so the filled portion reads clearly */
  color: var(--pin-bar);   /* strong accent (the same orange used for pin bars) */
  pointer-events: none; /* never block clicks */
}
.reading-progress::-webkit-progress-bar {
  background: var(--rule);
}
.reading-progress::-webkit-progress-value {
  background: var(--pin-bar);
  transition: width 80ms linear;
}
.reading-progress::-moz-progress-bar {
  background: var(--pin-bar);
}

/* --- Floating action cluster (H7: copy link / back to top) --- */
.fab-cluster {
  position: fixed;
  bottom: 1.5rem;
  right: 1.5rem;
  z-index: 20;
  display: flex;
  flex-direction: column;
  margin: 0;
  gap: 0.5rem;
  align-items: flex-end;
}
.fab {
  width: 2.4rem;
  height: 2.4rem;
  border-radius: 50%;
  border: 1px solid var(--rule);
  background: var(--bg);
  color: var(--fg);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 1px 4px rgba(0,0,0,0.08);
  transition: background-color 120ms ease, transform 120ms ease, opacity 120ms ease;
  display: flex;
  align-items: center;
  justify-content: center;
}
.fab:hover { background: var(--hover-bg); transform: scale(1.05); }
.fab[hidden] { display: none; }
.fab.copied-flash {
  background: var(--accent);
  color: var(--bg);
}

/* --- Skip link (H4 standard a11y pattern) --- */
.skip-link {
  position: absolute;
  top: -100px;
  left: 1rem;
  z-index: 100;
  background: var(--accent);
  color: var(--bg);
  padding: 0.6rem 1rem;
  border-radius: 4px;
  text-decoration: none;
  font-size: 0.9rem;
  /* No transition — the link must appear instantly on focus for keyboard users. */
}
.skip-link:focus {
  top: 1rem;
}

/* --- Collapsible chrome (H8 Minimalist) --- */
.chrome-toggle {
  position: fixed;
  top: 0.5rem;
  right: 0.5rem;
  z-index: 30;
  width: 2.2rem;
  height: 2.2rem;
  border: 1px solid var(--rule);
  background: var(--bg);
  color: var(--fg);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  border-radius: 4px;
  box-shadow: 0 1px 4px rgba(0,0,0,0.08);
  transition: background-color 120ms ease;
}
.chrome-toggle:hover { background: var(--hover-bg); }

/* --- Fullscreen reading mode (operator 2026-08-23) ---
   Distraction-free: hide every chrome element so only the book text shows.
   100dvh (RC-4) + safe-area so the reading column fills the real viewport. */
body.fullscreen-reading .chrome-frame,
body.fullscreen-reading .chrome-toggle,
body.fullscreen-reading .quick-actions,
body.fullscreen-reading .quick-lang-btn,
body.fullscreen-reading .rbs-pill,
body.fullscreen-reading .rbs-ribbon,
body.fullscreen-reading .audio-pill { display: none !important; }
body.fullscreen-reading { background: var(--bg); }

/* Barely-visible exit glyph, top-right. Transparent until touched/hovered,
   so it never competes with the text; a visible affordance is still present
   (Nielsen: every gesture needs a visible alternative — the menu switch also
   toggles fullscreen). */
#rbs-fs-exit {
  position: fixed;
  top: 0.4rem;
  right: 0.5rem;
  z-index: 40;
  width: 2rem;
  height: 2rem;
  border: none;
  background: transparent;
  color: var(--fg-muted);
  font-size: 0.9rem;
  line-height: 1;
  cursor: pointer;
  border-radius: 4px;
  opacity: 0.18;               /* barely visible at rest */
  transition: opacity 150ms ease, background-color 120ms ease;
}
#rbs-fs-exit:hover, #rbs-fs-exit:focus { opacity: 0.9; background: var(--hover-bg); }
/* Keep the exit glyph tappable on touch even at low opacity. */
@media (pointer: coarse) { #rbs-fs-exit { opacity: 0.28; width: 2.6rem; height: 2.6rem; } }

/* Mobile curtain (2026-08-12, operator directive): the chrome-frame becomes a
   FIXED overlay drawer sliding from the top — a physical blind that COVERS the
   reading page. The reading geometry NEVER reflows when it opens/closes, and
   when collapsed NOTHING occupies the top: the page is full-bleed with equal
   4-side margins (Kindle model). Breadcrumbs live inside the drawer. */
@media (max-width: 50em) {
  :root {
    --page-margin: 1.1rem;
    --page-margin: clamp(0.9rem, 5vw, 1.4rem);
  }
  .chrome-frame {
    max-height: 236px;
    overflow-y: auto;
    box-shadow: 0 8px 24px rgba(0,0,0,0.18);
    padding: calc(var(--page-margin) * .6) var(--page-margin)
             calc(var(--page-margin) * .6 + 0px);
    padding: calc(var(--page-margin) * .6) var(--page-margin)
             calc(var(--page-margin) * .6 + env(safe-area-inset-bottom, 0px));
    padding-top: calc(var(--page-margin) * .6 + 0px);
    padding-top: calc(var(--page-margin) * .6 + env(safe-area-inset-top, 0px));
  }
  body.chrome-collapsed .chrome-frame {
    overflow: hidden;
    box-shadow: none;
  }
  /* Reading page owns the full viewport; margins come from .column only. */
  .reader { padding: 0; }
  .column {
    padding: var(--page-margin);
    /* bottom = margin + home-indicator safe area (RC-4 bottom clipping) */
    padding-bottom: calc(var(--page-margin) + 0px);
    padding-bottom: calc(var(--page-margin) + env(safe-area-inset-bottom, 0px));
  }
  /* No asymmetric left gutter on mobile — the pin accent sits inside the
     equal margin instead, so left == right. */
  .paragraph { padding-left: 0; }
}

/* --- Reader toolbar (theme switch, layout toggle) --- */
.reader-toolbar {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  justify-content: center;
  padding: 0.5rem 1rem 0.5rem 1rem;
  /* Reserve space for fixed .chrome-toggle (≡) on the right */
  margin-right: 2.7rem;
  background: var(--bg);
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--rule);
}
.reader-toolbar button {
  font: inherit;
  font-size: 0.85rem;
  padding: 0.35rem 0.75rem;
  background: transparent;
  color: var(--fg);
  border: 1px solid var(--rule);
  border-radius: 4px;
  cursor: pointer;
}
.reader-toolbar button:hover { background: var(--hover-bg); }
.reader-toolbar button[aria-pressed="true"] {
  background: var(--accent);
  color: var(--bg);
  border-color: var(--accent);
}
/* Theme cycle button — single icon (☀◐☾) replaces Day/Sepia/Night trio */
.reader-toolbar .theme-cycle-btn {
  font-size: 1.1rem;
  line-height: 1;
  min-width: 2rem;
}
/* Home breadcrumb — escape hatch back to the book index (H3 User Control). */
.reader-toolbar .toolbar-home-btn {
  font-size: 0.95rem;
  line-height: 1;
  padding: 0.3rem 0.5rem;
  text-decoration: none;
  color: var(--fg-muted);
  border: 1px solid transparent;
  border-radius: 4px;
  transition: color 120ms ease, border-color 120ms ease;
}
.reader-toolbar .toolbar-home-btn:hover {
  color: var(--accent);
  border-color: var(--rule);
}

/* --- Vertical layout (portrait / vertical-monitor reading, R1) --- */
[data-layout="vertical"] .reader {
  grid-template-columns: 1fr;
  max-width: 38em;
}
[data-layout="vertical"] .column {
  min-width: 0;
  max-width: none;
}
[data-layout="vertical"] .column + .column {
  margin-top: 3rem;
  padding-top: 2rem;
  border-top: 1px solid var(--rule);
}

/* --- Chapter summary (collapsible) --- */
.chapter-summary {
  max-width: 72rem;
  margin: 0 auto 1.5rem;
  padding: 0 1.5rem;
}
.chapter-summary-toggle {
  font: inherit;
  font-size: 0.9rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--fg-muted);
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 4px;
  padding: 0.5rem 1rem;
  cursor: pointer;
  transition: background-color 120ms ease;
  list-style: none;
}
.chapter-summary-toggle::-webkit-details-marker { display: none; }
.chapter-summary-toggle::before {
  content: "▸ ";
  font-family: var(--font-mono);
  font-size: 0.8em;
}
.chapter-summary[open] .chapter-summary-toggle::before {
  content: "▾ ";
}
.chapter-summary-toggle:hover {
  background: var(--hover-bg);
}
.chapter-summary-content {
  margin-top: 1rem;
  padding: 1.25rem 1.5rem;
  background: var(--hover-bg);
  border-radius: 6px;
  font-size: 0.95rem;
  line-height: 1.6;
}
.chapter-summary-content p {
  margin: 0 0 0.75rem;
}
.chapter-summary-content p:last-child {
  margin-bottom: 0;
  font-style: italic;
  color: var(--fg-muted);
}

/* --- Font size label --- */
.font-size-label {
  font-size: 0.85rem;
  min-width: 3em;
  text-align: center;
  color: var(--fg-muted);
  font-variant-numeric: tabular-nums;
}

/* --- Index page --- */
.reader-index ul {
  list-style: none;
  padding: 0;
}
.reader-index a {
  color: var(--accent);
  text-decoration: none;
  font-size: 1.1rem;
}
.reader-index a:hover { text-decoration: underline; }

/* --- Reduced motion (TC-024) --- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition: none !important;
    animation: none !important;
    scroll-behavior: auto !important;
  }
}

/* --- Print --- */
@media print {
  .reader-toolbar { display: none; }
  .reader { grid-template-columns: 1fr 1fr; }
  .sentence { background: none !important; box-shadow: none !important; }
}

/* --- Unified bottom sheet («шторка») — CANONICAL modal surface.
     Contract: docs/bottom-sheet-contract.md. Base styles are GLOBAL (the same
     component presents as a bottom sheet on mobile and as a centered card on
     desktop, e.g. glossary/overview). Shell DOM is built ONLY by openSheet()
     in reader/module/src/70-overlays.js. --- */
.mobile-sheet-overlay {
  position: fixed;
  top: 0; right: 0; bottom: 0; left: 0;
  z-index: 260; /* above the audio pill (250): desktop cards cover the docked pill */
  background: rgba(0,0,0,0.3);
  -webkit-backdrop-filter: blur(1px);
  backdrop-filter: blur(1px);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  opacity: 0;
  transition: opacity 300ms ease;
}
.mobile-sheet-overlay.open { opacity: 1; }
.mobile-sheet {
  width: 100%;
  max-width: 38em;
  max-height: 85vh;
  overflow-y: auto;
  background: var(--bg, #fff);
  border-top: 3px solid var(--pin-bar, #c05416);
  border-radius: 16px 16px 0 0;
  padding: 1.5rem 1.2rem calc(1.5rem + 0px);
  padding: 1.5rem 1.2rem calc(1.5rem + env(safe-area-inset-bottom, 0));
  box-shadow: 0 -4px 24px rgba(0,0,0,0.12);
  transform: translateY(100%);
  transition: transform 350ms cubic-bezier(0.32, 0.72, 0, 1);
  position: relative;
}
.mobile-sheet-overlay.open .mobile-sheet {
  transform: translateY(0);
}
.mobile-sheet-grip {
  position: relative;
  touch-action: none; /* the grip owns vertical touch — no page scroll fight */
  margin: -0.9rem -0.4rem 0;
  padding: 0.4rem 0.4rem 0;
}
.mobile-sheet-handle {
  width: 42px; height: 4px; border-radius: 2px;
  background: var(--rule, rgba(0,0,0,.2));
  margin: 0 auto 0.7rem;
}
.mobile-sheet-title { margin: 0 2.2rem 0.7rem 0; font-size: 1.05rem; }
.mobile-sheet-body { /* content flows inside .mobile-sheet's own scroll */ }
.mobile-sheet-close {
  position: absolute;
  top: 0.6rem;
  right: 0.8rem;
  width: 2rem;
  height: 2rem;
  border: none;
  background: var(--hover-bg, #f0ede5);
  color: var(--fg-muted, #999);
  font-size: 1.3rem;
  line-height: 1;
  border-radius: 50%;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1;
}
.mobile-sheet-close:hover { background: var(--accent, #6b4f1d); color: #fff; }

/* Desktop: the SAME component presents as a centered card (glossary,
   overview). Mobile-only sheets never render there (isMobile gates). */
@media (min-width: 50.01em) {
  .mobile-sheet-overlay { align-items: center; }
  .mobile-sheet {
    border-radius: 16px;
    max-width: 32rem;
    padding-bottom: 1.5rem;
  }
  .mobile-sheet-grip { cursor: default; }
}

/* --- Responsive (≤50em): MOBILE SINGLE-LANGUAGE MODE (Nielsen H8 Minimalism).
     Instead of stacking both language columns (two separate scroll areas = bad
     mobile UX), show ONE language full-screen. Tap a sentence → its translation
     appears inline (accordion). ⇄ FAB swaps which language is primary.
     Toolbar HIDDEN on mobile — 8 buttons wrapping to 6 rows wastes 40% of
     viewport. Theme/font/layout controls are desktop-only; mobile is reading. --- */
@media (max-width: 50em) {
  .reader-toolbar { display: none !important; }

  .reader {
    grid-template-columns: 1fr;
    max-width: 38em;
  }
  .column { min-width: 0; max-width: none; }

  /* Compact header on mobile — shrink title + reduce padding (H8 Minimalism) */
  .reader-header { padding: 1rem 1rem 0.5rem; }
  .reader-title { font-size: 1.4rem; margin-bottom: 0.1rem; }
  .reader-kicker { margin-bottom: 0.25rem; font-size: 0.75rem; }
  .reader-meta { font-size: 0.75rem; }

  /* Hide translation column by default (source is primary).
     Gass fallback: [data-column="ru"] for pages without data-role. */
  .column[data-role="translation"],
  .column[data-column="ru"] {
    display: none;
  }

  /* When swapped to translation-primary, flip visibility */
  body[data-mobile-primary="translation"] .column[data-role="source"],
  body[data-mobile-primary="translation"] .column[data-column="en"] {
    display: none;
  }
  body[data-mobile-primary="translation"] .column[data-role="translation"],
  body[data-mobile-primary="translation"] .column[data-column="ru"] {
    display: block;
  }

  /* Bottom sheet base styles moved to GLOBAL scope (unified sheet contract,
     2026-08-21): the same component is a bottom sheet here and a centered
     card on desktop. Only mobile-specific content styles remain below. */
  .mobile-sheet-role {
    display: inline-block;
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    padding: 0.2em 0.55em;
    border-radius: 4px;
    margin-bottom: 0.6rem;
    line-height: 1;
  }
  .role-translation { background: var(--accent, #6b4f1d); color: #fff; }
  .role-original  { background: var(--hover-bg, #f0ede5); color: var(--fg-muted, #777); }
  .mobile-sheet-text {
    margin: 0;
    padding-right: 2.5rem;
    font-size: 1rem;
    color: var(--fg, #333);
    line-height: 1.65;
    font-weight: 500;
  }
  /* "Continue reading in this language" — contextual language switch inside
     the sheet. The modal is high-priority (above tap zones), so this never
     conflicts with page-flip navigation. */
  .mobile-sheet-audio {
  display: flex; align-items: center; justify-content: center; gap: .45rem;
  margin: 10px 0 8px; padding: 11px 14px; width: 100%;
  border: 1px solid var(--accent, #6b4f1d); border-radius: 10px;
  background: transparent; color: var(--accent, #6b4f1d);
  font-size: .92rem; font-weight: 600; cursor: pointer;
}
.mobile-sheet-audio:disabled { opacity: .45; cursor: default; }
.mobile-sheet-audio.is-playing {
  background: var(--accent, #6b4f1d);
  color: #fff;
}
.mobile-sheet-continue {
    display: block;
    width: 100%;
    margin-top: 1rem;
    padding: 0.65rem 1rem;
    background: var(--accent, #6b4f1d);
    color: #fff;
    border: none;
    border-radius: 8px;
    font-size: 0.95rem;
    font-weight: 600;
    cursor: pointer;
    transition: opacity 0.15s;
  }
  .mobile-sheet-continue:active { opacity: 0.85; }

  /* Tapped sentence highlight in mobile mode */
  .sentence.mobile-active {
    background: var(--pin-bg);
    box-shadow: inset 3px 0 0 var(--pin-bar);
    border-radius: 2px;
  }

  /* Mobile reading settings sheet (⚙): font size / alignment / hyphenation */
  .settings-sheet { padding: 1.25rem 1.25rem 1.5rem; }
  .settings-title {
    margin: 0 0 1rem;
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--fg, #333);
    padding-right: 2.5rem;
  }
  .settings-row {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.75rem 0;
    border-top: 1px solid var(--border, rgba(0,0,0,0.08));
  }
  .settings-label {
    font-size: 0.85rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--fg-dim, #777);
  }
  /* Permanent one-line help under a settings row (Nielsen H10) — survives the
     one-time toast, which can be missed. First user: volume-keys pagination. */
  .settings-caption {
    font-size: 0.74rem;
    line-height: 1.35;
    color: var(--fg-dim, #888);
    margin-top: -0.25rem;
    padding-bottom: 0.5rem;
  }
  /* Corrected-edition marker in the «Книга» settings row (TC-204). */
  .book-update-dot { color: var(--accent, #6b4f1d); font-size: .6rem; vertical-align: middle; margin-left: .25rem; }
  /* Same signal projected onto the ⚙ gear (adversarial Nielsen F1): a happy
     reader never opens settings — the entry point must carry the state. */
  .book-update-dot-gear { position: absolute; top: 4px; right: 4px; margin: 0; pointer-events: none; }
  /* Primary action styling for the update buttons (Nielsen F3): matches the
     fs-offer-go accent convention for do-now vs defer decision shapes. */
  .book-update-go { background: var(--accent, #6b4f1d); color: var(--bg, #fff); }
  /* Fullscreen launch offer (TC-103) — honest, one-tap, reversible. */
  .fs-offer-text { font-size: .95rem; line-height: 1.45; margin: 0 0 .9rem; }
  .fs-offer-actions { display: flex; flex-wrap: wrap; gap: .5rem; }
  .fs-offer-actions .fs-offer-go { background: var(--accent, #6b4f1d); color: var(--bg, #fff); }
  /* iOS install instruction sheet (TC-104) */
  .ios-install-body { display: flex; gap: 1rem; align-items: flex-start; }
  .ios-install-icon { width: 64px; height: 64px; border-radius: 12px; flex: none; box-shadow: 0 2px 8px rgba(0,0,0,.25); }
  .ios-install-steps { margin: 0; padding-left: 1.2rem; font-size: .95rem; line-height: 1.5; }
  .settings-controls {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
  }
  .settings-btn {
    position: relative; /* anchor for the .book-update-dot-gear marker */
    border: 1px solid var(--border, rgba(0,0,0,0.15));
    background: var(--bg, #fff);
    color: var(--fg, #333);
    border-radius: 8px;
    padding: 0.5rem 0.9rem;
    font-size: 1rem;
    min-width: 2.75rem;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
  }
  .settings-btn:active { background: var(--hover-bg, rgba(0,0,0,0.05)); }
  .settings-toggle.active {
    background: var(--accent, #6b4f1d);
    border-color: var(--accent, #6b4f1d);
    color: #fff;
  }
  .settings-value {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--fg, #333);
    min-width: 3rem;
    text-align: center;
  }
  /* Page navigation inside settings sheet (◀ Страница ▶).
     Lets the user turn pages while adjusting settings — no modal trap. */
  .settings-page-nav {
    flex-direction: row;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
    padding: 0.5rem 0;
  }
  .settings-page-btn {
    font-size: 1.2rem;
    min-width: 2.5rem;
    padding: 0.35rem 0.7rem;
  }
  .settings-page-label {
    font-size: 0.85rem;
    color: var(--fg-muted, #777);
    font-weight: 500;
  }

  /* Kindle-style: ZERO floating FABs on mobile. Swap moved to ≡ chrome panel.
     Tap zones handle page-flip navigation (left=up, right=down). */
  .fab, .fab-cluster, .swap-lang-fab { display: none !important; }

  /* Invisible tap zones: left/right 30% = page flip, center 40% (tap-zone-mid)
     = Kindle menu toggle (added 2026-08-18 — NOT uncovered text; sentence taps
     long-press through the zones). When the chrome menu is expanded the frame
     stacks above the zones (Mode B) — menu is tappable, zones work below. */
  .tap-zone {
    position: fixed;
    top: 4rem;
    bottom: 0;
    width: 30%;
    z-index: 1;
    background: transparent;
    -webkit-tap-highlight-color: transparent;
  }
  .tap-zone-left { left: 0; }
  .tap-zone-right { right: 0; }
  /* Kindle menu zone: center 40% minus 12px dead zones at the flip boundaries
     (grip misfire protection, expert panel 2026-08-18). */
  .tap-zone-mid { left: calc(30% + 12px); width: calc(40% - 24px); }
}

/* Debug outlines (?debug-zones=1, persistent) — RED borders around ALL active
   areas (operator request): zones = red dashed, backdrop = red dotted,
   sheet = red solid. Visual only — no behavior change, no hit-testing effect. */
body.debug-zones .tap-zone-left,
body.debug-zones .tap-zone-right,
body.debug-zones .tap-zone-mid { outline: 3px dashed #ff2a1a; outline-offset: -3px; }
body.debug-zones .mobile-sheet.rbs-menu { outline: 2px solid #ff2a1a; }


/* Mode B (sandbox-validated 2026-08-09): when the chrome menu is expanded it
   stacks ABOVE the tap zones (position:relative + higher z-index). Menu buttons
   stay tappable; zones below the menu keep flipping pages (Kindle behavior).
   Taps inside the menu box never reach the zones. When collapsed, frame height
   is 0 so it covers nothing. */
@media (min-width: 50.01em) {
  .tap-zone { display: none !important; }
}

/* --- Reading typography prefs (set via ⚙ settings sheet, persisted) ---
   Justify + language-correct hyphenation. Sentences carry lang="ru|de|en",
   so hyphens:auto applies each language's own hyphen rules. */
/* Block-level targets: text-align is ignored on inline spans, and the RU
   column renders paragraphs as plain text (no .sentence spans), so both
   properties must land on the <p> itself. hyphens inherits into the EN
   sentence spans; each span's own lang picks the right dictionary. */
body[data-align="justify"] .paragraph {
  text-align: justify;
}
body[data-hyphens="auto"] .paragraph {
  -webkit-hyphens: auto;
  hyphens: auto;
  hyphenate-limit-chars: 5 3 3;
}
body[data-align="justify"][data-hyphens="off"] .paragraph {
  /* Justify without hyphenation creates rivers of whitespace —
     soften with slightly looser word spacing */
  word-spacing: 0.05em;
}
/* --- Translation attribution (slim one-liner under RU column header) --- */
/* Nielsen #8 minimalism + #6 recognition: short visible tag, full
   provenance one click away via progressive disclosure (<details>). */
.column-attribution {
  margin: 0 0 1rem;
  font-size: 0.78rem;
  line-height: 1.4;
  color: var(--fg-muted);
  font-weight: 400;
}
.column-attribution em {
  font-style: italic;
  color: var(--fg-muted);
}
.column-attribution-details {
  display: inline;
}
.column-attribution-details > summary {
  display: inline;
  list-style: none;
  cursor: help;
  color: var(--fg-muted);
  opacity: 0.7;
  padding: 0 0.2em;
  font-size: 1em;
  line-height: 1;
  vertical-align: baseline;
}
.column-attribution-details > summary::-webkit-details-marker { display: none; }
.column-attribution-details > summary:hover {
  opacity: 1;
  text-decoration: underline dotted;
}
.column-attribution-details[open] > summary {
  display: none;
}
.column-attribution-full {
  display: block;
  margin-top: 0.4rem;
  padding: 0.5rem 0.75rem;
  background: var(--hover-bg);
  border-left: 2px solid var(--rule);
  border-radius: 0 3px 3px 0;
  font-size: 0.75rem;
  line-height: 1.5;
  color: var(--fg-muted);
}

/* ============================================================================
   Resume toast (TC-003) — "Resumed at sentence N — jump to top"
   Non-blocking pill shown after progress restore. Auto-hides 4s.
   ============================================================================ */
.resume-toast {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%) translateY(8px);
  padding: 8px 14px;
  background: var(--bg);
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  color: var(--fg-muted, #555);
  font-size: 13px;
  line-height: 1.4;
  border-radius: 999px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);
  opacity: 0;
  transition: opacity 200ms ease, transform 200ms ease;
  z-index: 1000;
  pointer-events: none;
  max-width: calc(100vw - 32px);
  border: 1px solid rgba(0, 0, 0, 0.06);
}
.resume-toast.visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
  pointer-events: auto;
}
.resume-toast-jump {
  background: none;
  border: none;
  padding: 0 0 0 2px;
  margin: 0;
  font: inherit;
  color: var(--accent, #0066cc);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.resume-toast-jump:hover {
  text-decoration: none;
  opacity: 0.8;
}
@media (prefers-reduced-motion: reduce) {
  .resume-toast,
  .resume-toast.visible {
    transition: none;
    transform: translateX(-50%);
  }
}

/* sentence-counter chip REMOVED — blocked the chrome-toggle button (≡).
   Position info is already shown by .chrome-context-label when collapsed. */

/* ============================================================================
   Multi-chapter: TOC modal + auto-hide (added for unified reader)
   ============================================================================ */

/* TOC — rendered in the canonical bottom sheet (.toc-sheet via openSheet,
   TC-017). Shell (overlay/modal/close) belongs to .mobile-sheet; only the
   chapter-link content styles live here. */
.toc-ch-link{display:block;padding:.5rem .8rem;margin:.2rem 0;border-radius:4px;
 cursor:pointer;font-size:.9rem;color:var(--fg,#333);text-decoration:none;}
.toc-ch-link:hover{background:var(--accent,#6b4f1d);color:#fff;}
.toc-ch-link.current{background:rgba(107,79,29,.12);font-weight:600;}

/* Chapter overview modal (golden rule: every chapter gets a summary_ru).
   «Обзор» button on each .ch-heading opens a modal — no inline expansion
   that pushes content down. Rendered in the unified bottom sheet. */
.chapter-overview-btn{
  float:right;font-size:.65rem;font-weight:400;letter-spacing:.04em;
  color:var(--fg-muted,#999);background:transparent;border:1px solid var(--rule,#ccc);
  border-radius:3px;padding:.1rem .4rem;cursor:pointer;margin-top:.1rem;
  transition:background-color 120ms ease,color 120ms ease;}
.chapter-overview-btn:hover{background:var(--accent,#6b4f1d);color:#fff;border-color:var(--accent,#6b4f1d);}
/* Chapter overview — rendered in the unified bottom sheet (.overview-sheet)
   via openSheet() (TC-004). Shell is canonical; only the summary text styles
   live here, scoped to the sheet body. */
.overview-sheet .mobile-sheet-body p{margin:0 0 .8rem;font-size:.92rem;line-height:1.6;color:var(--fg,#333);}
.overview-sheet .mobile-sheet-body p:last-child{margin-bottom:0;}
.overview-sheet .mobile-sheet-body p[lang]{font-style:normal;}
.overview-sheet .mobile-sheet-body p.summary-ru{font-weight:500;}
.overview-sheet .mobile-sheet-body p.summary-src{color:var(--fg-muted,#777);font-style:italic;font-size:.85rem;border-top:1px solid var(--rule,#e3d9c6);padding-top:.8rem;margin-top:.8rem;}

/* Chrome frame auto-hide — natural physics (Material Design standard ease).
   cubic-bezier(0.4, 0, 0.2, 1) gives a smooth decelerate-then-settle feel
   like a physical drawer sliding shut. max-height tuned to fit all chrome
   content (toolbar + header + nav) without clipping. */
/* Nav bar inside chrome-frame.
   Right padding reserves space for the fixed .chrome-toggle (≡) button
   (2.2rem wide + 0.5rem right offset ≈ 2.7rem) so nav buttons never
   slide under it on narrow screens. */
.nav-bar{margin:0;display:flex;gap:.5rem;justify-content:center;padding:.4rem 1rem .4rem 3.2rem;
 border-bottom:1px solid var(--rule,#e3d9c6);}
.nav-btn{background:none;border:1px solid var(--rule,#ccc);color:var(--accent,#6b4f1d);
 border-radius:4px;padding:.3rem .7rem;cursor:pointer;font-size:.8rem;
 text-decoration:none;font-weight:600;}
.nav-btn:hover{background:var(--accent,#6b4f1d);color:#fff;}
.nav-home{margin-right:.5rem;}

/* Cloud bookmark status chip (TC-302) — one tiny state icon in the nav-bar.
   Loud-by-contract: hidden when not connected, never ambiguous when shown. */
.cloud-chip{display:inline-flex;align-items:center;font-size:.8rem;
 padding:.2rem .4rem;border-radius:4px;border:1px solid var(--rule,#ccc);
 color:var(--accent,#6b4f1d);margin-right:.5rem;line-height:1;user-select:none;}
.cloud-chip-syncing{color:var(--accent,#6b4f1d);opacity:.7;}
.cloud-chip-error{color:#b3402a;border-color:#b3402a;}

/* Quick-action row: language + font + theme — at the TOP of expanded chrome.
   These are the most-used controls, placed first for instant access (Nielsen H6). */
.quick-actions{
 display:flex;gap:.4rem;justify-content:center;align-items:center;
 padding:.5rem 1rem;flex-wrap:wrap;
 border-bottom:1px solid var(--rule,#e3d9c6);}
.quick-btn{
 background:var(--bg,#fff);border:1px solid var(--rule,#ccc);
 border-radius:6px;padding:.4rem .8rem;font-size:.9rem;font-weight:600;
 cursor:pointer;color:var(--fg,#333);min-width:2.5rem;text-align:center;
 transition:background .15s,border-color .15s;}
.quick-btn:active{background:var(--hover-bg,rgba(0,0,0,.06));}
.quick-lang-btn{background:var(--accent,#6b4f1d);color:#fff;border-color:var(--accent,#6b4f1d);min-width:5rem;font-size:1rem;}

/* Multi-chapter sticky headings */
.ch-heading{font-size:.95rem;color:var(--accent,#6b4f1d);
 border-bottom:1px solid var(--rule,#e3d9c6);
 padding:.4rem 0 .25rem;margin:0 0 .6em;font-weight:600;
 position:sticky;top:0;background:var(--bg,var(--paper,#fff));z-index:5;}
.ch-heading .strand{font-size:.6rem;color:var(--fg-muted,#999);
 vertical-align:super;letter-spacing:.1em;font-weight:400;}

/* Mobile: hide the STICKY ch-heading in vertical scroll (it eats ~36px at the
   top) but KEEP it in Kindle mode as a visible EPUB-style chapter separator so
   readers get clear chapter separation when switching chapters. */
@media (max-width: 50em) {
  .ch-heading { display: none; }
  .kindle-on .ch-heading {
    /* EPUB semantics: a chapter starts a NEW page — no tail of the previous
       chapter leaks into the first page of the new one (operator 2026-08-21). */
    break-before: column;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    min-height: 60%; position: static; background: none; border-bottom: 0;
    text-align: center; font-family: var(--font-serif, Georgia, serif);
    font-size: 1.4rem; font-weight: 700; color: var(--fg, #1f1d1a); letter-spacing: .02em;
    padding: 2rem 0;
  }
  .kindle-on .ch-heading::after {
    content: ""; width: 3rem; height: 2px; background: var(--accent, #6b4f1d); margin-top: .8rem;
  }
  .kindle-on .ch-heading .strand { font-size: .65rem; }
  /* Also hide the column-label (H2 "DE"/"RU") on mobile — the breadcrumb
     shows the book title; language is obvious from content. */
  .column-label { display: none; }
  /* Padding now comes from the equal-margin curtain block (--page-margin on
     all 4 sides + safe-area bottom) earlier in this media query. */
}

/* ============================================================================
   TTS audio pill + cache markers (TC-005)
   Bottom-fixed pill appears on pin (reader:pinned); all colors via design
   tokens so day/sepia/night themes render correctly. z-index 250: above
   fab-cluster (100) and mobile sheet (200), below header/modals (1000).
   ============================================================================ */
.audio-pill {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  transition: transform .25s ease, opacity .25s ease;
  bottom: calc(14px + 0px);
  bottom: calc(14px + env(safe-area-inset-bottom, 0px));
  z-index: 250;
  min-width: 0;
  max-width: 340px;
  max-width: min(340px, 92vw);
  background: var(--bg);
  color: var(--fg);
  border: 1px solid var(--rule);
  border-radius: 10px;
  box-shadow: 0 3px 12px rgba(0, 0, 0, 0.16);
  padding: 0.26rem 0.5rem;
  font-size: 0.75rem;
}

/* Modal discipline (2026-08-20): any bottom surface (Kindle menu, sentence
   accordion, settings) slides the audio pill away; it returns on close.
   CSS-only — pill JS/contract untouched. MOBILE-ONLY: on desktop the pill is
   a docked control and the settings sheet must not blank it (review P2). */
@media (max-width: 50em) {
  body.mobile-sheet-open .audio-pill {
    transform: translateX(-50%) translateY(140%);
    opacity: 0;
    pointer-events: none;
  }
}

.audio-pill-row { margin: 0; }
.audio-pill-row { display: flex; align-items: center; gap: 0.4rem; }
.audio-pill-icon { font-size: 0.9rem; line-height: 1; }
.audio-pill-id {
  color: var(--fg-muted);
  font-family: var(--font-mono);
  font-size: 0.68rem;
  white-space: nowrap;
}
/* Selection-change pulse: visible proof the pill follows the clicked paragraph */
.audio-pill-pop { animation: audio-pop 0.5s ease-out; }
@keyframes audio-pop {
  0% { box-shadow: 0 0 0 3px var(--pin-bar), 0 3px 12px rgba(0, 0, 0, 0.16); }
  100% { box-shadow: 0 0 0 0 rgba(0, 0, 0, 0), 0 3px 12px rgba(0, 0, 0, 0.16); }
}
.audio-pill.is-generating .audio-pill-iconbtn {
  display: inline-block;
  animation: audio-spin 1.2s linear infinite;
}
@keyframes audio-spin { to { transform: rotate(360deg); } }
.audio-pill-iconbtn {
  background: transparent;
  border: 0;
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  padding: 0.1rem 0.25rem;
  border-radius: 6px;
}
.audio-pill-iconbtn:hover:not(:disabled) { background: var(--hover-bg); }
.audio-pill-iconbtn:disabled { opacity: 0.45; cursor: default; }
.audio-pill-iconbtn.is-unavailable { opacity: 0.5; }
.audio-pill-progress {
  margin-top: 0.25rem;
  height: 3px;
  background: var(--rule);
  border-radius: 2px;
  overflow: hidden;
}
.audio-pill-progress i {
  display: block;
  height: 100%;
  width: 0;
  background: var(--pin-bar);
  transition: width 0.25s linear;
}
/* Generating: indeterminate sliding segment (no chunk progress from proxy) */
.audio-pill.is-generating .audio-pill-progress i {
  width: 35%;
  transition: none;
  animation: audio-slide 1.1s ease-in-out infinite alternate;
}
@keyframes audio-slide {
  from { transform: translateX(-10%); }
  to { transform: translateX(200%); }
}
.audio-pill-time {
  color: var(--fg-muted);
  font-size: 0.68rem;
  white-space: nowrap;
  max-width: 45%;
  overflow: hidden;
  text-overflow: ellipsis;
}
.audio-pill-more {
  background: transparent;
  border: 0;
  color: var(--fg-muted);
  font-size: 0.95rem;
  line-height: 1;
  cursor: pointer;
  padding: 0.05rem 0.3rem;
  border-radius: 6px;
}
.audio-pill-more:hover { background: var(--hover-bg); color: var(--fg); }
/* [hidden] loses to author display rules — restore it inside the pill */
.audio-pill [hidden] { display: none !important; }
.audio-pill-extra {
  margin-top: 0.5rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--rule);
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}
.audio-regen {
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 8px;
  color: var(--fg);
  font: inherit;
  font-size: 0.8rem;
  padding: 0.3rem 0.5rem;
  cursor: pointer;
  text-align: left;
}
.audio-regen:hover { border-color: var(--accent); background: var(--hover-bg); }
.audio-voice { color: var(--fg-muted); font-size: 0.78rem; opacity: 0.7; }
.audio-meta { color: var(--fg-muted); font-size: 0.72rem; }

/* Gutter cache marker — one speaker glyph in the left margin of voiced paras */
[data-pid] { position: relative; }
[data-pid].audio-cached::before {
  content: "🔊";
  position: absolute;
  left: -1.4em;
  top: 0.18em;
  font-size: 0.62em;
  opacity: 0.35;
  pointer-events: none;
}
[data-pid].audio-cached.audio-stale::before { content: "🔊⚠"; opacity: 0.55; }

@media (prefers-reduced-motion: reduce) {
  .audio-pill.is-generating .audio-pill-icon { animation: none; }
  .audio-pill-progress i { transition: none; }
}
.audio-pill-close {
  background: transparent;
  border: 0;
  color: var(--fg-muted);
  font-size: 0.9rem;
  line-height: 1;
  cursor: pointer;
  padding: 0.05rem 0.3rem;
  border-radius: 6px;
}
.audio-pill-close:hover { background: var(--hover-bg); color: var(--fg); }
/* Loud failure state — errors are never silent */
.audio-pill-error { border-color: var(--pin-bar); }
.audio-pill-error .audio-pill-time { color: var(--pin-bar); font-weight: 600; }
.audio-pill-handoff {
  display: block;
  margin-top: 0.3rem;
  font-size: 0.7rem;
  color: var(--accent);
  text-decoration: none;
  white-space: nowrap;
}
.audio-pill-handoff:hover { text-decoration: underline; }

/* ── Kindle experience (happy place B v1.0 port) — mobile horizontal pagination ──
   Frozen reference: reader/kindle-experience/v1.0/ (tag kindle-happy-place-b-v1.0).
   The mobile column becomes a horizontal scroller over a wide CSS-multicolumn
   flow; folds land at line-box boundaries (CSS Fragmentation), never mid-line. */
.kindle-on {
  overflow-x: auto !important;
  overflow-y: hidden !important;
  scrollbar-width: none;
}
.kindle-on::-webkit-scrollbar { display: none; }
.kindle-on > .kflow {
  column-fill: auto;
  overflow-wrap: break-word;
  -webkit-line-box-contain: block glyphs replaced; /* epub.js #983 glyph fix */
}

/* Range in which the reader reserves two lines minimum at fold edges for
   paragraph-shaped blocks (p.para) and a hard break before headings.
   Without these, long paragraphs in legacy books (Gass ch05, Ulysses)
   throw orphan/widow lines at page bottoms — the "coarse paragraph
   divisions" the operator saw vs Vineland's dense short-paragraph pages.
   Paged-media rules apply in multicolumn contexts. */
.kflow .paragraph {
  orphans: 2;
  widows: 2;
}
.kflow h1, .kflow h2, .kflow h3, .kflow h4, .kflow h5,
.kflow .ch-heading, .kflow .ep-heading, .kflow .scene-heading {
  break-inside: avoid-column;
  break-after: avoid-column;
}

/* Kindle status strip: Стр. X/Y · Loc N · % + progress (visible when chrome collapsed) */
#kindle-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 35;
  padding: 3px 1.25rem calc(5px + 0px);
  padding: 3px 1.25rem calc(5px + env(safe-area-inset-bottom));
  font-size: 11px;
  color: var(--ink-soft, var(--rule, #8a8a80));
  background: var(--bg, var(--paper, #fff));
  border-top: 1px solid var(--rule, rgba(128,128,128,.18));
  opacity: 0; pointer-events: none;
  transition: opacity .18s ease;
}
#kindle-bar.visible { opacity: 1; }
#kindle-progress { height: 2px; background: var(--rule, rgba(128,128,128,.2)); border-radius: 1px; margin-bottom: 3px; }
#kindle-progress-fill { height: 100%; width: 0%; background: var(--accent, #6b4f1d); border-radius: 1px; transition: width .15s; }
.kindle-row { display: flex; justify-content: space-between; }

/* ── Kindle TOC jump feedback (H1 status flash + H3 back-to-position pill) ── */
#kindle-ch-flash {
  position: fixed; top: calc(12px + 0px); left: 50%;
  position: fixed; top: calc(12px + env(safe-area-inset-top)); left: 50%;
  transform: translateX(-50%) translateY(-6px); z-index: 60;
  max-width: 80vw; padding: 6px 14px; border-radius: 14px;
  background: var(--bg, var(--paper, #fff)); color: var(--fg, #191919);
  border: 1px solid var(--rule, rgba(128,128,128,.25));
  font-size: 13px; text-align: center;
  opacity: 0; transition: opacity .25s ease, transform .25s ease;
  pointer-events: none;
}
#kindle-ch-flash.show { opacity: 1; transform: translateX(-50%) translateY(0); }
/* Resume flash: same shape as the chapter flash, accent-colored so a
   returning reader instantly reads it as «you are back», not a chapter cue. */
#kindle-resume-flash {
  position: fixed; top: calc(12px + 0px); left: 50%;
  position: fixed; top: calc(12px + env(safe-area-inset-top)); left: 50%;
  transform: translateX(-50%) translateY(-6px); z-index: 60;
  max-width: 80vw; padding: 6px 14px; border-radius: 14px;
  background: var(--bg, var(--paper, #fff)); color: var(--accent, #6b4f1d);
  border: 1px solid var(--accent, #6b4f1d);
  font-size: 13px; text-align: center;
  opacity: 0; transition: opacity .25s ease, transform .25s ease;
  pointer-events: none;
}
#kindle-resume-flash.show { opacity: 1; transform: translateX(-50%) translateY(0); }
#kindle-backpill {
  position: fixed; bottom: calc(44px + 0px); left: 50%;
  position: fixed; bottom: calc(44px + env(safe-area-inset-bottom)); left: 50%;
  transform: translateX(-50%); z-index: 55;
  padding: 5px 14px; border-radius: 16px;
  background: var(--bg, var(--paper, #fff)); color: var(--accent, #6b4f1d);
  border: 1px solid var(--rule, rgba(128,128,128,.3));
  font-size: 12px; cursor: pointer;
  box-shadow: 0 1px 4px rgba(0,0,0,.12);
}

/* ── Kindle clean-chrome model (expert panel 2026-08-18) ────────────────────
   Reading state = pure text + slim print folio. The drawer opens ONLY via
   center tap; ≡ hides once the gesture is learned. Spacing aligned to the
   reading margins (--page-margin) so panel columns match page columns. */
@media (max-width: 50em) {
  /* ≡ corner: faint affordance until the first center tap, then gone. */
  .chrome-toggle { opacity: .35; }
  body.kindle-learned .chrome-toggle { display: none; }

  /* Breadcrumb demoted to context caption (only links tappable). */
  .reader-crumbs { font-size: 11px; opacity: .75; padding: 2px 0 6px; }
  /* The big book-title header is redundant with the breadcrumb on mobile and
     pushes the nav row past the one-hand cap — hide it (print stays clean). */
  .chrome-frame .reader-header { display: none; }
  /* Rows: 44px targets on a hairline-separated stack, muted glyphs. */
  .quick-actions, .nav-bar { padding: 0; }
  .quick-actions + .nav-bar { border-top: 0.5px solid var(--rule); }
  .nav-bar {
    display: flex; gap: .5rem; padding: .5rem 0 0;
    margin: 0; border-top: 0.5px solid var(--rule);
    justify-content: stretch;
  }
  .nav-bar .nav-btn, .nav-bar .toc-trigger {
    flex: 1 1 0; min-height: 44px; margin: 0;
    font-size: .8rem; border-radius: 6px;
  }
  .nav-btn, .quick-btn { filter: saturate(.85); }
  .nav-btn .emoji, .toc-trigger { letter-spacing: .01em; }
}

/* First-visit coach mark (persisted once dismissed). */
#kindle-hint {
  position: fixed; top: 50%; left: 50%; z-index: 40;
  transform: translate(-50%, -50%);
  padding: 8px 16px; border-radius: 14px;
  background: rgba(20, 18, 14, .62); color: #fdfdfa;
  font-size: 12px; letter-spacing: .02em;
  opacity: 0; transition: opacity .45s ease;
  pointer-events: none;
}
#kindle-hint.show { opacity: 1; }

/* Kindle status strip restyled as a print folio: status, not app chrome. */
#kindle-bar {
  height: auto; padding: 3px var(--page-margin, 1.25rem)
             calc(4px + 0px);
  padding: 3px var(--page-margin, 1.25rem)
             calc(4px + env(safe-area-inset-bottom, 0px));
  font-size: 11px; opacity: .62;
  font-variant-numeric: tabular-nums;
  border-top: 0.5px solid var(--rule, rgba(128,128,128,.18));
  box-shadow: none;
}

/* Muted monochrome nav icons (expert B: emoji read as amateurish beside book
   typography). Quick actions keep color — the RU pill carries language state. */
@media (max-width: 50em) {
  .nav-bar .nav-btn { filter: grayscale(1); opacity: .85; }
}

/* Inline illustration embeds (operator 2026-08-19): a figure injected at an exact
   reader paragraph. Keeps the paragraph as the alignment atom; glued to its
   following paragraph so the Kindle fold never strands/slices it; height-capped. */
:root { --ill-max-w: 420px; --ill-max-h: 60vh; --ill-shadow: 0 1px 6px rgba(0,0,0,.12); }
[data-theme="night"] { --ill-shadow: none; }

.reader-inline-ill {
  margin: 1.2rem auto .8rem;
  max-width: 100%;
  text-align: center;
  break-inside: avoid;
}
.reader-inline-ill .fig-media {
  display: inline-block; border: 0; background: none; padding: 0; margin: 0;
  font: inherit; cursor: zoom-in; border-radius: 8px;
}
.reader-inline-ill img {
  display: block;
  max-width: var(--ill-max-w);
  max-width: min(var(--ill-max-w), 92%);
  max-height: var(--ill-max-h);
  width: auto; height: auto;
  object-fit: contain;
  border-radius: 8px;
  border: 1px solid var(--rule);
  box-shadow: var(--ill-shadow);
}
.reader-inline-ill figcaption {
  margin-top: .4rem; font-size: .78rem; line-height: 1.4;
  color: var(--fg-muted, #8a8a80); font-style: italic;
}
[data-theme="night"] .reader-inline-ill img { filter: brightness(.9); }

/* Mobile Kindle fold: keep figure + its paragraph as one unbreakable unit */
.kflow .reader-inline-ill { break-inside: avoid-column; break-after: avoid-column; }
.kflow .reader-inline-ill + .paragraph { break-before: avoid-column; }

/* Full-res lightbox (fig-media tap) */
.fig-lightbox {
  position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 90;
  display: flex; align-items: center; justify-content: center;
  background: rgba(10,10,12,.82); -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  cursor: zoom-out;
}
.fig-lightbox img {
  max-width: 92vw; max-width: 92dvw; max-height: 92vh; max-height: 92dvh; object-fit: contain;
  border-radius: 6px; box-shadow: 0 8px 40px rgba(0,0,0,.5);
}
.fig-lightbox .lb-cap {
  position: absolute; bottom: 1rem; left: 0; right: 0; text-align: center;
  color: #eee; font-size: .85rem; font-style: italic; padding: 0 1rem;
}
.fig-lightbox .lb-close {
  position: absolute; top: 1rem; right: 1rem; width: 2.2rem; height: 2.2rem;
  border: 0; border-radius: 50%; background: rgba(255,255,255,.18); color: #fff;
  font-size: 1.1rem; line-height: 1; cursor: pointer;
}

/* ── rbs menu content (unified bottom sheet, TC-003) ────────────────────
   Shell (.mobile-sheet-overlay/.mobile-sheet/handle/close/drag) is the
   canonical block in reader.css (top of file) + reader/module/src/70-overlays.js.
   Only the menu's CONTENT styles live here, scoped to .rbs-menu. ──────── */
body.mobile-sheet-open .tap-zone { pointer-events: none !important; }

/* Menu title renders as the core .mobile-sheet-title — small uppercase header
   look (overrides the global card title sizing for the menu). */
.rbs-menu .mobile-sheet-title { font-size:.75rem; color:var(--fg-muted,#6a645b); text-transform:uppercase; letter-spacing:.06em; margin-bottom:2px; }
.rbs-menu .rbs-chapter { font-family:var(--font-serif,Georgia,serif); font-size:1.3rem; font-weight:700; margin-bottom:2px; }
.rbs-menu .rbs-pos { font-size:.78rem; color:var(--fg-muted,#6a645b); font-variant-numeric:tabular-nums; margin-bottom:14px; }
.rbs-menu .rbs-sep { height:1px; background:var(--rule,rgba(0,0,0,.12)); margin:14px 0; }
.rbs-menu .rbs-row { display:flex; align-items:center; justify-content:space-between; padding:10px 0; }
.rbs-menu .rbs-label { font-size:.95rem; }
/* Door to the reading-settings sheet from the ≡ menu (2026-08-25: the ⚙ in
   the expanded nav-bar was invisible from the reading surface). */
.rbs-menu .rbs-settings-open { width:100%; text-align:center; padding:11px 12px; border:1px solid var(--rule,rgba(0,0,0,.18)); border-radius:10px; background:transparent; color:var(--fg,#1f1d1a); font-size:.95rem; cursor:pointer; }
.rbs-menu .rbs-switch { position:relative; width:48px; height:28px; border-radius:999px; background:var(--accent,#6b4f1d); cursor:pointer; transition:background .2s; flex-shrink:0; display:inline-block; }
.rbs-menu .rbs-switch.off { background:var(--rule,rgba(0,0,0,.18)); }
.rbs-menu .rbs-knob { position:absolute; top:3px; left:3px; width:22px; height:22px; border-radius:50%; background:var(--bg,#fff); box-shadow:0 1px 2px rgba(0,0,0,.25); transition:left .2s; }
.rbs-menu .rbs-switch.off .rbs-knob { left:23px; }
.rbs-menu .rbs-lang { display:inline-flex; border:1px solid var(--rule,rgba(0,0,0,.15)); border-radius:8px; overflow:hidden; }
.rbs-menu .rbs-langbtn { border:0; background:transparent; color:var(--fg-muted,#6a645b); padding:10px 20px; font:inherit; font-size:.82rem; letter-spacing:.04em; cursor:pointer; }
.rbs-menu .rbs-langbtn.active { background:var(--accent,#6b4f1d); color:var(--bg,#fff); }
.rbs-menu .rbs-theme-cycle { border:1px solid var(--rule,rgba(0,0,0,.15)); border-radius:8px; background:var(--bg,#fff); color:var(--fg,#1f1d1a); padding:10px 18px; font:inherit; font-size:.85rem; cursor:pointer; }
.rbs-menu .rbs-bm-wrap { margin:0; }
.rbs-menu .rbs-bm-wrap { display:flex; align-items:center; gap:10px; }
.rbs-menu .rbs-bm-status { font-size:.78rem; color:var(--fg-muted,#6a645b); }
.rbs-menu .rbs-toc-head { font-size:.75rem; text-transform:uppercase; letter-spacing:.06em; color:var(--fg-muted,#6a645b); margin-bottom:8px; }
.rbs-menu .rbs-bm-jump { display:none; align-items:center; justify-content:space-between; padding:12px 8px; border:1px solid var(--accent,#6b4f1d); border-radius:8px; margin-bottom:8px; cursor:pointer; font-size:.92rem; color:var(--accent,#6b4f1d); font-weight:600; }
.rbs-menu .rbs-bm-jump.show { display:flex; }
.rbs-menu .rbs-freeze { padding:7px 12px; border:1px solid var(--rule,rgba(0,0,0,.18)); border-radius:10px; background:transparent; color:var(--fg,#1f1d1a); font-size:.86rem; cursor:pointer; }
.rbs-menu .rbs-freeze.active { border-color:var(--accent,#6b4f1d); background:var(--accent,#6b4f1d); color:var(--bg,#fff); }
.rbs-menu .rbs-dev { margin-top:14px; text-align:center; }
.rbs-menu .rbs-dev button { background:none; border:1px dashed var(--rule,rgba(0,0,0,.3)); border-radius:8px; padding:6px 12px; font-size:.78rem; color:var(--fg-muted,#6a645b); cursor:pointer; }

.rbs-menu .rbs-toc-list { max-height: 36vh; }
.rbs-menu .rbs-toc-list { list-style:none; max-height:min(36vh,320px); overflow-y:auto; -webkit-overflow-scrolling:touch; }
.rbs-menu .rbs-toc-list li { display:flex; justify-content:space-between; padding:12px 0; border-top:1px solid var(--rule,rgba(0,0,0,.12)); font-size:.92rem; cursor:pointer; }
.rbs-menu .rbs-toc-list li:last-child { border-bottom:1px solid var(--rule,rgba(0,0,0,.12)); }
.rbs-menu .rbs-toc-list li.here { font-weight:700; color:var(--accent,#6b4f1d); border-left:3px solid var(--accent,#6b4f1d); padding-left:8px; }
.rbs-toast { top: calc(56px + 0px); }
.rbs-toast { position:fixed; top:calc(56px + env(safe-area-inset-top,0px)); left:50%; transform:translateX(-50%); background:var(--fg,#1f1d1a); color:var(--bg,#fff); padding:10px 18px; border-radius:8px; font-size:.85rem; z-index:300; /* above the sheet veil (.mobile-sheet-overlay 260): a toast fired from an open sheet must not be dimmed/blurred under it (review Nielsen sev-2); pointer-events:none keeps everything beneath clickable */ opacity:0; transition:opacity .3s; pointer-events:none; max-width:calc(100vw - 32px); text-align:center; }
.rbs-toast.show { opacity:1; }
#rbs-pill { padding-top: calc(8px + 0px); }
#rbs-pill { position:fixed; top:0; left:0; right:0; z-index:210; /* above every mobile overlay (accordion/settings) — unfreeze must ALWAYS be reachable */ background:var(--accent,#6b4f1d); color:var(--bg,#fff); font-size:.76rem; padding:calc(8px + env(safe-area-inset-top,0px)) 14px 8px; box-shadow:0 2px 8px rgba(0,0,0,.25); display:flex; align-items:center; justify-content:center; gap:8px; white-space:nowrap; }
#rbs-pill .rbs-pill-x { border:0; background:rgba(255,255,255,.25); color:inherit; width:22px; height:22px; border-radius:50%; font-size:.9rem; line-height:1; cursor:pointer; display:flex; align-items:center; justify-content:center; }
#rbs-ribbon.rbs-ribbon-off { display:none; }
#rbs-ribbon { position:fixed; top:0; right:28px; width:16px; height:52px; background:var(--accent,#6b4f1d); z-index:3; cursor:pointer; clip-path:polygon(0 0,100% 0,100% 100%,50% 78%,0 100%); box-shadow:0 2px 8px rgba(0,0,0,.25); }
/* Freeze ON (2026-08-20 rework): ALL three activation zones (prev/next/menu)
   disappear completely — taps reach the content beneath (links, tesserae,
   sentences). The «заморожено [×]» pill is the only way back. */
body.tap-frozen .tap-zone { display: none !important; }

/* Unsupported-browser notice (TC-002). Rendered before reader.js loads. */
.browser-notice {
  padding: 2rem;
  font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  line-height: 1.5;
  text-align: center;
  color: var(--fg, #222);
  background: var(--bg, #fff);
}
.browser-notice h1 { font-size: 1.4rem; margin: 0 0 1rem; }
.browser-notice p { margin: 0 0 0.5rem; }
