/* 2026-05-19 Phase 15c — Hebrew/Greek webfonts.
 *
 * Both fonts are Google-Fonts-hosted; loaded via @import to keep this
 * stylesheet self-contained. Display-swap on so the page renders
 * immediately with the system fallback while the webfont loads.
 *
 * Hebrew: Noto Serif Hebrew — designed by Google in collaboration
 *   with the Hebrew typography community; good vowel-point + cantillation
 *   support, OFL licensed. Frank Ruhl Libre is also OFL and is what
 *   the original --hebrew variable named; Noto Serif Hebrew is closer
 *   to what biblical-text readers expect.
 *
 * Greek: Cardo — designed by David Perry for classical/biblical work;
 *   excellent polytonic Greek support (breathings, accents, iota
 *   subscript). OFL licensed.
 *
 * Both webfonts are subsetted via Google Fonts URL parameters
 * (`text=` would over-specify; using full sets so any verse renders).
 */
@import url("https://fonts.googleapis.com/css2?family=Noto+Serif+Hebrew:wght@400;600&family=Cardo:wght@400;700&display=swap");

:root {
  --bg: #faf7f2;
  --ink: #1c1917;
  --muted: #6b6256;
  --faint: #b7ad9d;
  --rule: #e7e1d6;
  --rule-strong: #d2c8b7;
  --accent: #8a3f2c;          /* legacy default; retained for non-name UI accents */
  --accent-soft: #f3e6df;
  --divergent: #1f6e6e;       /* context-divergent (popover badge only) */
  --divergent-soft: #d9ecea;
  --pending: #b08a1e;
  /* Confidence palette — applied to translated names in text + sidebar */
  --conf-high: #4a7c4a;
  --conf-high-soft: #e3eee0;
  --conf-medium: #b08a1e;
  --conf-medium-soft: #f3eacc;
  --conf-low: #9c3d2c;
  --conf-low-soft: #f3dcd5;
  --panel-bg: #ffffff;
  --panel-shadow: 0 24px 48px -16px rgba(28,25,23,0.25);
  --serif: "Iowan Old Style", "Charter", "Source Serif Pro", "Georgia", "Times New Roman", serif;
  /* Hebrew script — Noto Serif Hebrew (Phase 15c webfont), with
   * Frank Ruhl Libre + system Hebrew fonts as fallbacks. The system
   * fallbacks matter on first paint (before webfont swap) and for
   * offline use. */
  --hebrew: "Noto Serif Hebrew", "Frank Ruhl Libre", "David CLM", "David",
            "Times New Roman", serif;
  /* Greek script — Cardo (Phase 15c webfont) is designed for
   * classical / biblical Greek. GFS Didot is a strong fallback on
   * systems that have it. */
  --greek: "Cardo", "GFS Didot", "GFS Neohellenic", "Gentium Plus",
           "Times New Roman", "Iowan Old Style", serif;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --sidebar-w: 268px;
  /* P2.11.3: independent text-scale for English (Latin script) vs
   * Original (Hebrew/Greek source script). Hebrew renders smaller
   * than Latin at the same nominal font-size, so the user often
   * wants different sizes per script. Each scale is set on :root
   * by app.js based on localStorage. */
  /* 2026-05-19 Phase 15d: independent per-script text scales. Latin
   * is the baseline (1.0 = 20px). Hebrew + Greek each have their own
   * factor and the `verse-original-language[lang=...]` selectors pick
   * the matching var. The legacy `--reader-text-scale-original` is
   * kept aliased to Hebrew so any not-yet-migrated rule still works. */
  --reader-text-scale-latin:  1;
  --reader-text-scale-hebrew: 1.3;
  --reader-text-scale-greek:  1.1;
  --reader-text-scale-original: var(--reader-text-scale-hebrew);
  /* Rare-word highlight palette (mirrors source.css). */
  --rare-bg:        rgba(176, 138, 30, 0.08);
  --rare-border:    rgba(176, 138, 30, 0.22);
}
/* P2.11: theme is now driven by an explicit user choice (light by
 * default, persisted in localStorage as mfb.reader.theme). The OS
 * prefers-color-scheme query is no longer the source of truth.
 * body.theme-dark overrides the :root light values when the user
 * selects dark mode via the sidebar toggle. */
body.theme-dark {
  --rare-bg:     rgba(214, 177, 74, 0.10);
  --rare-border: rgba(214, 177, 74, 0.32);
  --bg: #181614;
  --ink: #ece6db;
  --muted: #9d9385;
  --faint: #57503f;
  --rule: #2e2a25;
  --rule-strong: #45403a;
  --accent: #d99a7b;
  --accent-soft: #2e231d;
  --divergent: #6fbab3;
  --divergent-soft: #1a2a29;
  --pending: #d6b14a;
  --conf-high: #7fb37f;
  --conf-high-soft: #1f2a1d;
  --conf-medium: #d6b14a;
  --conf-medium-soft: #2a241a;
  --conf-low: #d18470;
  --conf-low-soft: #2c1f1a;
  --panel-bg: #211d19;
  --panel-shadow: 0 24px 48px -16px rgba(0,0,0,0.6);
}
* { box-sizing: border-box; }
html, body { background: var(--bg); color: var(--ink); }
body {
  font-family: var(--serif);
  margin: 0;
  line-height: 1.7;
  font-size: 19px;
  -webkit-font-smoothing: antialiased;
}

/* ===== Sidebar ===== */
.sidebar {
  position: fixed;
  top: 0; left: 0; bottom: 0;
  width: var(--sidebar-w);
  border-right: 1px solid var(--rule);
  overflow-y: auto;
  background: var(--bg);
  font-family: var(--sans);
  z-index: 30;
}
.sidebar-inner { padding: 28px 22px 60px; position: relative; }

/* P2.11.1: theme toggle. Icon-only square pill in the upper-right
 * of the sidebar — moon when in light mode (click → dark), sun
 * when in dark mode (click → light). The icon is rendered as
 * inline SVG using currentColor so it inherits muted/ink color
 * from the button itself. */
.theme-toggle {
  position: absolute;
  top: 20px;
  /* 2026-05-14: shifted left from right:18 to make room for the
     sidebar-collapse toggle which now sits at the sidebar's top-right
     corner. */
  right: 60px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 999px;
  color: var(--muted);
  cursor: pointer;
  transition: background 100ms ease, color 100ms ease, border-color 100ms ease;
}
.theme-toggle:hover {
  background: var(--accent-soft);
  color: var(--ink);
  border-color: var(--accent-soft);
}
.theme-toggle svg {
  display: block;
}
.sidebar .brand {
  font-family: var(--serif);
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.005em;
  margin: 0 0 4px;
}
.sidebar .brand-sub {
  font-size: 11px;
  color: var(--muted);
  letter-spacing: 0.04em;
  margin-bottom: 4px;
  text-transform: uppercase;
}
/* P2.11.2: build indicator moved from fixed bottom-right corner into
 * the sidebar, just under the "TEST BUILD · JONAH" line. Same purpose
 * (glance-confirm which build is loaded), tucked away in the menu
 * area so it's reachable but doesn't sit over the reader content. */
.sidebar .brand-build {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 9.5px;
  color: var(--muted);
  opacity: 0.55;
  letter-spacing: 0.04em;
  margin-bottom: 18px;
  user-select: none;
  word-break: break-all;
}
.sidebar .brand-build:empty { display: none; }
.sidebar .canon-section { margin-top: 22px; }
.sidebar h4 {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--muted);
  font-weight: 700;
  margin: 0 0 8px;
}
.sidebar h5 {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--faint);
  font-weight: 600;
  margin: 10px 0 4px 0;
}
/* 2026-05-23 (Curtis): "Former" / "Latter" sub-labels under the
   merged "Prophets" canon-section. Smaller + subtler than h4 (the
   "PROPHETS" heading) and h5 (the "The Twelve" sub-grouping) so
   the higher-level Tanakh division reads first. Italic + lowercase
   to feel like a quiet aside rather than another category. */
.sidebar .canon-subdivision {
  font-size: 10px;
  font-style: italic;
  color: var(--faint);
  letter-spacing: 0.02em;
  margin: 6px 0 2px 6px;
  opacity: 0.75;
}
/* First subdivision under the Prophets h4 has zero top margin so it
   sits snugly under the heading. */
.sidebar .canon-section-prophets > .canon-subdivision:first-of-type {
  margin-top: 2px;
}
.sidebar ul { list-style: none; padding: 0; margin: 0; }
.sidebar .book {
  position: relative;
  font-size: 13px;
  line-height: 1.35;
  padding: 5px 8px 5px 12px;
  color: var(--faint);
  cursor: default;
  border-radius: 4px;
  user-select: none;
}
.sidebar .book .book-meaning {
  color: var(--ink);
  font-weight: 500;
}
.sidebar .book .book-conv {
  color: var(--faint);
  font-size: 11.5px;
  margin-left: 3px;
  font-weight: 400;
}
.sidebar .book:not(.available) .book-meaning {
  color: var(--muted);
}
.sidebar .book.untranslated .book-meaning {
  color: var(--faint);
  font-weight: 400;
  font-style: italic;
}
.sidebar .book.available { cursor: pointer; }
/* 2026-05-23 (Curtis): hover removed the boxy `background: accent-soft`
   — only the text glows now. The .book-meaning color flip below is
   the visual signal; no surrounding pill or fill. */
.sidebar .book.available:hover .book-meaning,
.sidebar .book.active .book-meaning { color: var(--accent); }
.sidebar .book.active {
  color: var(--accent);
  font-weight: 600;
}
/* Vertical progress line beside active book (non-tabbed books only —
   for tabbed books the bar lives on the active .component, see below).
   2026-05-23 (Curtis revision): "I don't like how the current tabbed
   reading bar looks right now... that smaller bar right next to the
   tabbed books should be the reading bar." So for tabbed parents the
   parent itself no longer gets the indicator; the bar moves to the
   active component. Parent title still gets the accent color via
   .book.has-active-child > .book-meaning below. */
.sidebar .book.active::before {
  content: "";
  position: absolute;
  left: 0;
  top: 2px;
  bottom: 2px;
  width: 2px;
  background: var(--rule-strong);
  border-radius: 2px;
}
.sidebar .book.active::after {
  content: "";
  position: absolute;
  left: 0;
  top: 2px;
  width: 2px;
  height: calc((100% - 4px) * var(--progress, 0));
  background: var(--accent);
  border-radius: 2px;
  transition: height 80ms linear;
}
/* 2026-05-23 (Curtis): tabbed-book parent title turns accent when any
   child component is active (e.g. reading 1 Chronicles → "Words-of-
   the-Days (Chronicles)" parent title accent). The `>` direct-child
   selectors are deliberate so the nested .component .book-meaning
   isn't double-colored. */
.sidebar .book.has-active-child > .book-meaning,
.sidebar .book.has-active-child > .book-conv {
  color: var(--accent);
}
.sidebar .division-rule {
  height: 1px;
  background: var(--rule);
  margin: 14px 0 14px;
}

/* 2026-05-18 (Curtis): chapter pop-up — full-height vertical rail
 * anchored to the right edge of the sidebar. Top-to-bottom of the
 * viewport, like the word-details side panel but sliding out from
 * the SIDEBAR instead of the right edge of the screen. Chapter 1
 * always sits at the top; scroll down for long books. Single
 * column. When open, the sidebar-inner gets padding-right so book
 * titles shift left to make room. Main reading text NOT affected. */
:root {
  --chapter-popup-w: 52px;
}
.chapter-popup {
  position: fixed;
  /* Sidebar's right edge IS the seam. Popup sits FLUSH against it
     (left: sidebar-w) and emerges from BEHIND it via slide animation.
     The sidebar's existing right border = the popup's visual left
     edge / "line." */
  left: var(--sidebar-w);
  width: var(--chapter-popup-w);
  top: 0;
  height: 100vh;
  /* z-index BELOW the sidebar (30) so the sidebar physically hides
     the popup during its slide-out animation. As the popup
     translates from translateX(-100%) (entirely covered by sidebar)
     to translateX(0) (revealed to the right of sidebar), it
     appears to come out from behind the line. */
  z-index: 20;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 64px 8px 24px;
  /* Match the sidebar/page bg so the seam between sidebar and
     popup is invisible at the moment of emergence. */
  background: var(--bg);
  /* No left border — the sidebar's existing right border IS the
     seam, the line Curtis pointed at. */
  border-right: 1px solid var(--rule);
  /* Subtle top inset for depth — no left inset (the seam should
     look like a clean edge, not a shadowed crease). */
  box-shadow: inset 0 6px 6px -6px rgba(28,25,23,0.10);
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--rule) transparent;
}
/* 2026-05-23 (Curtis): in admin mode the reader-nav stays pinned at
   the top (top:55, height:62 → bottom ~117), and the existing
   `body.reader-nav-visible .chapter-popup` rule below positions the
   popup at top:68px. That hides chapter 1 behind the bar. Override
   here with a higher-specificity rule (chains both body classes) to
   start the popup below the pinned nav. */
body.admin-mode.reader-nav-visible .chapter-popup {
  top: 124px;
  height: calc(100vh - 124px);
  padding-top: 16px;
}
.chapter-popup {
  /* 2026-05-23 (Curtis): "when I try to scroll on it, the background
     text scrolls instead of the chapters." Scroll containment — when
     the wheel hits the popup's top/bottom boundary, the scroll event
     stops at the popup instead of propagating to the page. Also
     prevents the chain effect where a fast wheel gesture scrolls the
     popup briefly and then the page once the popup hits its boundary. */
  overscroll-behavior: contain;
  overflow-y: auto;
  /* Resting transform is the visible state (translateX(0)). The
     .opening keyframe animation starts the element at translateX(-100%)
     and ends at translateX(0). After the animation finishes JS removes
     .opening — the base rule's lack of transform = default translateX(0)
     keeps the popup visible. .closing reverses it back to -100% and
     JS removes the element on animationend. */
}
/* 2026-05-23 (Curtis): "The scroll bar on the book pop up is a
   little too big. Make it nice and thin." 6px → 3px + lower-
   contrast thumb so it reads as a quiet hint, not a chrome bar. */
.chapter-popup::-webkit-scrollbar { width: 3px; }
.chapter-popup::-webkit-scrollbar-thumb { background: var(--rule); border-radius: 2px; opacity: 0.6; }
.chapter-popup::-webkit-scrollbar-track { background: transparent; }

/* Slide-out-from-behind-the-sidebar animation.
   Open: popup transforms from translateX(-100%) (covered by sidebar)
   to translateX(0) (revealed at its resting position to the right of
   the sidebar). The sidebar acts as a curtain that the popup emerges
   from behind. Close reverses the slide.
   Opacity stays at 1 throughout — no fade. The illusion is purely
   positional. */
.chapter-popup.opening {
  animation: chapter-popup-in 280ms cubic-bezier(0.22, 1, 0.36, 1) forwards;
}
.chapter-popup.closing {
  animation: chapter-popup-out 240ms cubic-bezier(0.55, 0, 0.7, 0.2) forwards;
  pointer-events: none;
}
@keyframes chapter-popup-in {
  from { transform: translateX(-100%); }
  to   { transform: translateX(0); }
}
@keyframes chapter-popup-out {
  from { transform: translateX(0); }
  to   { transform: translateX(-100%); }
}
.chapter-popup.loading {
  font-size: 11px;
  color: var(--muted);
  padding: 18px 8px;
  letter-spacing: 0.2em;
  text-align: center;
}
.chapter-popup-btn {
  font-family: var(--sans);
  font-size: 11.5px;
  font-weight: 500;
  width: 100%;
  height: 26px;
  padding: 0;
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 4px;
  color: var(--muted);
  cursor: pointer;
  transition: background 80ms ease, color 80ms ease, border-color 80ms ease;
  flex-shrink: 0;
}
.chapter-popup-btn:hover {
  background: var(--accent-soft);
  color: var(--accent);
  border-color: var(--accent);
}
/* 2026-05-23 (Curtis): the chapter button matching the user's current
   reading position gets a subtle highlight so they can see WHICH
   chapter the popup is anchored to. Cooldown-realign re-centers on
   this button. Styled distinct from :hover so the two states can
   coexist (hovering a non-current button shouldn't visually
   "consume" the current marker). */
.chapter-popup-btn.current-chapter {
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
  box-shadow: inset 0 0 0 1px var(--accent);
}
.chapter-popup-btn.current-chapter:hover {
  background: var(--accent-soft);
}
/* 2026-05-23 (Curtis): chapter-popup buttons whose chapter is in the
   reader's navigation history (per-book history icon click → opens
   popup with these dots). A small accent dot in the lower-right
   corner signals "you were here recently"; clicking jumps to the
   saved verse rather than v.1. Distinct from .current-chapter
   (which marks the CURRENTLY-active chapter, not a historical
   visit). Both can coexist — current + visited would show the
   accent ring AND the dot. */
.chapter-popup-btn.is-visited {
  position: relative;
}
.chapter-popup-btn.is-visited::after {
  content: "";
  position: absolute;
  bottom: 3px;
  right: 3px;
  width: 4px;
  height: 4px;
  background: var(--accent);
  border-radius: 50%;
  opacity: 0.85;
}
/* Section header for multi-component books (Samuel, Kings, Chronicles,
   Ezra-Nehemiah, The Twelve). Sits above each component's chapter
   buttons inside the popup. First header has no top margin; subsequent
   ones get a divider via top border. */
.chapter-popup-section {
  font-family: var(--sans);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 6px 2px 4px;
  text-align: center;
  flex-shrink: 0;
}
.chapter-popup-section + .chapter-popup-section,
.chapter-popup-btn + .chapter-popup-section {
  margin-top: 6px;
  padding-top: 8px;
  border-top: 1px solid var(--rule);
}
/* 2026-05-18 (Curtis): popup is a secondary quick-select layer —
   it should NOT reshape the main reading area. The popup floats
   over the leftmost portion of the main content (which on most
   desktop widths is empty margin between the sidebar and the
   centered text column). Sidebar bg + popup z-index 20 (below
   sidebar 30, above content default) preserve the slide-from-
   behind illusion without shifting any text. */
/* Subtle right-edge drop shadow on the popup makes it read as a
   layer floating over the content, not as part of the sidebar. */
.chapter-popup {
  box-shadow:
    inset 0 6px 6px -6px rgba(28,25,23,0.10),
    4px 0 10px -6px rgba(28,25,23,0.18);
}
/* 2026-05-18 (Curtis): when the reader nav panel is visible, the
   chapter rail starts below it so chapter 1 isn't tucked behind
   the nav. Smooth transition between states (matches the popup's
   own slide-in easing). */
body.reader-nav-visible .chapter-popup {
  top: 68px;
  height: calc(100vh - 68px);
  padding-top: 16px;
}
.chapter-popup {
  transition:
    top 320ms cubic-bezier(0.22, 1, 0.36, 1),
    height 320ms cubic-bezier(0.22, 1, 0.36, 1),
    padding-top 320ms cubic-bezier(0.22, 1, 0.36, 1);
}
/* Mobile: same anchor as desktop (left: sidebar-w). The sidebar
   STAYS OPEN while the chapter pop-up is visible — see
   closeSidebarMobile in app.js, which now early-returns when
   body.chapter-popup-open is set. User taps a chapter from the
   popup, or taps the page outside the popup+sidebar to dismiss
   both. Same look as desktop, just compressed against a narrow
   viewport. */

/* P3.11: multi-component books expose their underlying span-data files
 * as clickable sub-entries (Samuel → 1 Samuel / 2 Samuel; The Twelve →
 * 12 minor prophets; etc.). Sub-list sits nested inside the parent
 * <li.book.has-components>; click on parent loads the merged book at
 * the top, click on a sub-entry loads + scrolls to its section. */
.sidebar .book.has-components > .components {
  list-style: none;
  margin: 4px 0 4px 12px;
  padding-left: 8px;
  border-left: 1px solid var(--rule);
}
.sidebar .book.has-components > .components .component {
  position: relative;
  font-size: 12.5px;
  line-height: 1.3;
  padding: 3px 6px 3px 8px;
  color: var(--faint);
  cursor: default;
  border-radius: 3px;
  user-select: none;
}
.sidebar .book.has-components > .components .component .book-meaning {
  color: var(--ink);
  font-weight: 500;
}
.sidebar .book.has-components > .components .component .book-conv {
  color: var(--faint);
  font-size: 11px;
  margin-left: 3px;
  font-weight: 400;
}
.sidebar .book.has-components > .components .component.available {
  cursor: pointer;
}
/* 2026-05-23 (Curtis): same treatment for component sub-items — drop
   the background pill; only the text glows. */
.sidebar .book.has-components > .components .component.available:hover .book-meaning {
  color: var(--accent);
}
/* 2026-05-23 (Curtis revision): component activation — only the text
   glows (no background pill, matching the book-level treatment), AND
   the progress-bar indicator lives here, riding the active component
   inside its tabbed parent. As the user reads through chapters the
   bar moves between components (e.g. The Twelve: Hosea → Joel →
   Amos), making it obvious which sub-book they're in. */
.sidebar .book.has-components > .components .component.active .book-meaning {
  color: var(--accent);
  font-weight: 600;
}
.sidebar .book.has-components > .components .component.active::before {
  content: "";
  position: absolute;
  /* Sit on the ul.components border-left line (ul has padding-left:8
     and border-left:1, so the line is at li.component's `left: -8px`).
     The bar overlays that line at 2px width, reading as a thicker
     accent-colored segment just for the active component. */
  left: -8px;
  top: 2px;
  bottom: 2px;
  width: 2px;
  background: var(--rule-strong);
  border-radius: 2px;
}
.sidebar .book.has-components > .components .component.active::after {
  content: "";
  position: absolute;
  left: -8px;
  top: 2px;
  width: 2px;
  height: calc((100% - 4px) * var(--progress, 0));
  background: var(--accent);
  border-radius: 2px;
  transition: height 80ms linear;
}
/* Parent's hover/active styling shouldn't bleed into the nested sub-list:
 * when the user hovers a sub-entry, the parent <li.book> isn't the hover
 * target. Nothing extra needed — CSS specificity already handles this. */

/* Sidebar toggle — sits at the sidebar's top-right corner (near the
   theme toggle) on desktop, slides WITH the sidebar when collapsing
   so it ends up at the viewport's top-left edge. Icon switches
   between ≡ (open) and ← (collapse) via admin-sidebar.js.

   Implementation: position: fixed at left = sidebar width - 50px (so
   it visually sits inside the sidebar's right edge). When the body
   gets .sidebar-collapsed, the sidebar translates -100% (offscreen)
   AND the toggle translates by the same magnitude minus a small
   offset — so the toggle ends up at viewport x ~10. Both share a
   220ms ease transition for a synchronized slide.
*/
.sidebar-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: fixed;
  top: 18px;
  left: calc(var(--sidebar-w) - 50px);
  z-index: 60;
  background: var(--panel-bg);
  border: 1px solid var(--rule);
  color: var(--ink);
  border-radius: 8px;
  width: 36px; height: 36px;
  font-size: 18px;
  cursor: pointer;
  transition: transform 220ms ease, background 120ms ease;
}
.sidebar-toggle:hover { background: var(--accent-soft); }

.sidebar,
.content-wrap {
  transition: transform 220ms ease, margin-left 220ms ease;
}
body.sidebar-collapsed .sidebar {
  transform: translateX(-100%);
  pointer-events: none;
}
body.sidebar-collapsed .sidebar-toggle {
  /* Slide the toggle to the viewport's top-left corner. Magnitude
     matches the sidebar's slide minus a 60px offset so the toggle
     lands at x ~10 (= sidebar-w - 50 + (- sidebar-w + 60)). */
  transform: translateX(calc(-1 * var(--sidebar-w) + 60px));
}
body.sidebar-collapsed .content-wrap {
  margin-left: 0;
}
/* 2026-05-14 (Curtis): do NOT add padding-left on .wrap when the
   sidebar collapses — changing inner padding changes the wrapping
   width and shifts line breaks / verse positions. The .wrap is
   max-width: 720px with `margin: 0 auto`, so it recenters in the
   wider available space without resizing. The toggle button at
   viewport top-left is well outside the centered text column on any
   reasonably wide viewport. */

@media (max-width: 880px) {
  .sidebar { transform: translateX(-100%); transition: transform 220ms ease; box-shadow: var(--panel-shadow); }
  .sidebar.open { transform: translateX(0); }
  .content-wrap { margin-left: 0 !important; }
  .wrap { padding-top: 70px !important; }
  /* Mobile reverts to a simple top-left fixed toggle (sidebar uses
     .sidebar.open for its slide, body.sidebar-collapsed has no
     effect). */
  .sidebar-toggle {
    left: 14px;
    top: 14px;
    transform: none !important;
  }
}

/* ===== Main content ===== */
.content-wrap { margin-left: var(--sidebar-w); }
.wrap { max-width: 720px; margin: 0 auto; padding: 56px 28px 120px; }

/* ===== WIP banner ===== */
.wip-banner {
  max-width: 720px;
  margin: 0 auto;
  padding: 10px 28px 0;
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--muted);
}
.wip-banner .wip-inner {
  display: inline-block;
  padding: 6px 12px;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--accent-soft);
}
.wip-banner .wip-dot {
  display: inline-block;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--accent);
  margin-right: 8px;
  vertical-align: middle;
}
@media (max-width: 760px) {
  .wip-banner { padding-left: 16px; padding-right: 16px; }
}

header.masthead { border-bottom: 1px solid var(--rule); padding-bottom: 28px; margin-bottom: 36px; }
header.masthead h1 {
  font-size: 38px;
  font-weight: 600;
  margin: 0 0 6px;
  letter-spacing: -0.01em;
}
/* 2026-05-17: "Meaning (Traditional)" formatting in the masthead h1
 * — mirrors the canon sidebar's hierarchy so the translation
 * philosophy stays visible the moment the reader enters a book.
 * The meaning text is the primary heading; the traditional name is
 * smaller and muted as orientation context. */
header.masthead h1 .book-meaning {
  font-family: inherit;
  font-weight: 600;
  color: var(--ink);
}
header.masthead h1 .book-conv {
  font-family: inherit;
  font-size: 0.55em;
  font-weight: 500;
  color: var(--muted);
  letter-spacing: 0;
  vertical-align: middle;
  margin-left: 4px;
}
/* 2026-05-23 (Curtis): original-language masthead title in OL view.
   "מְלָכִים א (1 Kings)" / "ΚΑΤΑ ΜΑΘΘΑΙΟΝ (Matthew)" — the script
   form is the primary heading, the English name follows in the same
   muted parenthetical style as the meaning-first .book-conv. Hebrew
   gets RTL via lang/dir attributes set on the span; Greek stays LTR.
   Font is inherited so existing serif h1 styling stays consistent
   across views. */
header.masthead h1 .book-origtitle {
  font-family: inherit;
  font-weight: 600;
  color: var(--ink);
  /* Hebrew RTL via lang="he" dir="rtl" on the span (inline-driven). */
}
/* 2026-05-18: mirror the masthead h1 "Meaning (Traditional)" hierarchy
 * on multi-component section headings so e.g. inside The Twelve the
 * "Jonah" section heads as "Dove (Jonah)" with the same hierarchy. */
.section-heading .book-meaning {
  font-family: inherit;
  font-weight: 600;
  color: inherit;
}
.section-heading .book-conv {
  font-family: inherit;
  font-size: 0.6em;
  font-weight: 500;
  color: var(--muted);
  letter-spacing: 0;
  vertical-align: middle;
  margin-left: 4px;
}
/* 2026-05-18: keep the masthead title legible on narrow viewports —
 * book.meaning strings like "Salvation-of-He-Is" + "(Isaiah)" can
 * overflow at the default 38px on phones. Shrink the h1 a step and
 * give .book-conv whitespace flexibility so it wraps cleanly. */
@media (max-width: 760px) {
  header.masthead h1 { font-size: 30px; }
  header.masthead h1 .book-conv { display: inline-block; }
}
@media (max-width: 480px) {
  header.masthead h1 { font-size: 26px; }
}
header.masthead .sub {
  color: var(--muted);
  font-family: var(--sans);
  font-size: 14px;
  line-height: 1.5;
}

.controls {
  display: flex;
  gap: 18px;
  align-items: center;
  flex-wrap: wrap;
  margin-top: 18px;
  font-family: var(--sans);
  font-size: 13px;
  color: var(--muted);
}
.controls label { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; user-select: none; }
.controls input[type="checkbox"] { accent-color: var(--accent); }
.controls .seg {
  display: inline-flex;
  border: 1px solid var(--rule);
  border-radius: 999px;
  overflow: hidden;
}
.controls .seg button {
  background: transparent;
  border: 0;
  padding: 6px 14px;
  font-family: var(--sans);
  font-size: 13px;
  color: var(--muted);
  cursor: pointer;
}
.controls .seg button.active {
  background: var(--ink);
  color: var(--bg);
}

.legend {
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
  margin-top: 14px;
  font-family: var(--sans);
  font-size: 12px;
  color: var(--muted);
}
.legend .swatch { display: inline-flex; align-items: center; gap: 6px; }
.legend .swatch::before {
  content: "";
  width: 10px; height: 10px;
  border-radius: 50%;
  background: var(--conf-high);
  display: inline-block;
}
.legend .swatch.conf-high::before { background: var(--conf-high); }
.legend .swatch.conf-medium::before { background: var(--conf-medium); }
.legend .swatch.conf-low::before { background: var(--conf-low); }
.legend .swatch.divergent::before { background: var(--divergent); }
.legend .swatch.pending::before { background: var(--pending); }
.legend-note {
  font-family: var(--sans);
  font-size: 11.5px;
  color: var(--muted);
  margin-top: 8px;
  font-style: italic;
}

h2.chapter {
  font-family: var(--sans);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  font-size: 12px;
  color: var(--muted);
  font-weight: 600;
  margin: 56px 0 18px;
  border-top: 1px solid var(--rule);
  padding-top: 28px;
}
h2.chapter:first-of-type { border-top: 0; padding-top: 0; margin-top: 0; }

.verse { margin: 0; padding: 0; }
.vnum {
  color: var(--muted);
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  vertical-align: super;
  line-height: 0;
  margin-right: 4px;
  letter-spacing: 0.04em;
}

.name {
  color: var(--conf-high);
  border-bottom: 1px dotted var(--conf-high);
  cursor: pointer;
  padding: 0 1px;
  transition: background 120ms ease;
}
.name:hover, .name:focus {
  background: var(--conf-high-soft);
  outline: none;
}
.name.conf-high { color: var(--conf-high); border-bottom-color: var(--conf-high); }
.name.conf-high:hover, .name.conf-high:focus { background: var(--conf-high-soft); }
.name.conf-medium { color: var(--conf-medium); border-bottom-color: var(--conf-medium); }
.name.conf-medium:hover, .name.conf-medium:focus { background: var(--conf-medium-soft); }
.name.conf-low { color: var(--conf-low); border-bottom-color: var(--conf-low); }
.name.conf-low:hover, .name.conf-low:focus { background: var(--conf-low-soft); }
.name.pending {
  color: var(--pending);
  border-bottom-color: var(--pending);
  font-style: italic;
}
body.no-marks .name {
  color: inherit;
  border-bottom: 0;
  background: transparent;
  cursor: default;
  font-style: normal;
}

/* P3.12-clickable-spans: subtle affordance on plain source spans
 * (kind:source, NOT protected_name — proper-name spans use the
 * brighter .name treatment above). On hover the wrapper gets a
 * faint accent background; the underlying text stays in its normal
 * color so the visual change is gentle in dense paragraphs.
 *
 * The :not(.protected-name) selector keeps the proper-name source
 * spans from getting double affordance (both .name and .source-span
 * hover would otherwise stack); proper-name spans rely on the inner
 * .name's hover state. */
.source-span {
  cursor: pointer;
  border-radius: 2px;
  padding: 0 1px;
  transition: background 120ms ease;
}
.source-span:not(.protected-name):hover,
.source-span:not(.protected-name):focus {
  background: var(--accent-soft);
}
body.no-marks .source-span {
  cursor: default;
  background: transparent;
}

/* Translator-supplied content: structural-english, punctuation,
 * discourse-markers, etc. Click opens an explanation panel. The
 * affordance is even quieter than .source-span — a dotted underline
 * on hover, no background — because supplied content is by design
 * less semantically loaded than source-anchored words. Punctuation
 * supplied spans skip the underline because punctuation glyphs are
 * too small to underline cleanly. */
.supplied-span {
  cursor: pointer;
  padding: 0 1px;
  transition: background 120ms ease;
}
.supplied-span:not([data-supplied-category="punctuation"]):hover,
.supplied-span:not([data-supplied-category="punctuation"]):focus {
  background: var(--rule);
  border-bottom: 1px dotted var(--muted);
}
.supplied-span[data-supplied-category="punctuation"]:hover {
  background: var(--rule);
}
body.no-marks .supplied-span {
  cursor: default;
  background: transparent;
  border-bottom: 0;
}

/* Multi-morph source panel: stacked per-morph sections, each headed
 * with the morph_id in monospace + a separator rule. */
.multi-morph-meta {
  font-size: 12px;
  color: var(--muted);
  margin-bottom: 12px;
}
.morph-section {
  border-top: 1px solid var(--rule);
  padding-top: 12px;
  margin-top: 12px;
}
.morph-section:first-child {
  border-top: 0;
  padding-top: 0;
  margin-top: 0;
}
.morph-section .morph-section-head {
  font-size: 12px;
  color: var(--muted);
  margin-bottom: 8px;
}
.morph-section .morph-section-head code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  font-size: 11.5px;
  color: var(--ink);
}

/* Supplied-span panel: small explanation. */
.supplied-meta {
  font-size: 12px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: 8px;
}
.supplied-body p {
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink);
  margin: 0;
}

/* (P3.7-view-aware-rendering retired the body.original-view +
 * .name/.orig wrapper toggle. The Meaning-First and Original views
 * now consume different SPAN_DATA layers — smoothed vs rigid — and
 * render the appropriate proper-name text directly into a single
 * `.name` element. The .orig class has no remaining users.) */

/* ===== Side panel (translation note) ===== */
.panel {
  position: fixed;
  top: 0; right: 0;
  width: min(440px, 92vw);
  height: 100%;
  background: var(--panel-bg);
  box-shadow: var(--panel-shadow);
  transform: translateX(100%);
  transition: transform 220ms ease;
  z-index: 50;
  overflow-y: auto;
  padding: 36px 32px 60px;
}
.panel.open { transform: translateX(0); }
/* 2026-05-23 (Curtis): wide-mode panel is a TRUE SPLIT SCREEN, not
   an overlay. The reader's .content-wrap shifts left to make room
   (body.panel-split is set/cleared from app.js), so the user sees
   both the biblical text and the concordance side-by-side. Clicking
   a verse on the right scrolls the reader on the left without
   losing the study surface.
   Mobile (≤880px) keeps takeover-style for screen-space reasons. */
.panel.panel-wide {
  width: var(--panel-wide-width, clamp(520px, 50vw, 720px));
  box-shadow: -1px 0 0 var(--rule);  /* thin seam instead of dropshadow */
  /* 2026-05-24 (overnight P4, Curtis): seam-flush with the reader-nav.
     The nav's bottom edge is stamped onto --reader-nav-h by
     syncReaderNavHeight() (app.js), so the panel always sits exactly
     beneath the nav regardless of how the nav resizes (chip wrap on
     narrow viewports, admin-tabs strip, etc.). Falls back to 125px
     for sessions where the var hasn't been set yet (first paint). */
  top: var(--reader-nav-h, 125px);
  height: calc(100vh - var(--reader-nav-h, 125px));
}

/* 2026-05-24 overnight P6 (Curtis): right-edge pull-tab. Closed
   state: floats on the viewport's right edge, low-attention but
   discoverable. Open state: rides the panel's left edge as part of
   .panel-edge-controls and exposes close + history affordances. */
.reader-pull-tab {
  position: fixed;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 18px;
  height: 56px;
  border: 1px solid var(--rule);
  border-right: 0;
  border-radius: 8px 0 0 8px;
  background: var(--panel-bg);
  color: var(--muted);
  cursor: pointer;
  z-index: 44;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  opacity: 0.7;
  transition: opacity 160ms ease, color 160ms ease, background 160ms ease;
}
.reader-pull-tab:hover {
  opacity: 1;
  color: var(--ink);
  background: var(--bg);
}
/* When the panel is open, hide the standalone pull-tab — the edge
   controls inside the panel take over. */
body.panel-split .reader-pull-tab,
body:has(.panel.open) .reader-pull-tab {
  display: none;
}
@media (max-width: 880px) {
  /* Mobile: pull-tab hugs the right edge of the screen at a slightly
     smaller height so it doesn't fight thumb-zone gestures. */
  .reader-pull-tab { width: 16px; height: 44px; }
}

/* Edge controls cluster on the panel's left edge — only visible
   when the panel is open. Sits at viewport vertical center. */
.panel-edge-controls {
  position: absolute;
  top: 50%;
  left: -19px;
  transform: translateY(-50%);
  display: none;
  flex-direction: column;
  gap: 4px;
  z-index: 41;
}
.panel.open .panel-edge-controls { display: flex; }
.panel-edge-btn {
  width: 20px;
  height: 28px;
  border: 1px solid var(--rule);
  border-right: 0;
  border-radius: 6px 0 0 6px;
  background: var(--panel-bg);
  color: var(--muted);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: color 120ms ease, background 120ms ease;
}
.panel-edge-btn:hover {
  color: var(--ink);
  background: var(--bg);
}

/* 2026-05-24 overnight P7 (Curtis): drag-to-resize handle on the
   panel's left edge. Invisible until hover so it doesn't clutter,
   but always live for dragging. */
.panel-resize-handle {
  position: absolute;
  top: 0;
  left: -3px;
  width: 6px;
  height: 100%;
  cursor: ew-resize;
  z-index: 40;
  background: transparent;
  transition: background 120ms ease;
}
.panel-resize-handle:hover,
body.panel-resizing .panel-resize-handle {
  background: linear-gradient(to right, transparent, var(--rule-strong), transparent);
}
body.panel-resizing {
  cursor: ew-resize !important;
  user-select: none;
}
body.panel-resizing .panel,
body.panel-resizing .content-wrap {
  transition: none !important;
}
.panel-resize-handle { display: none; }
.panel.panel-wide .panel-resize-handle { display: block; }

/* 2026-05-24 overnight P8 (Curtis): drawer animation polish — gentler
   open/close transitions, hover-lift on the pull-tab, fade-in on the
   edge controls. The existing panel transitions used a snap easing;
   bump to a cubic-bezier with a touch of overshoot for the open
   direction and a calm decel for close. */
.panel.panel-wide {
  transition:
    transform 280ms cubic-bezier(0.16, 1.06, 0.36, 1),
    width 220ms cubic-bezier(0.22, 1, 0.36, 1);
}
body.panel-split .content-wrap {
  transition: margin-right 260ms cubic-bezier(0.22, 1, 0.36, 1);
}
.reader-pull-tab {
  transition:
    opacity 220ms ease,
    color 160ms ease,
    background 160ms ease,
    width 160ms ease,
    box-shadow 220ms ease;
}
.reader-pull-tab:hover {
  width: 22px;
  box-shadow: -2px 0 8px -2px rgba(28, 25, 23, 0.18);
}
.panel-edge-controls {
  opacity: 0;
  transition: opacity 220ms ease 80ms;
}
.panel.open .panel-edge-controls { opacity: 0.8; }
.panel.open .panel-edge-controls:hover { opacity: 1; }
body.panel-split .content-wrap {
  margin-right: var(--panel-wide-width, clamp(520px, 50vw, 720px));
  transition: margin-right 220ms ease;
}
@media (max-width: 880px) {
  .panel.panel-wide { width: 100vw; max-width: 100vw; }
  body.panel-split .content-wrap { margin-right: 0; }  /* mobile: takeover, no shift */
}
.panel .close {
  position: absolute;
  top: 14px; right: 14px;
  background: transparent;
  border: 0;
  font-size: 22px;
  color: var(--muted);
  cursor: pointer;
  line-height: 1;
}
.panel h3 {
  font-family: var(--serif);
  font-size: 32px;
  margin: 0 0 4px;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.panel .translit {
  font-family: var(--sans);
  color: var(--muted);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: 14px;
}
.panel .heb {
  font-family: var(--hebrew);
  font-size: 30px;
  direction: rtl;
  margin: 4px 0 14px;
  color: var(--ink);
}
/* P2.12: Greek variant for the panel's source-script display. The
 * `.heb` class name is legacy (predates Greek support) but its role
 * is "the source-script display block in a panel". Greek MACULA
 * books emit lang="grc" dir="ltr" via langAttrsFor; this attribute
 * selector swaps the font + direction without renaming the class. */
.panel .heb[lang="grc"] {
  font-family: var(--greek);
  direction: ltr;
}
.panel dd[lang="grc"] {
  font-family: var(--greek);
  direction: ltr;
}
.panel dl {
  font-family: var(--sans);
  font-size: 13px;
  margin: 0 0 16px;
}
.panel dt {
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 10.5px;
  font-weight: 600;
  margin-top: 12px;
}
.panel dd {
  margin: 3px 0 0;
  line-height: 1.5;
  color: var(--ink);
}
.panel .badge {
  display: inline-block;
  font-family: var(--sans);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent);
  margin: 0 6px 4px 0;
}
.panel .badge.divergent { background: var(--divergent-soft); color: var(--divergent); }
.panel .badge.pending { background: transparent; border: 1px solid var(--pending); color: var(--pending); }

.panel .section-block {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid var(--rule);
}
.panel .section-block:first-of-type { border-top: 0; padding-top: 0; }
.panel .section-label {
  font-family: var(--sans);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 10.5px;
  font-weight: 700;
  color: var(--muted);
  margin-bottom: 8px;
}

/* v3 morph-panel layout (Case A + Case B).
 *
 * Case A header: <h3 class="panel-english"> + <div class="panel-surface">.
 * Case B header: <h3 class="panel-mfb"> + <div class="panel-bsb"> + <div class="panel-surface">.
 *
 * The v3 spec calls for ~22px serif on h3 (down from the legacy 32px);
 * the panel-bsb subtitle is 16px serif in secondary color; panel-surface
 * is 18px serif in secondary color. Hebrew/Greek surface uses the
 * existing Hebrew/Greek font stacks via lang attributes (already wired
 * by langAttrsFor in app.js). */
.panel h3.panel-english,
.panel h3.panel-mfb {
  font-size: 22px;
  margin: 0 0 4px;
  font-weight: 600;
  letter-spacing: -0.005em;
}
.panel .panel-bsb {
  font-family: var(--serif);
  font-size: 16px;
  color: var(--muted);
  margin: 0 0 4px;
  line-height: 1.4;
}
.panel .panel-surface {
  font-family: var(--serif);
  font-size: 18px;
  color: var(--muted);
  margin: 0 0 14px;
  line-height: 1.4;
}
/* Hebrew (and Greek) surface lines in the panel are short single-word
 * or phrase displays — not running verse text. Left-align them so the
 * surface sits under the English in the header / Word Details rows.
 * `direction: rtl` is still needed to keep multi-glyph Hebrew sequences
 * in correct character order; `text-align: left` overrides the default
 * RTL alignment that would otherwise push the word to the right edge
 * of its container. Same fix applies to the panel-dd-source dd rows
 * below — kept consistent across header + Word Details. */
.panel .panel-surface[lang="he"]  { font-family: var(--hebrew); direction: rtl; text-align: left; font-size: 22px; color: var(--ink); }
.panel .panel-surface[lang="grc"] { font-family: var(--greek);  direction: ltr; font-size: 20px; color: var(--ink); }

/* 2026-05-19 (Curtis): cross-language line beneath the source-
 * language surface in the word panel. LXX-sourced in both
 * directions:
 *   OT panel → "LXX" label + Greek (the Septuagint translation)
 *   NT panel → "Hebrew (LXX)" label + Hebrew (the Hebrew word
 *               this Greek lemma translates in the LXX)
 * Label sits in muted sans-serif on the left of the script text. */
.panel .panel-xlang {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: -8px 0 14px;
  line-height: 1.4;
}
.panel .panel-xlang-label {
  font-family: var(--sans);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
}
.panel .panel-xlang-text {
  font-size: 18px;
  color: var(--ink);
}
.panel .panel-xlang[lang="grc"] .panel-xlang-text { font-family: var(--greek);  font-size: 18px; direction: ltr; }
.panel .panel-xlang[lang="he"]  .panel-xlang-text { font-family: var(--hebrew); font-size: 20px; direction: rtl; }

/* Phase 11.5 — popup note for superscripts carrying Mitchell-citation
 * (LXX-eschatological readings of lamnatseah / gittith / alamot /
 * shoshannim). Sits between the panel-surface line and the morph
 * details list. */
.panel .panel-note {
  margin-top: 12px;
  padding: 10px 12px;
  background: rgba(174, 130, 60, 0.06);
  border-left: 3px solid var(--accent, #ae823c);
  border-radius: 2px;
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink);
}
.panel .panel-note em { font-style: italic; }
.panel .panel-note strong { font-weight: 600; }

/* Word Details section, gloss-headed. One per morph in multi-morph
 * spans, divided by a dashed top border on every section after the
 * first. The CSS-level .word-details-block--first reset overrides
 * .section-block's first-of-type border-removal cleanly: we still
 * want a dashed separator between morph blocks but not above the
 * first one. */
.panel .word-details-block { border-top: 1px dashed var(--rule); }
.panel .word-details-block--first { border-top: 1px solid var(--rule); }
.panel .word-details-block:first-of-type { border-top: 1px solid var(--rule); }
.panel .gloss-heading { color: var(--muted); }
.panel .gloss-heading .gloss-heading-gloss {
  color: var(--ink);
  text-transform: none;
  letter-spacing: 0;
  font-weight: 600;
  font-size: 13px;
  margin-left: 4px;
}
.panel dd.panel-dd-source { font-size: 18px; line-height: 1.3; }
.panel dd.panel-dd-source[lang="he"]  { font-family: var(--hebrew); direction: rtl; text-align: left; font-size: 22px; }
.panel dd.panel-dd-source[lang="grc"] { font-family: var(--greek);  direction: ltr; }
.panel dd.panel-dd-lemma { font-size: 18px; line-height: 1.3; }
.panel dd.panel-dd-lemma[lang="he"]  { font-family: var(--hebrew); direction: rtl; text-align: left; font-size: 22px; }
.panel dd.panel-dd-lemma[lang="grc"] { font-family: var(--greek);  direction: ltr; }

/* Translation Note block (Case B only). Tinted background so the
 * editorial reasoning visually separates from the MACULA-derived
 * Word Details sections. */
/* Reasoning block (was 'translation note'). 2026-05-14 redesign:
 * background tint corresponds to confidence level — green for High,
 * amber for Medium, red for Low. Pending entries are neutral gray. */
.panel .tn-block {
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 12px 16px;
  border-top: 1px solid var(--rule);
}
#panel-body[data-confidence="high"] .tn-block {
  background: var(--conf-high-soft, #e8f4e3);
  border-color: rgba(36, 78, 29, 0.18);
}
#panel-body[data-confidence="medium"] .tn-block {
  background: var(--conf-medium-soft, #fbf1dc);
  border-color: rgba(109, 71, 16, 0.18);
}
#panel-body[data-confidence="low"] .tn-block {
  background: var(--conf-low-soft, #f9e0d8);
  border-color: rgba(107, 31, 16, 0.20);
}
#panel-body[data-confidence="pending"] .tn-block {
  background: rgba(127, 127, 127, 0.06);
  border-color: var(--rule);
}
.panel .tn-block .tn-meta { margin-bottom: 10px; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.panel .tn-block .tn-fields { margin: 4px 0 10px; font-family: var(--sans); font-size: 13px; }
.panel .tn-block .tn-fields dt { color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; font-size: 10.5px; font-weight: 600; margin-top: 6px; }
.panel .tn-block .tn-fields dd { margin: 2px 0 0; }
.panel .tn-block .body { font-family: var(--serif); font-size: 15px; line-height: 1.55; color: var(--ink); }

/* 2026-05-23 (Curtis): collapsible Root/Etymology + Reasoning bodies.
   Short by default — Root shows first sentence, Reasoning shows
   first 3 — disclosure triangle expands to full content. <details>
   provides the native expand/collapse; CSS hides the native marker
   and replaces with our own chevron so it matches the rest of the
   panel chrome. */
.panel .collapsible-body { display: block; cursor: pointer; }
.panel .collapsible-body > .collapsible-summary {
  list-style: none;   /* hide default disclosure marker (Firefox) */
  position: relative;
  padding-right: 22px;
  cursor: pointer;
}
.panel .collapsible-body > .collapsible-summary::-webkit-details-marker {
  display: none;      /* hide default disclosure marker (Chrome/Safari) */
}
.panel .collapsible-body > .collapsible-summary::after {
  content: "▸";
  position: absolute;
  right: 4px;
  top: 0;
  color: var(--muted);
  font-size: 11px;
  transition: transform 140ms ease;
}
.panel .collapsible-body[open] > .collapsible-summary::after {
  transform: rotate(90deg);
}
/* "…" hint at the end of the truncated summary — only when collapsed. */
.panel .collapsible-body > .collapsible-summary .collapsible-more {
  color: var(--muted);
}
.panel .collapsible-body[open] > .collapsible-summary .collapsible-more {
  display: none;
}
.panel .collapsible-body > .collapsible-rest {
  margin-top: 6px;
}
/* Root-body specific — keeps the same internal padding the
   .root-body had outside the collapsible. */
.panel .root-body.collapsible-body {
  /* Inherits from .root-body's existing rule; nothing extra needed
     beyond the shared collapsible chrome above. */
}

/* Confidence pill — uses existing --conf-{high,medium,low} CSS vars
 * (defined for both light and dark themes earlier in this file). */
.panel .confidence-pill {
  display: inline-block;
  font-family: var(--sans);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  padding: 3px 10px;
  border-radius: 999px;
}
.panel .confidence-pill.conf-high    { background: var(--conf-high-soft);    color: var(--conf-high); }
.panel .confidence-pill.conf-medium  { background: var(--conf-medium-soft);  color: var(--conf-medium); }
.panel .confidence-pill.conf-low     { background: var(--conf-low-soft);     color: var(--conf-low); }
.panel .confidence-pill.conf-pending { background: var(--rule); color: var(--muted); }

/* Raw MACULA dump inside Technical Details — preformatted JSON. Keep
 * the panel scrolling cleanly even when the dump is wide. */
.panel .raw-dump {
  font-family: var(--mono, ui-monospace, "SF Mono", Menlo, monospace);
  font-size: 11.5px;
  line-height: 1.45;
  background: var(--rule);
  padding: 10px 12px;
  border-radius: 4px;
  overflow: auto;
  max-height: 320px;
  margin: 6px 0 14px;
  color: var(--ink);
}
.panel .raw-dump-header {
  font-family: var(--sans);
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  margin-top: 10px;
  margin-bottom: 4px;
}
.panel .section-block .body {
  font-family: var(--serif);
  font-size: 16px;
  line-height: 1.6;
  color: var(--ink);
}
.panel .verse-ref {
  display: inline-block;
  font-family: var(--sans);
  font-size: 11px;
  color: var(--muted);
  background: var(--rule);
  padding: 2px 8px;
  border-radius: 4px;
  margin-bottom: 8px;
  letter-spacing: 0.04em;
}

.scrim {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.18);
  opacity: 0;
  pointer-events: none;
  transition: opacity 220ms ease;
  z-index: 40;
}
.scrim.show { opacity: 1; pointer-events: auto; }

/* Placeholder view for unavailable books */
.placeholder {
  text-align: center;
  padding: 80px 20px;
  color: var(--muted);
  font-family: var(--sans);
}
.placeholder h2 {
  font-family: var(--serif);
  font-size: 32px;
  color: var(--ink);
  margin: 0 0 8px;
  font-weight: 600;
}
.placeholder p { font-size: 15px; line-height: 1.6; max-width: 380px; margin: 0 auto 18px; }
.placeholder button {
  font-family: var(--sans);
  font-size: 13px;
  background: var(--ink);
  color: var(--bg);
  border: 0;
  padding: 8px 16px;
  border-radius: 999px;
  cursor: pointer;
}

/* Loading indicator */
.loading {
  text-align: center;
  padding: 80px 20px;
  color: var(--muted);
  font-family: var(--sans);
  font-size: 13px;
}

footer.foot {
  margin-top: 80px;
  border-top: 1px solid var(--rule);
  padding-top: 22px;
  color: var(--muted);
  font-family: var(--sans);
  font-size: 13px;
  line-height: 1.55;
}

/* ===== P2.5 — source-first pocket clickability =====
 * Subtle hover affordance for plain pockets only. Proper-name pockets
 * already carry .name styling; we don't add anything visible to them.
 * The :not(:has(.name)) selector targets only plain pockets — pocket
 * wrappers that don't contain an inner .name span. */
.pocket:not(:has(.name)) {
  cursor: pointer;
  border-radius: 3px;
  transition: background 100ms ease;
}
.pocket:not(:has(.name)):hover {
  background: rgba(127, 127, 127, 0.06);
}
body.theme-dark .pocket:not(:has(.name)):hover {
  background: rgba(255, 255, 255, 0.05);
}

/* ===== Source-token spans (Original Language view) =====
 * One .source-token per MACULA morph. Plain tokens get a subtle
 * hover affordance mirroring the .pocket pattern above. (Source-
 * Aligned view, which originally also used these tokens, was
 * retired in P3.6; Original Language is the sole consumer now.) */
.source-token:not(:has(.name)) {
  cursor: pointer;
  border-radius: 3px;
  transition: background 100ms ease;
}
.source-token:not(:has(.name)):hover {
  background: rgba(127, 127, 127, 0.06);
}
body.theme-dark .source-token:not(:has(.name)):hover {
  background: rgba(255, 255, 255, 0.05);
}

/* Fallback-text tokens: when MACULA has no `english` or `gloss` for
 * a morph, the renderer falls back to transliteration or a bracketed
 * POS label. Mark those visually as a romanization/placeholder so
 * readers see they're not a primary English equivalent. */
.source-token[data-token-kind="translit"],
.source-token[data-token-kind="pos-fallback"],
.source-token[data-token-kind="empty"] {
  font-style: italic;
  color: var(--muted);
}

/* 2026-05-19 (Curtis): Highlight names also affects Original Language.
 * Source tokens whose morph carries morphology.type === "proper" get
 * the same dotted-underline + accent-color treatment as .name spans
 * in the Latin views. body.no-marks suppresses the highlight here
 * just like it does for .name. */
.source-token[data-proper-name="1"] {
  color: var(--conf-high);
  border-bottom: 1px dotted var(--conf-high);
  padding-bottom: 0;
}
body.no-marks .source-token[data-proper-name="1"] {
  color: inherit;
  border-bottom: 0;
}

/* ===== P2.9 — reader-controls ===========================================
 * Text-size scale, rare-word highlight, tiny gloss line under tokens
 * in Original Language. All three are reader-side controls that toggle
 * via localStorage; the renderer doesn't need to know — body-level
 * data attributes drive CSS, and this section consumes them. */

/* Text-scale: independent per-script. Latin views (Meaning-First-Bible,
 * Original, Source-Aligned) use --reader-text-scale-latin; Original Language
 * uses --reader-text-scale-original. Either may be set independently
 * via app.js + localStorage. */
#reader-body p.verse {
  font-size: calc(20px * var(--reader-text-scale-latin));
}
/* Original Language uses a larger base than Latin so Hebrew at "S"
 * lands roughly where Latin's "L" does — Hebrew letterforms read
 * smaller than Latin at the same nominal size, and the previous
 * shared 20px base was too small even at L for comfortable reading. */
#reader-body p.verse.verse-original-language {
  font-size: calc(27px * var(--reader-text-scale-original));
  line-height: 2;
}
/* P2.12: language-specific font for the Original Language paragraph.
 * Selectors keyed off the paragraph's lang attribute (set by the
 * renderer from the manifest's `language` field). Latin views are
 * unaffected — they don't use .verse-original-language. */
/* 2026-05-19 Phase 15c — Hebrew/Greek visual separation. Beyond
 * just switching font families, give each script the leading + tracking
 * it deserves so the reader perceives Hebrew vs Greek at a glance.
 * Hebrew gets generous line-height (vowel points + cantillation need
 * room above the consonant baseline) and slight letter-spacing.
 * Greek gets tighter line-height and natural tracking — polytonic
 * accents stack horizontally, not vertically. */
#reader-body p.verse.verse-original-language[lang="he"] {
  font-family: var(--hebrew);
  font-size: calc(27px * var(--reader-text-scale-hebrew));
  line-height: 1.95;
  letter-spacing: 0.005em;
  font-feature-settings: "ss01" on;  /* enable cantillation-friendly stylistic set if font has it */
}
#reader-body p.verse.verse-original-language[lang="grc"] {
  font-family: var(--greek);
  font-size: calc(27px * var(--reader-text-scale-greek));
  line-height: 1.6;
  letter-spacing: 0;
}

/* Inline source-token typography: when a Hebrew or Greek source-token
 * span appears INSIDE a Latin-view verse (e.g. a name being shown in
 * its original script as a popover header), use the script-appropriate
 * font. The container's lang attribute already routes correctly; this
 * adds a minor weight nudge for visual presence. */
#reader-body [lang="he"]:not(.verse-original-language),
#reader-body [lang="grc"]:not(.verse-original-language) {
  font-feature-settings: "kern" on;
}

/* P2.11.4: text-size control in the masthead's upper-right.
 * Script-aware — renders A/A/A in Latin views, א/א/א in Original
 * Language — at three progressively larger sizes that visually
 * preview the choice. The button labels themselves communicate
 * what each does, so no separate row label is needed. */
.masthead { position: relative; }
/* 2026-05-19 Phase 15d (Curtis polish): subtle two-letter control,
 * no border, no fill — just the small A and the big A side by side.
 * The user reads the size DIFFERENCE between the two glyphs and
 * understands the direction without any text label or number. */
.text-size-control {
  position: absolute;
  top: 8px;
  right: 0;
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  font-family: var(--serif);
  background: transparent;
}
.text-size-control button.text-size-btn {
  background: transparent;
  border: 0;
  padding: 0;
  color: var(--muted);
  cursor: pointer;
  line-height: 1;
  font-family: inherit;
  transition: color 100ms ease;
}
.text-size-control button.text-size-btn:hover {
  color: var(--ink);
}
.text-size-control button.text-size-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}
.text-size-control button.text-size-btn-smaller { font-size: 11px; }
.text-size-control button.text-size-btn-larger  { font-size: 17px; }
/* Hebrew / Greek glyph variants pull in their writing system's font
 * so the size preview itself is in the script being adjusted. */
.text-size-control button[lang="he"] { font-family: var(--hebrew); }
.text-size-control button[lang="grc"] { font-family: var(--greek); }

/* Rare-word highlight (revised): SUBTLE color shift only — no
 * background, no border, no shadow. The original full-bleed rare
 * tint was visually overwhelming. We just nudge the text color to
 * a warm amber so rare words "pop" without dominating the page. */
:root {
  --rare-text: #8b6512;
}
body.theme-dark {
  --rare-text: #d4b566;
}
/* 2026-05-23 (Curtis): names override rare color. Previously a token
   that was BOTH proper-noun and rare picked up rare's amber color,
   covering the name color. Curtis: "the rarity highlight covers the
   name highlights. that should be the opposite." Adding the
   [data-proper-name="1"] exclusion preserves the proper-noun green
   when both apply. The :has(.name) exclusion was for the Latin views;
   the new exclusion handles Original Language. */
body.show-rare .source-token[data-rare="1"]:not(:has(.name)):not([data-proper-name="1"]) {
  color: var(--rare-text);
}

/* Tiny gloss line under rare Original-Language source-tokens.
 * Per-user (P2.10): tiny-gloss is meaningful as a vocabulary aid,
 * not a translation underlay. So glosses appear ONLY on tokens that
 * are marked rare by the current threshold (data-rare="1") — same
 * threshold the rare-highlight uses. Body must have BOTH .show-tiny-gloss
 * AND the token must have data-rare="1" for the gloss to show.
 * The renderer emits a hidden <span class="tiny-gloss">…</span>
 * inside every Original-Language source-token; CSS reveals only
 * the rare ones. */
.tiny-gloss { display: none; }
body.show-tiny-gloss
  #reader-body p.verse.verse-original-language .source-token[data-rare="1"] {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  vertical-align: top;
  margin-bottom: 4px;
}
body.show-tiny-gloss
  #reader-body p.verse.verse-original-language .source-token[data-rare="1"] .tiny-gloss {
  display: block;
  font-family: var(--sans);
  font-size: 10.5px;
  line-height: 1.15;
  color: var(--muted);
  margin-top: 2px;
  max-width: 7em;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  direction: ltr;
  unicode-bidi: isolate;
}

/* 2026-05-23 (Curtis): Name gloss — parallel rules to the rare-gloss
   pair above, keyed on [data-proper-name="1"] instead of rare. Lets
   proper-noun tokens show their project rendering as a tiny gloss
   regardless of rare-word threshold. Body class is `show-name-gloss`,
   default ON. Gloss text is colored same as the proper-noun chevron
   (--conf-high) so the visual stack reads "highlighted name + its
   meaning-first translation" instead of two unrelated underlines. */
body.show-name-gloss
  #reader-body p.verse.verse-original-language .source-token[data-proper-name="1"] {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  vertical-align: top;
  margin-bottom: 4px;
}
/* 2026-05-24 (overnight P3, Curtis): BSB Name-gloss — same visual
   treatment as the OL gloss above, but keyed on the BSB-view marker
   `.bsb-name-gloss` that renderSpanVerse emits on protected-name
   source spans whose displayed text differs from the project
   rendering. Gated by body[data-view="original_web"].show-name-gloss
   so the markup is inert in every other view. */
.bsb-name-gloss { display: none; }
body[data-view="original_web"].show-name-gloss
  #reader-body p.verse .source-span.protected-name {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  vertical-align: top;
  margin-bottom: 4px;
}
body[data-view="original_web"].show-name-gloss
  #reader-body p.verse .source-span.protected-name .bsb-name-gloss {
  display: block;
  font-family: var(--sans);
  font-size: 10.5px;
  line-height: 1.15;
  color: var(--conf-high);
  margin-top: 2px;
  max-width: 9em;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
body.show-name-gloss
  #reader-body p.verse.verse-original-language .source-token[data-proper-name="1"] .tiny-gloss {
  display: block;
  font-family: var(--sans);
  font-size: 10.5px;
  line-height: 1.15;
  color: var(--conf-high);
  margin-top: 2px;
  max-width: 9em;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  direction: ltr;
  unicode-bidi: isolate;
}

/* P2.10: sidebar-resident reader controls. Sits between the modes
 * nav and the canon list so it's accessible from any reader scroll
 * position (the sidebar is a sticky aside). Subtle, low-contrast. */
.sidebar-reader-controls {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 14px 0 18px;
  padding: 12px 14px;
  border: 1px solid var(--rule);
  border-radius: 6px;
  background: rgba(127, 127, 127, 0.03);
  font-family: var(--sans);
  font-size: 12px;
  color: var(--muted);
}
.sidebar-reader-controls .src-control-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  flex-wrap: wrap;
}
.sidebar-reader-controls .src-control-label {
  flex: 0 0 auto;
}
.sidebar-reader-controls select {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 60%;
  padding: 3px 4px;
  font-size: 11px;
  font-family: var(--sans);
  color: var(--ink);
  background: var(--bg);
  border: 1px solid var(--rule-strong);
  border-radius: 4px;
  cursor: pointer;
}
.sidebar-reader-controls label {
  display: inline-flex;
  gap: 6px;
  align-items: center;
  cursor: pointer;
}
.sidebar-reader-controls label:has(input:disabled),
.sidebar-reader-controls .src-control-row:has(select:disabled) {
  opacity: 0.4;
  cursor: not-allowed;
}
.sidebar-reader-controls .src-control-hint {
  font-style: italic;
  font-size: 10px;
  color: var(--faint);
}

/* Reader-view tabs stacked vertically inside the sidebar. The
 * masthead used a horizontal pill group; here labels are too long
 * for that, and the sidebar is the natural home for navigation-
 * adjacent controls anyway. */
.sidebar-reader-controls .seg-views {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.sidebar-reader-controls .seg-views button {
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 5px 12px;
  font-size: 12px;
  color: var(--ink);
  cursor: pointer;
  font-family: var(--sans);
  text-align: center;
  transition: background 100ms ease, border-color 100ms ease;
}
.sidebar-reader-controls .seg-views button:hover:not(.active) {
  background: rgba(127, 127, 127, 0.05);
}
.sidebar-reader-controls .seg-views button.active {
  background: var(--accent-soft);
  color: var(--ink);
  border-color: var(--accent-soft);
}
.sidebar-reader-controls .src-control-divider {
  height: 1px;
  background: var(--rule);
  margin: 4px 0 2px;
}

/* Confidence legend visibility — only meaningful in Meaning-First-Bible
 * view. The masthead always renders the legend; CSS hides it for the
 * three non-MFB views via body[data-view] which app.js keeps in sync
 * with CURRENT_VIEW. Solves the Original↔MFB transition (no re-render)
 * leaving the legend stuck in the wrong state. */
body:not([data-view="meaning_first"]) .legend,
body:not([data-view="meaning_first"]) .legend-note {
  display: none;
}

/* ===========================================================================
 * P5 — Passage notes (book / chapter / verse).
 *
 * Three layers of clickable notes overlaid on the reader. Markers go on
 * elements present in the existing renderers — the .vnum (verse number),
 * h2.chapter (chapter heading), and book-name elements (h1 for single-
 * component canon entries; h2.section-heading for components within a
 * multi-component canon entry — both carry data-passage-notes-book).
 *
 * Marker is a faint color shift on the element itself — small enough that
 * straight-through reading does not notice it, visible enough that
 * scanning for notes picks it out. The verse number / chapter heading /
 * section heading defaults to var(--muted); has-notes shifts ~35% toward
 * var(--ink) via color-mix. The masthead h1 defaults to var(--ink); has-
 * notes shifts ~12% toward var(--accent). Hover is a deliberate user
 * action so it gets a more pronounced treatment (subtle accent-soft
 * background tint). body.no-marks suppresses both the shift and the
 * cursor (consistent with the existing proper-noun marker policy).
 *
 * The earlier dot-marker treatment (a7d63ea) was visually loud against
 * the verse-number stream; replaced here with a quieter color shift.
 *
 * See notes/PASSAGE_NOTES_SCHEMA.md.
 * =========================================================================== */

.vnum.has-notes,
.chapter.has-notes,
.section-heading.has-notes,
header.masthead h1.has-notes {
  cursor: pointer;
  transition: color 120ms ease, background 120ms ease;
}

/* Color shift: per-element-family because the default colors differ.
 * vnum + h2.chapter default to var(--muted) (small grey-brown);
 * shifting 30% toward var(--ink) gives a subtle perceptible darkening
 * (~10% absolute lightness delta in oklch space). Conservative by
 * design — straight-through reading shouldn't notice; scanning for
 * notes should pick it out. The section-heading and masthead h1 are
 * already at var(--ink) at full strength, so darkening would be a
 * no-op — instead shift 25% toward var(--accent) for a faint
 * warming. */
.vnum.has-notes,
.chapter.has-notes {
  color: color-mix(in oklch, var(--muted), var(--ink) 30%);
}
.section-heading.has-notes,
header.masthead h1.has-notes {
  color: color-mix(in oklch, var(--ink), var(--accent) 25%);
}

/* Hover is deliberate — accent-soft background tint with a small
 * inline-block padding so it reads as a nudge, not an underline. */
.vnum.has-notes:hover,
.vnum.has-notes:focus,
.chapter.has-notes:hover,
.chapter.has-notes:focus,
.section-heading.has-notes:hover,
.section-heading.has-notes:focus,
header.masthead h1.has-notes:hover,
header.masthead h1.has-notes:focus {
  background: var(--accent-soft);
  color: var(--accent);
  outline: none;
  border-radius: 3px;
}

/* no-marks: suppress the marker color and the pointer cursor entirely. */
body.no-marks .vnum.has-notes,
body.no-marks .chapter.has-notes,
body.no-marks .section-heading.has-notes,
body.no-marks header.masthead h1.has-notes {
  color: inherit;
  cursor: text;
}
body.no-marks .vnum.has-notes:hover,
body.no-marks .chapter.has-notes:hover,
body.no-marks .section-heading.has-notes:hover,
body.no-marks header.masthead h1.has-notes:hover {
  background: transparent;
  color: inherit;
}

/* Modal — used for chapter intros + book intros. Verse notes use the
 * existing side #panel so the surrounding reading text stays visible. */
.modal-scrim {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  z-index: 90;
  opacity: 0;
  pointer-events: none;
  transition: opacity 150ms ease;
}
.modal-scrim.show {
  opacity: 1;
  pointer-events: auto;
}
.modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) scale(0.96);
  width: min(92vw, 640px);
  max-height: 85vh;
  background: var(--bg);
  color: var(--ink);
  border: 1px solid var(--rule);
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.35);
  padding: 36px 32px 32px;
  overflow-y: auto;
  z-index: 100;
  opacity: 0;
  pointer-events: none;
  transition: opacity 150ms ease, transform 150ms ease;
}
.modal.open {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
  pointer-events: auto;
}
.modal .close {
  position: absolute;
  top: 8px;
  right: 12px;
  background: transparent;
  border: 0;
  font-size: 28px;
  line-height: 1;
  color: var(--muted);
  cursor: pointer;
  padding: 4px 8px;
}
.modal .close:hover { color: var(--ink); }
.modal h3 {
  font-family: var(--serif);
  font-size: 24px;
  font-weight: 600;
  margin: 0 0 4px;
}
.modal .modal-sub {
  font-family: var(--sans);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--muted);
  margin-bottom: 18px;
}

/* Passage-notes content (rendered inside #panel for verses, #modal for
 * chapter/book). Section headings, kind pills, paragraphs, lists. */
.passage-notes-body h4 {
  font-family: var(--serif);
  font-size: 17px;
  font-weight: 600;
  margin: 22px 0 10px;
  color: var(--ink);
}
.passage-notes-body h4:first-child { margin-top: 0; }
.passage-notes-body p {
  font-family: var(--serif);
  font-size: 15px;
  line-height: 1.55;
  margin: 0 0 12px;
  color: var(--ink);
}
.passage-notes-body ul {
  font-family: var(--serif);
  font-size: 15px;
  line-height: 1.55;
  margin: 8px 0 14px;
  padding-left: 22px;
}
.passage-notes-body li { margin: 4px 0; }
.passage-notes-body strong { font-weight: 700; }
.passage-notes-body em { font-style: italic; }

/* 2026-05-23 (Curtis): panel "Find this word" action row. Buttons
   sit at the bottom of the openPanel popover; each routes to either
   mfbSearch (highlight in current chapter) or mfbConcordance (full
   cross-book lookup modal). */
.panel-actions {
  margin-top: 18px;
}
.panel-action-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 6px;
}
.panel-action-btn {
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 0.02em;
  padding: 6px 12px;
  border: 1px solid var(--rule);
  background: var(--panel-bg);
  color: var(--ink);
  border-radius: 999px;
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease;
}
.panel-action-btn:hover {
  background: var(--accent-soft, var(--panel-bg));
  border-color: var(--rule-strong, var(--rule));
}

/* Concordance modal — verse list with highlighted hits. */
.concordance-status {
  font-family: var(--sans);
  font-size: 12px;
  color: var(--muted);
  margin-bottom: 14px;
  font-style: italic;
}
.concordance-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.concordance-item {
  padding: 10px 12px;
  margin: 0 -12px;
  border-radius: 6px;
  cursor: pointer;
  display: grid;
  grid-template-columns: 110px 1fr;
  gap: 12px;
  align-items: baseline;
  transition: background 100ms ease;
}
.concordance-item:hover {
  background: var(--accent-soft, rgba(0,0,0,0.04));
}
.concordance-item + .concordance-item {
  border-top: 1px solid var(--rule);
}
.concordance-ref {
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  letter-spacing: 0.02em;
}
.concordance-excerpt {
  font-family: var(--serif);
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink);
}
.concordance-hit {
  background: rgba(255, 213, 0, 0.55);
  color: inherit;
  padding: 0 2px;
  border-radius: 2px;
}
body.theme-dark .concordance-hit {
  background: rgba(255, 213, 0, 0.35);
}

.passage-notes-body .note + .note {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid var(--rule);
}
.passage-notes-body .note-kind {
  display: inline-block;
  font-family: var(--sans);
  font-size: 9.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--muted);
  background: var(--accent-soft);
  padding: 3px 9px;
  border-radius: 999px;
  margin-bottom: 10px;
}
.passage-notes-body .note-kind.kind-narrative   { color: var(--accent); }
.passage-notes-body .note-kind.kind-lexical     { color: var(--conf-high); background: var(--conf-high-soft); }
.passage-notes-body .note-kind.kind-structural  { color: var(--conf-medium); background: var(--conf-medium-soft); }
.passage-notes-body .note-kind.kind-intertextual{ color: var(--divergent); background: var(--divergent-soft); }
.passage-notes-body .note-kind.kind-teaching    { color: var(--pending); }

/* ===== Inspector-style popover sections (2026-05-14) ===== */
.panel .panel-confidence-row {
  display: flex;
  gap: 8px;
  align-items: center;
  margin: 8px 0 4px;
  flex-wrap: wrap;
}
.panel .root-block .root-body {
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: 6px;
  padding: 10px 14px;
  font-family: var(--serif);
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink);
}
.panel .alt-block {
  background: rgba(127, 127, 127, 0.04);
  border-radius: 6px;
  padding: 0;
}
.panel .alt-block > .section-label-summary {
  cursor: pointer;
  padding: 8px 12px;
  list-style: none;
  user-select: none;
}
.panel .alt-block > .section-label-summary::-webkit-details-marker { display: none; }
.panel .alt-block > .section-label-summary::before {
  content: "▸";
  display: inline-block;
  margin-right: 6px;
  font-size: 10px;
  transition: transform 0.1s;
}
.panel .alt-block[open] > .section-label-summary::before { transform: rotate(90deg); }
.panel .alt-block .alt-list {
  list-style: none;
  padding: 4px 14px 12px;
  margin: 0;
}
.panel .alt-block .alt-list > li {
  padding: 6px 0;
  border-top: 1px dashed var(--rule);
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-soft, var(--ink));
}
.panel .alt-block .alt-list > li:first-child { border-top: 0; }
.panel .alt-block .alt-rendering {
  font-weight: 600;
  color: var(--ink);
  margin-right: 4px;
}
.panel .alt-block .alt-sep { color: var(--muted); margin-right: 4px; }
.panel .alt-block .alt-case { color: var(--muted); }
.panel .ne-block .ne-body {
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: 6px;
  padding: 10px 14px;
}
.panel .ne-block .ne-line {
  margin: 0 0 4px;
  font-size: 13px;
  color: var(--ink-soft, var(--ink));
}
.panel .ne-block .ne-ref {
  margin: 0;
  font-size: 12px;
  color: var(--muted);
}
.panel .ne-block .ne-ref code {
  font-family: var(--mono, ui-monospace, monospace);
  background: rgba(127, 127, 127, 0.08);
  padding: 1px 5px;
  border-radius: 3px;
}

/* ===== Popover typography harmonization (2026-05-14) ===== */
/* Goal: a single coherent type scale across the popover. Header takes
 * the rendering big; section labels are uniform small caps; section
 * bodies are uniformly 13.5px sans (or 14px serif for prose). */

.panel .section-label,
.panel .alt-block > .section-label-summary {
  font-family: var(--sans);
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  margin: 0 0 8px;
  padding-top: 0;
}
.panel .tn-block .body,
.panel .root-block .root-body {
  font-family: var(--serif);
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink);
}
.panel .ne-block .ne-line {
  font-family: var(--serif);
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--ink);
}
.panel .alt-block .alt-list > li {
  font-family: var(--sans);
  font-size: 13px;
  line-height: 1.5;
}
.panel .alt-block .alt-rendering {
  font-family: var(--serif);
  font-size: 13.5px;
}
.panel .panel-bsb {
  font-family: var(--sans);
  font-size: 13px;
  color: var(--muted);
}
.panel h3.panel-mfb {
  font-family: var(--serif);
  font-size: 22px;
  font-weight: 700;
  line-height: 1.15;
  color: var(--ink);
  margin: 0 0 4px;
}

/* ===== Floating reader navigation panel — 2026-05-18 (Curtis) =====
   Full-width panel slides down from above the viewport when summoned.
   Same "emerge from behind a seam" pattern as the chapter rail and
   word panel: hidden by default, the panel's bottom border acts as
   the seam line. More real estate than a centered pill — back/
   forward, search, size pills now, with room for future features
   (filters, jumps, render switchers, etc.). */
.reader-nav {
  position: fixed;
  top: 0;
  /* Respect the sidebar's frame — panel starts at the sidebar's
     right border, never covers it. The sidebar's existing
     border-right serves as the panel's visual left edge. */
  left: var(--sidebar-w);
  right: 0;
  z-index: 45;
  display: flex;
  /* 2026-05-19 (Curtis revision 2): align children to the top edge of
     the bar — the search-column is taller (input + view-picker strip),
     so flex-start keeps the back/forward arrows, Highlight names, and
     size pills "raised up" at the input's level rather than vertically
     centered against the whole column. */
  align-items: flex-start;
  gap: 12px;
  padding: 8px 18px 4px;
  background: var(--bg);
  border-bottom: 1px solid var(--rule);
  /* Soft inset on the bottom edge — gives a sense the panel sits
     a layer behind the seam (its bottom border), not floating in
     front. Matches the chapter-rail "paper underneath" feel. */
  box-shadow: inset 0 -6px 8px -6px rgba(28,25,23,0.10);
  font-family: var(--sans);
  /* Default: tucked entirely above the viewport. */
  transform: translateY(-100%);
  pointer-events: none;
  transition:
    transform 320ms cubic-bezier(0.22, 1, 0.36, 1),
    left      220ms cubic-bezier(0.22, 1, 0.36, 1);
}
/* When the admin sidebar-collapse is active, the sidebar slides
   off-screen — the nav panel should fill the freed space so it
   still spans edge-to-edge of the content area. Bottom border (the
   seam) extends all the way; the inner content gets extra left
   padding to clear the .sidebar-toggle ≡ button that lives at
   viewport x≈10 in collapsed state. */
body.sidebar-collapsed .reader-nav,
body.sidebar-collapsed .reader-nav-tap-zone {
  left: 0;
}
body.sidebar-collapsed .reader-nav {
  padding-left: 60px;
}
body.reader-nav-visible .reader-nav {
  transform: translateY(0);
  pointer-events: auto;
}
@media (max-width: 880px) {
  .reader-nav {
    /* On mobile the sidebar is hidden by default; the panel spans
       full width. Left padding clears the mobile .sidebar-toggle ≡
       at left:14 + 36 = x:50. */
    left: 0;
    padding: 8px 12px 8px 56px;
    gap: 8px;
  }
  /* 2026-05-23 (Curtis mobile QA): when the mobile sidebar is open,
     hide the reader-nav entirely. The previous behavior — shifting it
     to the sidebar's right edge — left only ~107px of nav chrome on
     a 375px viewport, which mangled the back/clock/forward row and
     squished the search bar. The sidebar is the navigation surface
     while it's open; the reader-nav reappears via the tap-zone once
     the user closes the sidebar (tap outside / pick a book / etc.). */
  body:has(.sidebar.open) .reader-nav,
  body:has(.sidebar.open) .reader-nav-tap-zone,
  body:has(.sidebar.open) .reader-nav-ol-options {
    display: none !important;
  }
}
/* Tap-zone strip at the top — receives clicks to summon the panel
   while hidden. Also offset by the sidebar so it doesn't compete
   with sidebar-toggle clicks at the top-left. */
.reader-nav-tap-zone {
  position: fixed;
  top: 0;
  left: var(--sidebar-w);
  right: 0;
  height: 24px;
  z-index: 44;
  pointer-events: auto;
}
@media (max-width: 880px) {
  .reader-nav-tap-zone { left: 0; }
}
body.reader-nav-visible .reader-nav-tap-zone {
  pointer-events: none;
}
/* 2026-05-18 (Curtis): leftover mobile @media rule from the
   earlier centered-pill design retired. The current full-width
   panel layout is governed by the @media rule near the top of
   this section. */

.reader-nav-btn {
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 999px;
  font-size: 18px;
  font-weight: 500;
  color: var(--muted);
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
  font-family: var(--sans);
  line-height: 1;
}
.reader-nav-btn:hover {
  background: var(--accent-soft);
  color: var(--accent);
}
.reader-nav-btn:disabled,
.reader-nav-btn[aria-disabled="true"] {
  color: var(--faint);
  cursor: default;
}
/* 2026-05-23 (Curtis): theme-toggle relocated from sidebar header to
   reader-nav. The old .theme-toggle CSS used position:absolute inside
   the sidebar; the new home is .reader-nav (display: flex), so the
   class .reader-nav-theme just inherits reader-nav-btn styling and
   sits inline next to the size pills. SVG icon is injected by app.js
   applyThemeToBody — give it display:block so it centers properly. */
.reader-nav-btn.reader-nav-theme { margin-left: 6px; }
.reader-nav-btn.reader-nav-theme svg { display: block; width: 14px; height: 14px; }

/* 2026-05-23 (Curtis): history dropdown button between back/forward.
   Smaller than the arrow buttons, with a subtle dot glyph. Opens the
   .reader-nav-history-panel anchored just below. */
/* 2026-05-23 (Curtis): clock-history button matches the back/forward
   arrow sizing (28×28 via .reader-nav-btn) so it baseline-aligns with
   them. Was 24×24 with `align-self: center` which fought the
   .reader-nav's `align-items: flex-start` and ended up visually
   off-center. */
.reader-nav-btn.reader-nav-history {
  color: var(--muted);
  opacity: 0.65;
  transition: opacity 100ms ease, color 100ms ease, background 100ms ease;
}
.reader-nav-btn.reader-nav-history:hover {
  opacity: 1;
}
.reader-nav-btn.reader-nav-history[aria-expanded="true"] {
  color: var(--accent);
  background: var(--accent-soft);
  opacity: 1;
}
.reader-nav-btn.reader-nav-history svg { display: block; }

/* The dropdown panel itself — floats over the reader, lists the last
   12 visited verses in shorthand. Newest first. The currently-active
   entry gets a "›" marker so the user can see where they are in the
   stack. */
.reader-nav-history-panel {
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 6px 0;
  box-shadow: 0 10px 28px -8px rgba(28, 25, 23, 0.18),
              0 2px 6px -2px rgba(28, 25, 23, 0.10);
  z-index: 60;
  min-width: 180px;
  max-height: 60vh;
  overflow-y: auto;
  font-family: var(--sans);
}
.reader-nav-history-item {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  border: 0;
  background: transparent;
  text-align: left;
  padding: 6px 12px 6px 8px;
  font-size: 13px;
  color: var(--ink);
  cursor: pointer;
}
.reader-nav-history-item:hover {
  background: var(--accent-soft);
  color: var(--accent);
}
.reader-nav-history-item.is-current {
  color: var(--accent);
  font-weight: 600;
}
.reader-nav-history-item.is-admin {
  color: var(--accent);
}
.reader-nav-history-marker {
  display: inline-block;
  width: 12px;
  text-align: center;
  font-size: 13px;
  color: var(--accent);
}
.reader-nav-history-ref {
  font-feature-settings: "tnum";
}
.reader-nav-history-sub {
  margin-left: auto;
  padding-left: 10px;
  font-size: 11px;
  color: var(--muted);
  font-feature-settings: "tnum";
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.reader-nav-history-item { display: flex; align-items: center; gap: 0; }

/* 2026-05-23 (Curtis): per-book history icon. Sits at the right edge
   of any sidebar book li that has at least one verse in _navHistory.
   Discrete + subtle by default; brightens on hover. Click jumps to
   the most recent visited verse in that book. */
.sidebar .book .book-history-icon {
  position: absolute;
  /* 2026-05-23 (Curtis): pushed further right + aligned to the FIRST
     text line of the title (was vertically-centered between rows on
     multi-line book labels like "Gospel according to Gift-of-He-Who-
     Is (Matthew)"). top:7px hugs the padding-top of the .book li so
     the icon sits at the first row's optical baseline; right:0 lets
     it tuck flush against the sidebar's right edge. */
  right: 0;
  top: 7px;
  width: 16px;
  height: 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 0;
  border-radius: 4px;
  color: var(--faint);
  opacity: 0.55;
  cursor: pointer;
  transition: opacity 100ms ease, color 100ms ease, background 100ms ease;
  padding: 0;
}
.sidebar .book .book-history-icon:hover {
  opacity: 1;
  color: var(--accent);
  background: var(--accent-soft);
}
.sidebar .book .book-history-icon svg { display: block; }

.reader-nav-search {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  /* 2026-05-24 (Curtis): per "search bar and book views should always
     stay in the middle" — was flex:1 1 auto which ate all free space and
     defeated margin:auto centering. Content-sized basis with min-width
     for the input + max-width cap for the view-pill row + margin:0 auto
     places the column at the geometric center of the bar. */
  flex: 0 1 auto;
  min-width: 280px;
  max-width: 560px;
  margin: 0 auto;
}

.reader-nav-search-input {
  font-family: var(--sans);
  font-size: 13px;
  width: 100%;
  padding: 6px 14px;
  border-radius: 999px;
  border: 1px solid var(--rule);
  background: var(--panel-bg);
  color: var(--ink);
  outline: none;
  transition: background 120ms ease, border-color 120ms ease;
}
.reader-nav-search-input::placeholder {
  color: var(--faint);
  font-style: italic;
  font-weight: 400;
}
.reader-nav-search-input:focus {
  background: var(--panel-bg);
  border-color: var(--rule-strong);
}
/* 2026-05-18: parser-rejected input flashes a red ring for ~1s. The
   .error class is added by the keydown handler on miss and cleared on
   the next valid Enter. */
.reader-nav-search-input.error {
  border-color: #c0392b;
  box-shadow: 0 0 0 2px rgba(192, 57, 43, 0.25);
}

/* 2026-05-19 (Curtis): the standalone .reader-nav-location subtitle
   was retired. The current "Book ch:v" location now lives inside the
   .reader-nav-search-input itself when unfocused; on focus the input
   clears so the user can type a verse ref or a :command. */
.reader-nav-location { display: none !important; }

/* When the input is showing the current location (idle state) we want
   the location text to read as a label, not as an editable string. The
   .reader-nav-search-input always carries data-location and we restore
   it on blur, so this is mostly a typography signal. */
.reader-nav-search-input {
  text-align: center;
  font-family: var(--sans);
  letter-spacing: 0;
}
.reader-nav-search-input:focus {
  text-align: left;
}

/* Vertical separator between search and size pills (in the
   full-width panel layout the search is auto-centered so the
   separator is no longer needed; kept as 0 width but reserved
   for future feature groupings). */
.reader-nav-sep {
  display: none;
}

/* 2026-05-23 (Curtis): word-search controls inside the search bar.
   Floats to the right edge of the input when a text search is active.
   The .reader-nav-search-active class is toggled by mfbSearch.start /
   mfbSearch.clear. Hidden via the [hidden] attribute by default. */
.reader-nav-search-find {
  /* 2026-05-23 (Curtis mobile QA): the previous `top: 50%` centered
     the pill against the WHOLE .reader-nav-search column (input +
     sub-controls), so the chrome stuck down into the view-picker row
     beneath. Anchor instead to the input's vertical center — the
     input is the FIRST child, so its top edge = container top and
     its height = the input pill height (29px including borders). */
  position: absolute;
  right: 4px;
  top: 2px;
  display: flex;
  align-items: center;
  gap: 4px;
  background: var(--panel-bg);
  padding: 2px 4px;
  border-radius: 999px;
  z-index: 2;
}
.reader-nav-search-find[hidden] { display: none !important; }
.reader-nav-search-count {
  font-family: var(--sans);
  font-size: 11px;
  color: var(--muted, var(--ink));
  opacity: 0.75;
  padding: 0 4px;
  min-width: 30px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.reader-nav-search-btn {
  width: 20px;
  height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--rule);
  background: var(--panel-bg);
  color: var(--ink);
  border-radius: 50%;
  padding: 0;
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease;
}
.reader-nav-search-btn:hover {
  background: var(--accent-soft, var(--panel-bg));
  border-color: var(--rule-strong, var(--rule));
}
.reader-nav-search-btn svg { display: block; }

/* Reserve trailing room on the input itself when search controls are
   visible so the typed query doesn't slide under the controls. */
.reader-nav-search.reader-nav-search-active .reader-nav-search-input {
  padding-right: 100px;
}

/* Highlight marks injected by mfbSearch into the reader DOM. The
   "active" hit (current navigation target) is intensified. */
.mfb-search-hit {
  background: rgba(255, 213, 0, 0.45);
  color: inherit;
  padding: 0 1px;
  border-radius: 2px;
  /* Keep <mark> from inheriting browser-default bold/italic. */
  font-style: inherit;
  font-weight: inherit;
}
.mfb-search-hit.is-active {
  background: rgba(255, 152, 0, 0.85);
  outline: 2px solid rgba(204, 102, 0, 0.6);
  outline-offset: -2px;
}
body.theme-dark .mfb-search-hit {
  background: rgba(255, 213, 0, 0.35);
}
body.theme-dark .mfb-search-hit.is-active {
  background: rgba(255, 152, 0, 0.75);
  outline-color: rgba(255, 175, 60, 0.9);
}

/* 2026-05-19 Phase 15d (Curtis polish): subtle two-letter control.
 * No background pill, no border — just the two A's side by side
 * with their relative size doing the affordance work. Click target
 * is generous (8px padding around the glyph) even though the
 * visible character is small, so the buttons are easy to hit
 * without resizing the visual control. */
.reader-nav-size {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 0 4px;
  background: transparent;
}
.reader-nav-size-btn {
  height: 28px;
  min-width: 22px;
  padding: 0 6px;
  border: none;
  background: transparent;
  font-family: var(--serif);
  cursor: pointer;
  color: var(--muted);
  font-weight: 500;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: color 100ms ease, background 100ms ease;
  border-radius: 4px;
}
.reader-nav-size-btn-smaller { font-size: 11px; }
.reader-nav-size-btn-larger  { font-size: 17px; }
.reader-nav-size-btn:hover {
  color: var(--ink);
  background: rgba(127, 127, 127, 0.06);
}
.reader-nav-size-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

/* (Previous load-time fade-in keyframes removed — the bar now stays
   hidden by default and slides in only when summoned. The transform
   transition on .reader-nav above handles the slide animation.) */
@keyframes reader-nav-fade-in-DEPRECATED {
  from { opacity: 0; transform: translate(-50%, -8px); }
  to   { opacity: 0.65; transform: translate(-50%, 0); }
}

/* 2026-05-18 (Curtis): hide the inline masthead text-size control
   now that the size pills live in the floating .reader-nav at the
   top. The inline buttons stay in the DOM so the existing handlers
   (bindTextSizeGroup) keep working; the floating bar's pills
   delegate to them via programmatic click. */
.text-size-control { display: none !important; }

/* ────────────────────────────────────────────────────────────────
   2026-05-19 (Curtis revision): subtle inline reader-controls strip.
   Lives directly under the .reader-nav-search-input. Three edition
   labels acting as text-tab pills, plus the Highlight names toggle,
   plus the original-language-only controls when in that view.
   Very low chrome — muted text, thin underline for the active edition.
   The popover model (gear button + dropdown) was scrapped per
   Curtis 2026-05-19; this is the replacement.
   ──────────────────────────────────────────────────────────────── */
.reader-nav-controls {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  justify-content: center;
  align-items: center;
  gap: 6px 10px;
  padding: 2px 4px 0;
  margin: 0;
  font-family: var(--sans);
  font-size: 11px;
  line-height: 1.4;
  color: var(--muted);
  background: transparent;
  border: 0;
  user-select: none;
}
.reader-nav-search { max-width: 520px; }

/* 2026-05-19 (Curtis revision 7): Highlight names — small + discrete,
   identical to the OL panel toggles. Just centers it vertically on
   the top row. All visual styling (font-size, checkbox, gap) inherits
   from .reader-nav-toggle. */
.reader-nav-toggle-marks {
  align-self: center;
  margin: 0 4px;
}
/* Phase 28b: keep the 4 top-bar toggles (Names / Cites / Roots / Gloss)
 * grouped so they wrap to the same row at narrow viewports rather than
 * one toggle escaping to the verse-nav line above. On desktop the
 * wrapper is transparent (display:contents) so the existing flex
 * layout is unchanged; on mobile it becomes a flex sub-row that
 * wraps as a unit. */
/* 2026-05-24 v5 (Curtis mockup): two toggle clusters now exist —
   .reader-nav-toggle-group-universal sits LEFT of the search input,
   .reader-nav-toggle-group-ol sits RIGHT. Both flex with wrap so
   chips can flow to a second sub-row gracefully on narrow viewports.
   The OL cluster carries a subtle border to read as a "box" of
   Hebrew/Greek tools, matching the mockup. */
.reader-nav-toggle-group {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}
/* v6 (Curtis): Names+Gloss form one "box" cluster so the visual
   pairing is obvious. The box expands to include Gloss only in BSB
   and OL views (Gloss is hidden in MFB via .not-mfb-only). */
.reader-nav-toggle-group-names {
  align-self: flex-start;
  margin-top: 2px;
  padding: 3px 6px;
  border: 1px solid var(--rule);
  border-radius: 6px;
  column-gap: 8px;
  row-gap: 3px;
}
.reader-nav-toggle-group-notes {
  /* Notes ▾ sits beside the Names box as a loose chip — no box
     treatment of its own. */
  align-self: flex-start;
  margin-top: 4px;
}
.reader-nav-toggle-group-ol {
  /* The OL "box" — subtle border so the cluster reads as a unified
     group of Hebrew/Greek tools. Leading אΩ glyph (see .rn-script-
     marker) makes the scope explicit. max-width tuned for the 2-up
     / 2-down mockup wrap: Rare + threshold on row 1, Tiny + Niqqud
     on row 2 (Gloss moved to the Names box in v6). */
  align-self: flex-start;
  margin-top: 2px;
  padding: 3px 6px 3px 4px;
  border: 1px solid var(--rule);
  border-radius: 6px;
  column-gap: 6px;
  row-gap: 3px;
  max-width: 195px;
}

/* 2026-05-24 overnight P10 (Curtis): mobile-specific nav polish.
   At ≤880px the nav was wrapping into a 275px stack — each toggle
   cluster taking its own row. Tighten everything for thumb-zone
   viewports while keeping the search column centered. */
@media (max-width: 880px) {
  .reader-nav {
    gap: 6px;
    padding: 6px 8px 4px;
  }
  .reader-nav-toggle-group-names,
  .reader-nav-toggle-group-ol {
    /* Drop the box border on narrow viewports — boxed clusters that
       wrap to multiple sub-rows read as nested boxes which is noisy.
       Keep tight padding so the chip cluster stays compact. */
    border: 0;
    padding: 0;
    margin-top: 0;
    max-width: 100%;
  }
  .reader-nav-toggle-group-ol {
    /* OL cluster keeps an extremely subtle visual grouping via the
       leading אΩ glyph alone; the border is gone but the glyph still
       communicates scope. */
  }
  .rn-script-marker {
    /* Drop the right-border divider on mobile — looks busy when the
       OL box has lost its own border. */
    border-right: 0;
    padding-right: 2px;
    margin-right: 0;
  }
  .reader-nav-search {
    /* On mobile the search column gets the most width since it's
       the primary interaction. Order it last in the flex flow so
       it wraps to the bottom row and the toggle clusters stack on
       top — keeping the input visually prominent above the verse. */
    order: 99;
    flex-basis: 100%;
    max-width: 100%;
    margin: 0;
  }
  .reader-nav-toggle-group-names { order: 1; }
  .reader-nav-toggle-group-notes { order: 2; }
  .reader-nav-toggle-group-ol { order: 3; flex-basis: 100%; }
  .reader-nav-size { order: 50; margin-left: auto; }
  .reader-nav-btn.reader-nav-theme,
  .reader-nav-btn.reader-nav-popup-tabs { order: 51; }
}
.rn-script-marker {
  /* Tiny dark Hebrew aleph + Greek capital omega — communicates
     "Original Language only" without needing words. Same neutral
     palette as the chips so it doesn't shout. */
  display: inline-flex;
  align-items: center;
  font-family: var(--hebrew), var(--greek), serif;
  font-size: 13px;
  letter-spacing: 0.04em;
  color: var(--muted);
  line-height: 1;
  padding-right: 4px;
  margin-right: 2px;
  border-right: 1px solid var(--rule);
  user-select: none;
}
/* .not-mfb-only — show in BSB + Original Language, hide in
   Meaning-First-Bible view. Mirrors the .ol-only gate pattern. */
body[data-view="meaning_first"] .reader-nav .not-mfb-only {
  display: none !important;
}
@media (max-width: 720px) {
  .reader-nav-toggle-group {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    /* Take a full row of the parent flex so the group never stays
     * adjacent to the wide search/verse-nav block. */
    flex-basis: 100%;
  }
}
.reader-nav-views {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.reader-nav-controls-sep {
  color: var(--faint);
  font-size: 10px;
  user-select: none;
}
.reader-nav-controls-sep-strong { opacity: 0.55; padding: 0 2px; }

.reader-nav-view-btn {
  appearance: none;
  background: transparent;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  color: var(--muted);
  cursor: pointer;
  letter-spacing: 0.01em;
  border-bottom: 1px solid transparent;
  line-height: 1.5;
  /* Keep each view label on a single line — the search column has room
     now that toggles collapsed to .rn-pill, and 2-line wrapping made
     the bar look broken (Curtis 2026-05-24). */
  white-space: nowrap;
  transition: color 120ms ease, border-color 120ms ease;
}
.reader-nav-view-btn:hover { color: var(--ink); }
.reader-nav-view-btn.active {
  color: var(--ink);
  border-bottom-color: currentColor;
}
/* 2026-05-20 (Curtis): long / short label swap.
   Desktop shows the full names; mobile shows the abbreviations
   "MFB" / "BSB" / "אα" (Hebrew aleph + Greek alpha) so all three
   pills fit on one line under the search input. */
.reader-nav-view-btn .vlong  { display: inline; }
.reader-nav-view-btn .vshort { display: none; }
.reader-nav-view-btn[id="view-original-language"] .vshort {
  font-family: var(--hebrew), var(--greek), serif;
  font-size: 13px;
  letter-spacing: 0.04em;
}
/* 2026-05-21 Phase 28: vlong/vshort label pattern extended to every
   top-bar toggle (Highlight names / Show citations / Show root family /
   Admin gloss). On desktop only the long label is visible; the mobile
   breakpoint below swaps to the short label so all four toggles fit
   on a 375px-wide row alongside the A/A size pills. */
.reader-nav-toggle .vlong  { display: inline; }
.reader-nav-toggle .vshort { display: none; }

@media (max-width: 720px) {
  .reader-nav-view-btn .vlong  { display: none; }
  .reader-nav-view-btn .vshort { display: inline; }
  /* Tighter row gap so the three pills + the separator dots sit
     comfortably on a single line on narrow screens. */
  .reader-nav-controls,
  .reader-nav-views { gap: 4px 8px; }
  /* Phase 28 mobile fix (2026-05-21):
   * Curtis flagged the top-bar toggle row overflowing at 375px wide —
   * "Show citations" and "Show root family" were clipped or pushed
   * fully off-screen. Two-part fix:
   *   (a) every top-bar toggle uses .vlong / .vshort label pairs, and
   *       at <=720px we swap to the short labels (Names / Cites /
   *       Roots / Gloss).
   *   (b) .reader-nav itself drops flex-wrap:nowrap → flex-wrap:wrap
   *       so even with short labels the row can fall to a second
   *       line gracefully on the narrowest phones (≤360px).
   * Together this restores reach to every toggle on a 375px viewport
   * without crowding the search input or the A/A size pills. */
  .reader-nav-toggle .vlong  { display: none; }
  .reader-nav-toggle .vshort { display: inline; }
  .reader-nav { flex-wrap: wrap; row-gap: 6px; }
}

.reader-nav-toggle {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
  color: var(--muted);
  /* 2026-05-19 (Curtis fix): explicit font-size — the previous
     `font: inherit` shorthand was overriding the 11px on
     .reader-nav-toggle-marks, bumping it to body's 19px because
     .reader-nav-toggle is more general but came LATER in the
     stylesheet. The OL toggles already inherit 11px from
     .reader-nav-ol-options; this guarantees Highlight names too. */
  font-family: var(--sans);
  font-size: 11px;
  line-height: 1.4;
  white-space: nowrap;
}
.reader-nav-toggle:hover { color: var(--ink); }
.reader-nav-toggle input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 11px;
  height: 11px;
  border: 1px solid currentColor;
  border-radius: 2px;
  background: transparent;
  cursor: pointer;
  position: relative;
  margin: 0;
  vertical-align: middle;
}
.reader-nav-toggle input[type="checkbox"]:checked {
  background: currentColor;
}
.reader-nav-toggle input[type="checkbox"]:checked::after {
  content: "";
  position: absolute;
  inset: 1px;
  background: var(--panel-bg, #fff);
  clip-path: polygon(14% 50%, 0 64%, 38% 100%, 100% 22%, 86% 9%, 38% 73%);
}
.reader-nav-toggle-select select {
  appearance: none;
  -webkit-appearance: none;
  font: inherit;
  font-size: 11px;
  background: transparent;
  border: 0;
  border-bottom: 1px dotted var(--faint);
  color: var(--muted);
  padding: 0 14px 0 2px;
  cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 7px) 50%, calc(100% - 3px) 50%;
  background-size: 4px 4px;
  background-repeat: no-repeat;
}
.reader-nav-toggle-select select:focus { outline: none; color: var(--ink); }

/* Inside the floating-nav strip, override the original
   .sidebar-reader-controls box chrome — no border, no padding box.
   The original styles were for the sidebar's framed group; in the
   floating nav we want clean inline text. */
.reader-nav .sidebar-reader-controls,
.reader-nav-search .sidebar-reader-controls {
  margin: 0;
  padding: 2px 4px 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  font-size: 11px;
}

/* 2026-05-19 (Curtis): legacy sidebar mount-point — if any stale call
   path renders #sidebar-reader-controls inside the sidebar (it now
   lives in the floating nav), hide it. */
.sidebar .sidebar-reader-controls { display: none; }

/* ────────────────────────────────────────────────────────────────
   2026-05-19 (Curtis): subtle context arrows on the side of the
   reading column. Spec from notes/PRODUCT_BRAINSTORM_2026-05-17.md
   §"Reader Position Tracking + Context Arrows". This is the basic
   click-to-cycle-view version; the future canonical-position drag
   handles + cross-render sync land in Phase 17.

   Behavior: faded out at rest; visible when the cursor is moving
   inside the reader viewport. Mirrors macOS overlay-scrollbar
   semantics — present when you need them, invisible otherwise.
   ──────────────────────────────────────────────────────────────── */
/* 2026-05-23 (Curtis): "pretty close to the text, but faint. so that
   you could really see where you're scrolling." Smaller hit target,
   no background pill at any state — just the chevron glyph with low
   opacity. Hover lifts opacity but doesn't add a box. */
.reader-side-arrow {
  position: fixed;
  /* 2026-05-23 (Curtis): arrows track the current-verse anchor, not
     viewport center. mfbPosition anchors the "current verse" at 30%
     viewport height; arrows default to that same line so a fresh
     page-load lands them at the right spot. JS in app.js then drives
     `top` per-scroll to follow the exact verse element on every
     scroll-settle, so as the user reads, the arrows ride the
     current-verse line. */
  top: 30vh;
  transform: translateY(-50%);
  width: 28px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  border-radius: 6px;
  z-index: 40;
  opacity: 0;
  pointer-events: none;
  transition: opacity 280ms ease, color 120ms ease, transform 200ms ease;
}
.reader-side-arrow:hover {
  color: var(--ink);
  opacity: 0.55 !important;
}
.reader-side-arrow:focus-visible {
  outline: 2px solid var(--accent-soft);
  outline-offset: 2px;
}
/* Anchored at the column's outer edge — left arrow on the LEFT of
   the wrap, right arrow on the RIGHT. The .wrap padding gives us
   visible breathing room outside the reading column. */
/* 2026-05-23 (Curtis) revision 2: anchor arrows near the text column's
   outer edges, NOT next to the chapter-popup rail. The reading column
   is .wrap inside .content-wrap; content-wrap has margin-left:
   sidebar-w, .wrap is max-width 720px centered inside it. So the text
   column's outer left edge = sidebar-w + (content-wrap-w - 720)/2 =
   (sidebar-w + 100vw - 720) / 2. Park the arrow ~56px before that
   edge so it sits in the gutter just outside the text. max() ensures
   the arrow doesn't slide back into the chapter-rail area on narrow
   viewports (chapter-popup is 52px wide at left: var(--sidebar-w);
   so we floor at sidebar-w + 80px to stay clear of it). */
.reader-side-arrow-left {
  left: max(
    calc(var(--sidebar-w, 220px) + 80px),
    calc((100vw + var(--sidebar-w, 220px) - 720px) / 2 - 56px)
  );
}
.reader-side-arrow-right {
  right: max(
    20px,
    calc((100vw - var(--sidebar-w, 220px) - 720px) / 2 - 56px)
  );
}
/* Visible state — set by JS in response to cursor activity. Faint
   default opacity per Curtis 2026-05-23 ("but faint. so that you
   could really see where you're scrolling"). */
body.reader-arrows-visible .reader-side-arrow {
  opacity: 0.22;
  pointer-events: auto;
}
/* Sidebar collapsed → text column re-centers because content-wrap's
   margin-left collapses to 0. The max() expression above handles this
   automatically since it uses var(--sidebar-w) which the body class
   doesn't change (only .content-wrap's margin does). So leave a
   simple floor for the collapsed left arrow. */
body.sidebar-collapsed .reader-side-arrow-left {
  left: max(
    72px,
    calc((100vw - 720px) / 2 - 56px)
  );
}
/* 2026-05-23 (Curtis): admin override followed the legacy 50vh
   baseline; rebased to 30vh + 24px so the admin-tabs strip still
   gets cleared but the arrows continue to land on the
   mfbPosition anchor line. The JS scroll-track overrides this
   anyway when a current-verse element exists. */
body.admin-mode .reader-side-arrow {
  top: calc(30vh + 24px);
}
/* Hide on narrow screens — swipe is the primary mobile interaction. */
@media (max-width: 720px) {
  .reader-side-arrow { display: none; }
}
/* Phase 17 L6c — drag-handle visual. While the arrow is being
   dragged as a position handle, render an overlay-scrollbar-style
   vertical "thumb" line through it. The arrow stays at full opacity
   and shows a subtle background to communicate "I am the active
   handle right now". Click-to-cycle behavior is unaffected (the
   drag handler decides click-vs-drag with a 4px threshold). */
.reader-side-arrow.dragging {
  opacity: 1 !important;
  color: var(--ink);
  background: rgba(127, 127, 127, 0.14);
  cursor: ns-resize;
}
.reader-side-arrow.dragging::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 2px;
  height: 28px;
  transform: translate(-50%, -50%);
  background: currentColor;
  opacity: 0.4;
  border-radius: 2px;
  pointer-events: none;
}

/* ────────────────────────────────────────────────────────────────
   2026-05-19 (Curtis revision 2): Original-Language options sliding
   pop-up. Sibling of .reader-nav. Hidden by default behind the seam
   (translateY -100% under the nav). When body[data-view="original_
   language"] is set, slides into view just below the .reader-nav.
   Matches the "emerge from behind a seam" motion of the nav itself.
   ──────────────────────────────────────────────────────────────── */
.reader-nav-ol-options {
  position: fixed;
  /* Anchor to top:0 (same as .reader-nav). Z-index 44 keeps the panel
     STRICTLY BEHIND the nav (z:45) so the slide-out emerges from
     under the nav's bottom seam rather than landing on top of it. */
  top: 0;
  left: var(--sidebar-w);
  right: 0;
  z-index: 44;
  /* 2026-05-19 (Curtis revision 5): outer panel spans full content
     width for chrome continuity with the nav, but the actual controls
     live inside an inner .reader-nav-ol-track that matches the search
     column's max-width — so the OL row visually aligns with the
     editions row above instead of drifting toward the geometric
     center of the panel. */
  display: flex;
  justify-content: center;
  align-items: center;
  /* 2026-05-19 (Curtis revision 4): the panel is meant to feel like a
     continuation of the nav, not a floating second surface. No top
     border, no internal box-shadow, share the nav's bottom-seam
     treatment so the two read as one connected chrome strip. */
  padding: 8px 18px;
  background: var(--bg);
  border-top: 0;
  border-bottom: 1px solid var(--rule);
  /* Soft inset shadow matching the nav's, so the seam continues from
     the nav into the OL panel without a visible step. */
  box-shadow: inset 0 -6px 8px -6px rgba(28, 25, 23, 0.10);
  font-family: var(--sans);
  font-size: 11px;
  color: var(--muted);
  /* Default rest position: tucked behind the nav at y:0. */
  transform: translateY(-100%);
  pointer-events: none;
  /* Match the nav's transition curve + 320ms timing so the two
     surfaces slide as a family rather than at different speeds. */
  transition:
    transform 320ms cubic-bezier(0.22, 1, 0.36, 1),
    left      220ms cubic-bezier(0.22, 1, 0.36, 1);
  user-select: none;
}
/* Inner track — same max-width as the search column (520px) so the
   centered OL controls visually align with the search input + the
   editions row above. Wraps gracefully when narrow. */
.reader-nav-ol-track {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 6px 14px;
  width: 100%;
  max-width: 520px;
}
/* When reader-nav is visible AND view=original_language, slide the
   OL panel DOWN past the nav's footprint to sit just below it. The
   panel passes through the nav region during transit and is hidden by
   the nav (z:45 vs 44), so visually it emerges from behind the seam. */
body.reader-nav-visible[data-view="original_language"] .reader-nav-ol-options {
  transform: translateY(var(--reader-nav-h, 64px));
  pointer-events: auto;
}
/* While the OL panel is visible, drop the nav's bottom border so the
   two surfaces read as one continuous chrome strip (no double-line
   seam between them). The nav's inset shadow remains; the OL panel
   picks up the visible bottom border. */
body.reader-nav-visible[data-view="original_language"] .reader-nav {
  border-bottom-color: transparent;
}
@media (max-width: 880px) {
  .reader-nav-ol-options { left: 0; }
}
body.sidebar-collapsed .reader-nav-ol-options {
  left: 0;
  padding-left: 60px;
}
/* In admin mode the reader-nav floats below the admin-tabs strip
   (~55px). The OL options stack below the nav in that mode too —
   the --reader-nav-h variable carries the nav's full offset (admin
   tabs + nav height). app.js wires it. */

/* ============================================================
   Phase 18A — NT-LXX Citation Bridge (2026-05-19)
   ============================================================
   Citation marker glyph next to .vnum on any NT verse that has at
   least one OT cross-reference (data sourced from
   data/lxx-citations/<book>.json — OpenBible.info CC BY). The marker
   is ALWAYS in the DOM when present but DEFAULT-HIDDEN until the user
   opts in via the "Show citations" toggle (body.show-citations).
   Click the marker → openCitationPanel routes to the same .panel
   surface used for word details, in Citation mode. */

.citation-marker {
  display: none;          /* default off — see body.show-citations below */
  font-family: var(--sans);
  font-size: 0.85em;
  line-height: 0;
  vertical-align: super;
  color: var(--muted);
  background: transparent;
  border: 0;
  padding: 0 2px;
  margin: 0 1px 0 -1px;
  cursor: pointer;
  opacity: 0.55;
  transition: opacity 120ms ease, color 120ms ease, transform 120ms ease;
}
.citation-marker:hover,
.citation-marker:focus-visible {
  opacity: 1;
  color: var(--accent, #335);
  transform: translateY(-1px);
  outline: none;
}
body.show-citations .citation-marker {
  display: inline-block;
}
/* Marker hidden in Original Language view — the OL renderer builds
   its own DOM (.source-token) and the .vnum siblings don't sit in
   the same flow. We re-enable case by case in a follow-up; for now
   the marker is only meaningful in MFB / BSB views. */
body[data-view="original_language"] .citation-marker {
  display: none !important;
}

/* Citation panel — reuses .panel chrome (#panel + #panel-body). */
.citation-panel {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.citation-panel-title {
  font-family: var(--serif, serif);
  font-size: 1.15rem;
  font-weight: 600;
  margin: 0;
  letter-spacing: 0.005em;
}
.citation-panel-summary {
  font-size: 12px;
  color: var(--muted);
}
.citation-panel-attrib abbr { text-decoration: none; border-bottom: 1px dotted var(--muted); }

.citation-nt-block {
  background: var(--bg-soft, rgba(0, 0, 0, 0.03));
  border-left: 3px solid var(--accent, #5a7);
  padding: 10px 12px;
  border-radius: 0 4px 4px 0;
}
.citation-nt-text {
  font-family: var(--serif, serif);
  font-size: 0.98rem;
  line-height: 1.55;
  margin-top: 4px;
}
.citation-section-label {
  font-size: 11px;
  font-family: var(--sans);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  font-weight: 600;
}

.citation-list {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.citation-card {
  border: 1px solid var(--rule, #d9d4cc);
  border-radius: 4px;
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.citation-card-head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.citation-card-otref {
  font-family: var(--serif, serif);
  font-weight: 600;
  font-size: 0.95rem;
}
.citation-confidence {
  font-family: var(--sans);
  font-size: 10px;
  color: var(--muted);
  margin-left: auto;
}

.citation-type {
  display: inline-block;
  padding: 1px 7px;
  font-size: 10px;
  font-family: var(--sans);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  border-radius: 8px;
  font-weight: 600;
}
.citation-type-verbatim {
  background: var(--conf-high-soft, rgba(80, 140, 80, 0.18));
  color: var(--conf-high, #2c6c2c);
}
.citation-type-paraphrastic {
  background: var(--conf-medium-soft, rgba(180, 140, 60, 0.18));
  color: var(--conf-medium, #8a6a1f);
}
.citation-type-echo {
  background: var(--bg-soft, rgba(0, 0, 0, 0.06));
  color: var(--muted);
}

.citation-section {
  padding-top: 4px;
}
.citation-section-body {
  font-family: var(--serif, serif);
  font-size: 0.95rem;
  line-height: 1.5;
  margin-top: 4px;
}
.citation-section-loading {
  color: var(--muted);
  font-style: italic;
}
.citation-section-unavailable {
  color: var(--muted);
  font-size: 0.88rem;
}
.citation-lxx-deferred {
  background: var(--bg-soft, rgba(0, 0, 0, 0.03));
  padding: 8px 10px;
  border-radius: 3px;
  color: var(--muted);
  font-size: 0.85rem;
  font-style: italic;
  border-left: 2px dashed var(--rule, #ccc);
}
.citation-ot-text .citation-section-body {
  /* Hebrew Vorlage may carry Latin glosses — let the renderer pick a
     direction per text node. We render in LTR by default; future
     enhancement: detect heb. anchors on the underlying spans and
     emit a dir="rtl" overlay. */
  direction: ltr;
}
.citation-glossary-chip {
  display: inline-block;
  padding: 2px 7px;
  margin: 2px 4px 2px 0;
  background: var(--accent-soft, rgba(80, 90, 130, 0.12));
  color: var(--accent, #335);
  font-family: var(--sans);
  font-size: 11px;
  border-radius: 3px;
  font-weight: 500;
}

.citation-card-actions {
  display: flex;
  gap: 8px;
  margin-top: 4px;
  flex-wrap: wrap;
}
.citation-jump-btn {
  background: var(--accent, #335);
  color: var(--accent-fg, #fff);
  border: 0;
  padding: 6px 12px;
  font-family: var(--sans);
  font-size: 12px;
  border-radius: 3px;
  cursor: pointer;
  transition: background 120ms ease;
}
.citation-jump-btn:hover,
.citation-jump-btn:focus-visible {
  background: var(--accent-hover, #224);
  outline: none;
}
.citation-jump-btn-disabled,
.citation-jump-btn[disabled] {
  background: var(--bg-soft, rgba(0, 0, 0, 0.06));
  color: var(--muted);
  cursor: not-allowed;
}

/* Top-row Show-citations toggle — pairs with #toggle-marks visually. */
.reader-nav-toggle-citations { /* inherit .reader-nav-toggle layout from above */ }


/* ===== Phase 18B — Root family side-panel section =====
 *
 * Default OFF (gated by body.show-root-family for cases where the
 * block is pre-rendered but the user hasn't opted in yet; the JS path
 * only adds the block when SHOW_ROOT_FAMILY is true, so the body
 * class is belt-and-suspenders).
 */
.reader-nav-toggle-rootfamily { /* inherits .reader-nav-toggle layout */ }

.root-family-block {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--rule, rgba(0, 0, 0, 0.08));
}
.root-family-block .section-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted, #777);
  margin-bottom: 6px;
}
.rf-root-line {
  display: flex;
  align-items: baseline;
  gap: 14px;
  margin-bottom: 12px;
}
.rf-root {
  font-size: 22px;
  font-weight: 600;
  font-family: var(--serif-heb, var(--serif));
}
.rf-root-meta {
  font-size: 12px;
  color: var(--muted, #777);
}
.rf-section-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--fg-soft, #444);
  margin: 12px 0 6px;
}
.rf-glossary-cousins,
.rf-common-cousins {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.rf-cousin-link,
.rf-common-link {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  padding: 6px 8px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 4px;
  cursor: pointer;
  font: inherit;
  color: inherit;
  text-align: left;
}
.rf-cousin-link:hover,
.rf-common-link:hover,
.rf-cousin-link:focus-visible,
.rf-common-link:focus-visible {
  border-color: var(--rule, rgba(0, 0, 0, 0.12));
  background: var(--bg-soft, rgba(0, 0, 0, 0.03));
  outline: none;
}
.rf-cousin-rendering {
  font-weight: 600;
}
.rf-cousin-hebrew,
.rf-common-hebrew {
  font-family: var(--serif-heb, var(--serif));
  font-size: 16px;
}
.rf-common-gloss {
  flex: 1;
  color: var(--muted, #666);
  font-size: 13px;
  font-style: italic;
}
.rf-common-count {
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  color: var(--muted, #888);
}
.rf-common-more {
  font-size: 12px;
  color: var(--muted, #888);
  padding: 4px 8px;
}
.rf-sample-host {
  margin-top: 10px;
}
.rf-sample-host:empty { display: none; }
.rf-sample-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-size: 13px;
  margin-bottom: 6px;
}
.rf-sample-gloss {
  color: var(--muted, #777);
  font-style: italic;
}
.rf-sample-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.rf-sample-jump {
  background: var(--bg-soft, rgba(0, 0, 0, 0.04));
  border: 1px solid var(--rule, rgba(0, 0, 0, 0.1));
  border-radius: 3px;
  padding: 3px 8px;
  font-size: 12px;
  cursor: pointer;
  color: inherit;
  font-family: inherit;
}
.rf-sample-jump:hover,
.rf-sample-jump:focus-visible {
  background: var(--bg-soft-hover, rgba(0, 0, 0, 0.07));
  outline: none;
}

/* ────────────────────────────────────────────────────────────────
 * Phase 26 — Admin-mode MACULA gloss underlay
 *
 * Curtis's request (2026-05-19): show the MACULA gloss for each
 * anchored morph as small text under each English span in both the
 * meaning_first_smoothed and rigid views — admin-only — so anchor
 * accuracy is verifiable at a glance.
 *
 * Mirrors the public Original-Language `tiny-gloss` pattern (renderer
 * emits a hidden span; CSS reveals it on a body class). The .admin-
 * gloss element is emitted unconditionally by renderSpanVerse for every
 * kind:source span; the JS decorator decoratePhase26AdminGlosses()
 * fills its text from MACULA. CSS hides it on the public reader and
 * reveals it only when body.admin-mode is on.
 * ──────────────────────────────────────────────────────────────── */
.admin-gloss { display: none; }

/* Phase 26 toggle (2026-05-21): the .admin-only-toggle checkbox wrapper
 * for "Admin gloss" is hidden by default and revealed only inside
 * admin mode, so the public reader's control bar stays clean. */
.admin-only-toggle { display: none; }
body.admin-mode .admin-only-toggle { display: inline-flex; }

body.admin-mode.show-admin-gloss .source-span,
body.admin-mode.show-admin-gloss .supplied-span {
  /* Flip wrappers into stacked layout so the gloss can sit directly
   * under the English span without breaking inline reading flow at
   * the verse level. inline-flex keeps each English word/phrase on
   * the same baseline as its neighbors; flex-direction:column stacks
   * the gloss beneath. vertical-align:top lines the tops up so glosses
   * dropping below don't shove subsequent spans down. Gated on BOTH
   * admin-mode AND the per-user show-admin-gloss toggle (Phase 26
   * 2026-05-21) so admins can hide the underlay without leaving
   * admin mode. */
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  vertical-align: top;
  /* Reserve a little vertical breathing room between verse lines so
   * the underlay doesn't crash into the next verse. */
  margin-bottom: 6px;
}
body.admin-mode.show-admin-gloss .admin-gloss {
  display: block;
  font-family: var(--sans);
  font-size: 10.5px;
  line-height: 1.15;
  color: var(--muted);
  margin-top: 1px;
  /* Allow the gloss line to be wider than the English span when needed
   * for multi-morph spans (e.g. "In the beginning" anchors two morphs:
   * "in · beginning"). The dot delimiter is added by the JS decorator. */
  max-width: 14em;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  direction: ltr;
  unicode-bidi: isolate;
  /* Subtle italic so admins instantly distinguish the underlay from
   * actual English content. */
  font-style: italic;
  opacity: 0.78;
}
/* Supplied-content placeholder — em-dash. Render at lower opacity so
 * the eye doesn't read it as a real gloss. */
body.admin-mode.show-admin-gloss .admin-gloss-supplied {
  opacity: 0.45;
  font-style: normal;
}

/* ===== Concordance modal — donut + filter chrome (2026-05-23) =====
 * Donut at top + clickable wedges, slice-color legend, multi-select
 * book-filter chips below. Click any wedge / legend item to filter
 * the verse list to that slice; click any book chip to limit to
 * specific books. "All books" chip restores no-book-filter.
 */
.concordance-donut-host { margin: 10px 0 6px; }
.concordance-donut-row {
  display: flex;
  align-items: flex-start;
  gap: 18px;
  flex-wrap: wrap;
}
.concordance-donut { flex: 0 0 160px; }
.concordance-donut-wedge { transition: stroke-width 120ms ease; }
.concordance-donut-wedge:hover { stroke-width: 28; }
.concordance-donut-wedge.is-active { stroke-width: 28; }
.concordance-legend {
  flex: 1;
  min-width: 220px;
}
.concordance-legend-head {
  font-size: 11.5px;
  color: var(--muted);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-bottom: 6px;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 8px;
}
.concordance-clear-slice {
  margin-left: auto;
  background: var(--accent);
  color: #fff;
  border: none;
  padding: 2px 8px;
  border-radius: 3px;
  font-size: 11px;
  cursor: pointer;
  letter-spacing: 0;
  text-transform: none;
  font-weight: 500;
}
.concordance-legend-list {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px 12px;
  max-height: 160px;
  overflow-y: auto;
}
.concordance-legend-item {
  display: flex;
  align-items: center;
  gap: 8px;
  background: transparent;
  border: 1px solid transparent;
  padding: 4px 6px;
  border-radius: 4px;
  font-family: inherit;
  font-size: 12px;
  cursor: pointer;
  text-align: left;
  color: var(--ink);
}
.concordance-legend-item:hover { background: var(--hit, #e8f0e0); }
.concordance-legend-item.is-active { background: var(--hit, #e8f0e0); border-color: var(--accent); }
.concordance-legend-swatch {
  flex: 0 0 10px;
  width: 10px;
  height: 10px;
  border-radius: 2px;
}
.concordance-legend-label {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.concordance-legend-count {
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  font-size: 11.5px;
}
.concordance-filter-host { margin: 8px 0 12px; }
.concordance-filter-head {
  font-size: 11.5px;
  color: var(--muted);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-bottom: 6px;
  font-weight: 600;
}
.concordance-book-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.concordance-book-chip {
  background: transparent;
  border: 1px solid var(--rule);
  padding: 3px 9px;
  border-radius: 12px;
  font-family: inherit;
  font-size: 11.5px;
  cursor: pointer;
  color: var(--muted);
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.concordance-book-chip:hover { background: var(--hit, #e8f0e0); }
.concordance-book-chip.is-active { background: var(--accent); color: #fff; border-color: var(--accent); }
.concordance-book-chip.is-active .concordance-book-count { color: rgba(255,255,255,0.85); }
.concordance-book-chip-all { font-weight: 600; }
.concordance-book-count {
  font-size: 10.5px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* ===== Popup-tabs button + dropdown (2026-05-23) =====
 * Reader-nav button (right of the theme toggle): small book/tabs icon.
 * Click opens a floating dropdown listing the last 12 recent study
 * popups; click an entry to reopen. Inherits .reader-nav-btn styling
 * for visual consistency with the other top-bar buttons.
 *
 * 2026-05-23 (Curtis): originally pinned inside the side panel
 * (.panel) — moved out so the dropdown is reachable without first
 * opening a word panel.
 */
.reader-nav-popup-tabs[aria-expanded="true"] {
  color: var(--accent);
}

.popup-tabs-panel {
  background: var(--bg, #faf6ee);
  border: 1px solid var(--rule);
  border-radius: 6px;
  box-shadow: 0 14px 32px -10px rgba(28, 25, 23, 0.3);
  min-width: 260px;
  max-height: 60vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  z-index: 10030;
  font-size: 13px;
}
.popup-tabs-header {
  padding: 8px 12px;
  border-bottom: 1px solid var(--rule);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.popup-tabs-clear {
  background: transparent;
  border: none;
  color: var(--muted);
  font-size: 11px;
  cursor: pointer;
  padding: 2px 4px;
  letter-spacing: 0;
  text-transform: none;
}
.popup-tabs-clear:hover { color: var(--accent); }
.popup-tabs-list { flex: 1; overflow-y: auto; padding: 4px; }
.popup-tabs-empty {
  padding: 18px 16px;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.5;
  text-align: center;
}
.popup-tabs-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 7px 9px;
  background: transparent;
  border: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
  border-radius: 4px;
  color: var(--ink);
}
.popup-tabs-item:hover { background: var(--hit, #e8f0e0); }
.popup-tabs-marker {
  width: 16px;
  text-align: center;
  color: var(--accent);
  flex-shrink: 0;
  font-size: 13px;
}
.popup-tabs-label {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.popup-tabs-sub {
  color: var(--muted);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  flex-shrink: 0;
}

/* ===== Concordance INSIDE the side panel (2026-05-23 — migrated
 * from #modal). Existing `.concordance-*` rules still apply for
 * structure; these adjust spacing + title styling to fit the panel
 * column (no h2 banner; tighter top spacing; donut+legend stacks on
 * narrow viewports). */
#panel-body .concordance-body { padding-top: 6px; }
#panel-body .concordance-title {
  font-family: var(--serif);
  font-size: 22px;
  margin: 0 0 4px;
  line-height: 1.2;
}
#panel-body .concordance-sub {
  color: var(--muted);
  font-size: 12.5px;
  margin-bottom: 12px;
}
/* Donut + legend: side-by-side at wide widths, stacked when the
   panel column is narrower than ~520px (mobile / narrow desktop). */
@media (max-width: 600px) {
  #panel-body .concordance-donut-row { flex-direction: column; }
}
/* Verse list — fill the remaining height naturally; the panel
   itself scrolls. */
#panel-body .concordance-list {
  margin-top: 8px;
  padding: 0;
  list-style: none;
}

/* ===== Nav cleanup (2026-05-24, Curtis) =====
 * .ol-only toggles only display in Original Language view.
 * .rn-pill is the compact toggle-pill replacement for the verbose
 * .reader-nav-toggle <label> + visible-checkbox + long-label rows.
 * Each pill is a small rounded button (short label, ~50–60px wide)
 * that hides its underlying checkbox and indicates checked state via
 * an active background + a leading ✓ glyph. Saves horizontal space
 * so all display toggles + the threshold select fit in one row, and
 * the search + view-pills stay centered.
 *
 * .ol-only pills hide entirely in non-OL views via the gate below.
 */
body:not([data-view="original_language"]) .reader-nav .ol-only {
  display: none !important;
}
/* 2026-05-24 v4 (Curtis): .rn-chip — tiny checkbox-with-label using the
   reader's neutral palette. No accent fill (he flagged the brown/red
   active state as "obnoxious — this is a reader view, use the same
   color scheme"). Unchecked = muted gray; checked = ink dark. The
   indicator is a real small ☐ box (7px) that fills dark when on. */
.rn-chip {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 1px 2px;
  background: transparent;
  border: 0;
  color: var(--muted);
  font-family: var(--sans);
  font-size: 11px;
  line-height: 1.2;
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
  transition: color 120ms ease;
}
.rn-chip:hover { color: var(--ink); }
.rn-chip input[type="checkbox"] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
  width: 1px;
  height: 1px;
  margin: 0;
}
.rn-chip-box {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 1.5px;
  border: 1px solid var(--rule-strong, currentColor);
  background: transparent;
  flex: 0 0 auto;
  transition: background 120ms ease, border-color 120ms ease;
}
.rn-chip-label {
  display: inline-block;
}
.rn-chip:has(input:checked) {
  color: var(--ink);
}
.rn-chip:has(input:checked) .rn-chip-box {
  background: var(--ink);
  border-color: var(--ink);
}
.rn-chip:has(input:focus-visible) .rn-chip-box {
  outline: 2px solid var(--rule-strong);
  outline-offset: 1px;
}
.rn-chip-dropdown {
  /* Notes ▾ button uses the same chip styling as the checkbox chips.
     Native <button> defaults override font-* and box-sizing, so we
     re-declare them explicitly (was: font: inherit, which the browser
     applied after .rn-chip's font properties and reset them back to
     defaults — making "Notes" render in serif 16px while every other
     chip stayed in 11px sans). */
  appearance: none;
  margin: 0;
  font-family: var(--sans);
  font-size: 11px;
  line-height: 1.2;
  color: var(--muted);
  /* Subtle ring so the dropdown affordance reads as a clickable
     control distinct from the bare-label chips. Border-color jumps
     to ink on hover/open to confirm it. */
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 1px 6px 1px 7px;
  background: transparent;
  cursor: pointer;
}
.rn-chip-dropdown:hover {
  color: var(--ink);
  border-color: var(--rule-strong);
}
.rn-chip-caret {
  display: inline-block;
  font-size: 10px;
  line-height: 1;
  opacity: 0.75;
  margin-left: 3px;
}
.rn-chip-dropdown[aria-expanded="true"] {
  color: var(--ink);
  border-color: var(--ink);
  background: var(--panel-bg);
}
.rn-chip-dropdown[aria-expanded="true"] .rn-chip-caret {
  opacity: 1;
  transform: rotate(180deg);
}
.rn-chip-dropdown-wrap {
  position: relative;
  display: inline-flex;
}
.rn-chip-popover {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: 6px;
  box-shadow: 0 12px 28px -8px rgba(28, 25, 23, 0.22);
  padding: 8px 10px;
  min-width: 220px;
  z-index: 50;
  font-size: 12px;
}
.rn-chip-popover-head {
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 6px;
}
.rn-chip-popover-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 3px 0;
  cursor: pointer;
  color: var(--muted);
}
.rn-chip-popover-item:hover { color: var(--ink); }
.rn-chip-popover-item input[type="checkbox"] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
  width: 1px;
  height: 1px;
}
.rn-chip-popover-item:has(input:checked) { color: var(--ink); }
.rn-chip-popover-item:has(input:checked) .rn-chip-box {
  background: var(--ink);
  border-color: var(--ink);
}
.rn-select {
  font-family: var(--sans);
  font-size: 10.5px;
  padding: 1px 4px;
  border-radius: 3px;
  border: 1px solid var(--rule);
  background: transparent;
  color: var(--muted);
  line-height: 1.2;
  max-width: 100px;
  margin: 0 2px;
}
.rn-select:hover { color: var(--ink); border-color: var(--rule-strong); }

/* 2026-05-24 overnight P5 (Curtis): inline concordance-lookup buttons.
   Sit next to each form (lexicon, root) inside word-detail panels so
   the user picks WHICH form to search instead of relying on a bottom-
   row first-morph-wins seed (which mis-fired on Hebrew clitic+stem
   clusters like ה+עִיר — the article got searched, not the word). */
.rn-inline-lookup-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  margin-left: 6px;
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: 4px;
  background: transparent;
  color: var(--muted);
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
  vertical-align: middle;
  transition: color 120ms ease, border-color 120ms ease, background 120ms ease;
}
.rn-inline-lookup-btn:hover {
  color: var(--ink);
  border-color: var(--ink);
  background: var(--panel-bg);
}
.rn-inline-lookup-btn:focus-visible {
  outline: 2px solid var(--rule-strong);
  outline-offset: 2px;
}
/* When the inline button is inside a section-label (root-block header)
   keep it aligned with the uppercase label letters. */
.section-label .rn-inline-lookup-btn { vertical-align: -3px; }
/* Two-line lemma cell: text + button stack inline. */
.panel-dd-lemma { display: inline-flex; align-items: center; gap: 4px; }
.panel-dd-lemma-text { display: inline; }
/* Surface line gets the button beside it too. */
.panel-surface { display: flex; align-items: baseline; gap: 6px; }
.panel-surface .rn-inline-lookup-btn { align-self: center; }
.rf-root-line .rn-inline-lookup-btn { margin: 0 6px; }
