/* ══════════════════════════════════════════════════════════════════════════════
   PPEA — Edition Passage Stylesheet
   ══════════════════════════════════════════════════════════════════════════════
   Structural layout for text and intro pages.  Loaded via html_head_text.html.

   Covers: edition-specific CSS tokens, passus grid layout (5-column subgrid),
   toolbar ribbon, bottom passus navigation, intro sidebar (nav.contents),
   note markers, responsive breakpoint stages (A–D), and the passus/folio
   combobox widgets.

   TEI annotation rendering → edition_annotations.css
   Editorial overlay features → edition_editorial.css
   ══════════════════════════════════════════════════════════════════════════════ */

/* ── §1  Edition Tokens ───────────────────────────────────────────────────────
   Custom properties consumed only on text/intro pages.
   ────────────────────────────────────────────────────────────────────────── */
:root {
    /* ── TEI annotation colors ────────────────────────────────────────── */
    --color-tei-sic:      light-dark(#7401DF, #b47aff);
    --color-tei-corr:     light-dark(#8A084B, #d66a99);
    --color-tei-add:      light-dark(#A0522D, #d4845a);
    --color-tei-orig:     light-dark(#00CC00, #44dd44);
    --color-tei-reg:      light-dark(#666633, #a3a060);
    --color-tei-reg-sep:  light-dark(#336600, #77bb44);
    --color-tei-damage:   light-dark(#00BFFF, #55ddff);
    --color-tei-seg:      light-dark(#FF1493, #ff66b2);
    --color-tei-app-bg:   light-dark(#BFBFBF, #3a3a3a);

    /* ── Manuscript highlight colors ──────────────────────────────────── */
    --color-hi-blue:       light-dark(blue, #6699ff);
    --color-hi-red:        light-dark(red, #ff6666);
    --color-hi-green:      light-dark(green, #66cc66);
    --color-hi-border:     light-dark(black, #999);
    --color-hi-border-red: light-dark(red, #ff6666);
}

/* ── §2  Registered custom property ───────────────────────────────────────────
   Resolves em at declaration site so child elements with a different
   font-size receive the parent's computed length.  Used by
   .initial-letter-cell to pass the text font-size into .initialLetter. */
@property --text-fs {
    syntax: '<length>';
    initial-value: 0px;
    inherits: true;
}

/* Horizontal squeeze factor for wide dropcap letters.  Default 1 (no squeeze).
   Set via per-letter CSS rules in §8a to reduce font-size (narrowing the layout
   column) and restore visual height with scaleY(1/--il-width-scale). */
@property --il-width-scale {
    syntax: '<number>';
    initial-value: 1;
    inherits: true;
}

/* Used by .witness-sigil (mobile comparison panel) to size its button
   to the adjacent text line's baseline-to-ascender height (cap height).
   Set on .witness-sigil-panel as `1cap`, resolved there against the
   inherited text column font, then read by the sigil element after it
   shrinks its own font-size. */
@property --text-cap {
    syntax: '<length>';
    initial-value: 0px;
    inherits: true;
}

/* Companion to --text-cap: the text column's line-height, resolved at
   the panel, used by .witness-sigil to compute a top offset that
   centres the button on the FIRST text line of a wrapped grid row. */
@property --text-lh {
    syntax: '<length>';
    initial-value: 0px;
    inherits: true;
}

/* article.passage-container inline padding (7px at Stage B and C, 0 below).
   Registered so #comparison-panel can add it to --main-pad-x in a single
   calc() for its mobile full-bleed negative margin — see edition_compare.css.
   Typed <length> so the 7px value doesn't need font-context resolution. */
@property --article-pad-x {
    syntax: '<length>';
    initial-value: 0px;
    inherits: true;
}


/* ── §3  Visually-hidden — edition controls ───────────────────────────────────
   Radio buttons and toggle checkboxes hidden visually but accessible to
   screen readers.  The generic .aria-text utility is in main.css. */
.radio-button-group input[type='radio'],
.linenum-toggle-cb,
.tags-toggle-cb,
.marg-toggle-cb {
    border: 0;
    clip: rect(0, 0, 0, 0);
    height: 1px;
    margin: -1px;
    overflow: hidden;
    padding: 0;
    position: absolute;
    width: 1px;
}


/* ══════════════════════════════════════════════════════════════════════════════
   PART A — PASSUS GRID LAYOUT
   ══════════════════════════════════════════════════════════════════════════════
   Design goals: docs/text-page-layout-spec.md
   Grid: article.passage-container owns the grid at ≥ 600px; .reading-grid inherits
   via subgrid.  At < 600px, .reading-grid owns its own grid.
   ══════════════════════════════════════════════════════════════════════════════ */

/* ── §4  Layout tokens ───────────────────────────────────────────────────────
   Custom properties controlling grid column sizes.  Responsive stages
   override these; the grid-template-columns definition consumes them. */
:root {
    /* Line number column width.  auto = content-sized.  Overridden to 0px
       at viewports where line numbers are hidden. */
    --linenum-w: auto;

    /* Comparison indicator column.  0px by default; nonzero when comparison
       view is active and line numbers are not serving as comparison links. */
    --compare-ind-w: 0px;
}

/* ── §4a  Inline grid (≥ 500px) ──────────────────────────────────────────── */
/* article.passage-container owns the grid at ≥ 500px.  .reading-grid and
   #comparison-panel use subgrid to share column tracks.

   At ≥ 650px the full 5-column grid is active:
     linenum | left-marg | compare-ind | text | right-marg
   At 500–649px, §26b overrides to a 3-column grid (no line numbers):
     left-marg | text | right-marg

   The text column uses minmax(12em, 32em): caps at 32em (wide enough for
   most verse lines without wrapping) but shrinks freely when the viewport
   can't fit 32em plus marginalia.

   Marginalia columns use minmax(3em, 1fr): they absorb all remaining
   space equally.  Because both are 1fr, the text column is naturally
   centered between them once it hits its max.

   All sizing is in em, so the layout scales naturally if the user
   increases the font size. */
@media (min-width: 500px) {
    article.passage-container {
        display: grid;
        grid-template-columns:
            [linenum]     var(--linenum-w)
            [left-marg]   minmax(3em, 1fr)
            [compare-ind] var(--compare-ind-w)
            [text]        minmax(12em, 32em)
            [right-marg]  minmax(3em, 1fr);
        max-width: 68rem;
        grid-auto-rows: auto;
        align-content: start;
        flex: 1;
        overflow: visible;
    }

    /* All direct children span all columns by default; .reading-grid and
       #comparison-panel override to subgrid. */
    article.passage-container > * { grid-column: 1 / -1; }

    article.passage-container > .reading-grid {
        grid-template-columns: subgrid;
    }

    /* Remove bottom padding when comparison panel is visible so the sticky
       panel sits flush against the viewport bottom. */
    article.passage-container:has(#comparison-panel.shown) {
        padding-bottom: 0;
    }
}

/* ── §4b  Passus grid base ───────────────────────────────────────────────── */
.reading-grid {
    display: grid;
    grid-auto-rows: auto;
    font-family: var(--font-text);
}


/* ── §4c  Column items ───────────────────────────────────────────────────── */
/* Each column wrapper is a subgrid child sharing both column and row tracks
   with the parent .reading-grid.  grid-row span is set inline by XSLT. */

/* Line number column (aria-hidden; decorative) */
.linenum-col {
    grid-column: linenum;
    display: grid;
    grid-template-rows: subgrid;
    align-items: start;
}

.linenumber {
    align-self: start;
    padding-left: 1.5ex;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
    line-height: 150%;
}

/* Text column */
.text-col {
    grid-column: text;
    display: grid;
    grid-template-columns: [line-body] 1fr;
    grid-template-rows: subgrid;
    line-height: 150%;
}

/* All text-col children span all internal columns.
   grid-row is set inline by XSLT; grid-column is constant. */
.linetext,
.linetext-cont,
.text-col .head,
.text-col .trailer,
.text-col .p,
.text-col .milestone,
.lg-gap,
.witness-notfound {
    grid-column: 1 / -1;
}


/* On desktop text pages, fixed header + toolbar both sit above content;
   override the generic main [id] rule from main.css with the full offset. */
@media (min-width: 900px) /* --bp-desktop */ {
    main [id] {
        scroll-margin-top: calc(var(--header-height, 50px) + var(--toolbar-ribbon-h, 28px) + 0.5rem);
    }
}

/* Hanging indent for wrapped lines. */
.linetext,
.text-col .head,
.text-col .trailer,
.text-col .p {
    padding-left: 1.5em;
    text-indent: -1.5em;
    text-indent: -1.5em each-line;
}

/* Compare-ind panel */
.compare-ind-panel {
    grid-column: compare-ind;
    display: grid;
    grid-template-rows: subgrid;
    align-items: start;
}

/* Witness-sigil panel (comparison view) */
.witness-sigil-panel {
    grid-column: compare-ind;
    display: grid;
    grid-template-rows: subgrid;
    align-items: start;
}


/* ── §4d  Margin columns ────────────────────────────────────────────────── */
/* Panel wrappers: subgrid for per-row alignment. */
.marginalia-left-panel {
    grid-column: left-marg;
    grid-template-columns: [left-marg] 1fr;
    display: grid;
    grid-template-rows: subgrid;
    align-items: start;
}

.marginalia-right-panel {
    grid-column: right-marg;
    grid-template-columns: [right-marg] 1fr;
    display: grid;
    grid-template-rows: subgrid;
    align-items: start;
}

/* Individual marginalia items */
.marginalia-left {
    grid-column: left-marg;
    align-self: start;
    text-align: right;
    padding-top: 0.3em;
    padding-bottom: 0.3em;
    padding-right: 0.75em;
    padding-left: 1.5em;
    text-indent: -1.5em;
    text-indent: -1.5em each-line;
    overflow: hidden;       /* Goal 4: never overlap text column */
    min-width: 0;           /* allow shrink below content size */
}

.marginalia-right {
    grid-column: right-marg;
    align-self: start;
    padding-top: 0.3em;
    padding-bottom: 0.3em;
    padding-left: calc(1ex + 1.5em);
    text-indent: -1.5em;
    text-indent: -1.5em each-line;
    overflow: hidden;       /* Goal 4: never overlap text column */
    min-width: 0;
}

.marginalia-center {
    grid-column: text;
    text-align: center;
    align-self: start;
}

/* Supralinear marginalia occupy their own interstitial grid row immediately before
   the associated text line. align-self:end places them at the bottom of that row
   (closest to the line below). Font is smaller to reflect the manuscript convention
   of squeezed interlinear writing. padding-bottom creates a small visual gap between
   the supralinear text and the line below.
   Note: when some supralinear items are later converted to ruby markup, this class
   will remain for the non-ruby cases. */
.marginalia-supralinear {
    align-self: end;
    font-size: 0.7em;
    line-height: 1;
    padding-bottom: 0.1em;
    font-style: italic;
    text-align: center;
}

/* When the supralinear shares the preceding blank row (follows-blank-row), align-self:end
   (inherited from .marginalia-supralinear) is all that's needed — it sits at the bottom
   of the shared lg-gap/lg-tag-open track, visually "written into" the blank line. */

/* Mobile-only controls — hidden by default.
   Responsive stages below activate them. */
.marg-indicator,
.marg-ind-left-panel,
.marg-ind-right-panel,
.compare-ind-panel,
.witness-sigil-panel,
.linenum-toggle-label {
    display: none;
}


/* ── §4e  Dropcap zones ─────────────────────────────────────────────────── */
/* Each dropcap zone is a subgrid wrapper with per-zone dropcap column. */
.dropcap-zone {
    display: grid;
    grid-template-columns: [dropcap] min-content [line-body] 1fr;
    grid-template-rows: subgrid;
    grid-column: 1 / -1;
    align-items: start;
}

.dropcap-zone .linetext,
.dropcap-zone .linetext-cont {
    grid-column: line-body;
}

/* Letter-specific column gaps (tight right-sidebearing letters). */
.dropcap-zone[data-letter="A"],
.dropcap-zone[data-letter="U"],
.dropcap-zone[data-letter="W"],
.dropcap-zone[data-letter="Y"],
.dropcap-zone[data-letter="R"],
.dropcap-zone[data-letter="N"] {
    column-gap: 0.15em;
}
.dropcap-zone[data-letter="T"],
.dropcap-zone[data-letter="F"],
.dropcap-zone[data-letter="C"],
.dropcap-zone[data-letter="P"] {
    column-gap: 0.1em;
}

.dropcap-filler { grid-column: line-body; height: 1.5em; }

.initial-letter-cell {
    grid-column: dropcap;
}


/* ── §5  Bordered-hi stitching ────────────────────────────────────────────────
   When ppea:cleave splits a line at <lb/>, ancestor <hi> elements with
   borders (boxed, BinR) get their shell copied into each segment.  These
   rules stitch them into one continuous box by removing internal borders
   at the split boundaries. */
.linetext:has(+ .linetext-cont) :is(.hi.boxed, .hi.BinR) {
    border-bottom: none;
}
.linetext-cont:has(+ .linetext-cont) :is(.hi.boxed, .hi.BinR) {
    border-top: none;
    border-bottom: none;
}
.linetext-cont:not(:has(+ .linetext-cont)) :is(.hi.boxed, .hi.BinR) {
    border-top: none;
}


/* ── §6  Verse group gap ─────────────────────────────────────────────────────
   Empty grid row between verse groups, one visual row tall. */
.lg-gap {
    height: 1lh;
}
/* Collapse gap when a folio/column break immediately precedes an lg boundary
   (the milestone already provides visual separation). */
.lg:has(> .milestone.folio) + .lg > .lg-gap:first-child,
.milestone.folio + .lg > .lg-gap:first-child {
    height: 0;
}


/* §7  Dropcap zone — STRIPPED (layout) */


/* ── §8  Dropcap initial letter ───────────────────────────────────────────────
   Cap-height spans from line 1's cap-top to line N's baseline:
     cap_target = (N-1) × 1.5em + 0.663em
     font-size  = cap_target / 0.663 × --il-width-scale
   When --il-width-scale < 1, font-size is reduced (narrowing the layout column)
   and scaleY(1/--il-width-scale) restores the visual height.  margin-top divides
   its em term by --il-width-scale so the cap-top stays on the same pixel.
   All constants from Junicode 2 metrics (docs/junicode2-font-metrics.md):
     sTypoAscender=860, sTypoDescender=−410, sCapHeight=663, UPM=1000. */
.initial-letter-cell {
    display: flex;
    align-items: flex-start;
    height: calc(var(--il-n) * 1.5em);
    overflow: visible;
    --text-fs: 1em;
}

.initial-letter-cell .initialLetter {
    font-stretch: condensed;
    font-size: calc(((var(--il-n) - 1) * 1.5em + 0.663em) / 0.663 * var(--il-width-scale));
    line-height: 1;
    margin-top: calc(-0.062em / var(--il-width-scale) + 0.312 * var(--text-fs));
    transform: scaleY(calc(1 / var(--il-width-scale)));
    transform-origin: top center;
}

/* Q has a significant tail descender — reduce font-size. */
.dropcap-zone[data-letter="Q"] .initialLetter {
    font-size: calc(((var(--il-n) - 1) * 1.5em + 0.663em) / 0.75 * var(--il-width-scale));
}

/* ── §8a  Wide-dropcap horizontal squeeze ─────────────────────────────────────
   Wide letters at large N occupy too much column width, wrapping the line-body
   text.  font-stretch: condensed (§8) gives ~14% reduction; these rules apply a
   further squeeze via --il-width-scale < 1 for the most problematic combinations.
   Math: see docs/junicode2-font-metrics.md §"Horizontal squeeze".
   Values empirically tuned at 1280px; worst-case passus governs each N bucket
   (CSS has no passus selector without a data-passus attribute on the zone). */

/* A: use ss02 alternate (A.alt1, 7% narrower advance width) for all sizes. */
.dropcap-zone[data-letter="A"] .initialLetter { font-feature-settings: 'ss02' 1; }

/* A o10: F.10 needs 0.70; F.9 is clear at 1.0 but o10 rule applies to both. */
.dropcap-zone[data-letter="A"][data-zone-n="10"] .initialLetter { --il-width-scale: 0.70; }
/* A o11: F.12 and F.15 need 0.58; F.11 and R.13 clear at 0.74 but share this rule. */
.dropcap-zone[data-letter="A"][data-zone-n="11"] .initialLetter { --il-width-scale: 0.58; }
/* A o12: R.15 clears at 0.62. */
.dropcap-zone[data-letter="A"][data-zone-n="12"] .initialLetter { --il-width-scale: 0.62; }

/* Þ (Thorn): wide glyph in R manuscript.
   o14 (R.10): 0.45 clears all wraps; 0.55 leaves 1.
   o16 (R.11): 0.40 clears all wraps; 0.45 leaves 1. — PENDING USER DECISION */
.dropcap-zone[data-letter="Þ"][data-zone-n="14"] .initialLetter { --il-width-scale: 0.45; }
.dropcap-zone[data-letter="Þ"][data-zone-n="16"] .initialLetter { --il-width-scale: 0.40; }

/* Screen-reader-only dropcap text */
.il-sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}


/* ── §9  Line number display states ───────────────────────────────────────────
   Athlone index numbers, visibility toggles, hover behavior, active line. */
.linenumber .index-linenum::before { content: "\00a0\00a0["; }
.linenumber .index-linenum::after  { content: "]"; }

.index-linenum { visibility: hidden; }

.critical-view .index-linenum,
.all-view .index-linenum,
.comparison-mode .index-linenum {
    visibility: visible;
}

.linenumber.hidden { display: none; }

.comparison-mode .linenumber.hidden { display: inline-block; }

.linenumber:hover { overflow: visible; }

.linenumber.hidden a { color: var(--color-border-light); }

.linenumber a {
    color: var(--color-text);
    text-decoration: none;
}

.linenumber a:hover { text-decoration: underline; }

.linenumber.hidden:hover a { color: var(--color-text); }

.linenumber:hover a { background-color: var(--color-bg-alt); }

.linenumber.active-line {
    font-weight: bold;
    color: inherit;
}

.linenumber.active-line a { color: var(--color-text); }


/* ── §10  Block element spacing ───────────────────────────────────────────── */
.head    { margin-bottom: 2em; }
.trailer { margin-top: 2em; }

/* Milestone: text-col subgrid item; grid-column via CSS rules above. */
.milestone {
    margin-top: 1em;
    margin-bottom: 1em;
    padding-left: 1.5em;
    font-weight: bold;
    align-self: start;
}


/* §11  Margin columns — STRIPPED (layout) */


/* §12  Marg panel wrappers — STRIPPED (layout)
   Keeping content-level marginalia styling below. */

/* Close trigger inside each panel — hidden; kept for future JS use. */
.marg-close { display: none; }

/* Marginalia content */
.marginalia {
    display: block;
    overflow-wrap: break-word;
    cursor: pointer;
    line-height: 100%;
    font-size: 0.875em;
}

/* Inline fw/marginalia: rendered within the text flow */
.fw.inline,
.marginalia.inline {
    display: inline;
    font-size: 0.75em;
    color: var(--color-text-faint);
}


/* ══════════════════════════════════════════════════════════════════════════════
   PART B — EDITION TOOLBAR & UI CONTROLS
   ══════════════════════════════════════════════════════════════════════════════ */

/* ── §12b  Toolbar ribbon ────────────────────────────────────────────────── */
.toolbar-wrap { display: contents; }   /* wrapper is layout-invisible */

.toolbar-ribbon {
    position: fixed;
    top: var(--header-height, 50px);
    left: 0;
    right: 0;
    z-index: 20;   /* toolbar tier — below header (25) so header flyouts
                      paint over it */
    background: var(--color-bg-subtle);
    border-bottom: 1px solid var(--color-border);
    padding: 0 1.5ex;
    height: var(--toolbar-ribbon-h, 28px);
    font-size: 0.8em;
}

.toolbar-items {
    display: flex;
    align-items: center;
    flex-wrap: nowrap;
    justify-content: space-between;
    height: 100%;
    list-style: none;
    margin: 0 auto;
    padding: 0;
    max-width: var(--content-max-width, 1200px);
}

.toolbar-items > li {
    display: flex;
    align-items: center;
    white-space: nowrap;
}

/* Hide Passus/Folio labels — the selectors are self-explanatory */
.toolbar-ribbon .label-above-component { display: none; }

/* Utility group (</>, Download, Search).
   At desktop, space-between on .toolbar-items distributes all items
   evenly across the content width — no auto-margin needed.
   At < 650px §30a-phone resets for edge-to-edge layout.
   At 650–899 §30b also resets. */
.toolbar-links {
    display: flex;
    gap: 1.5ex;
}

.toolbar-links a {
    color: var(--color-text-secondary);
    text-decoration: none;
}

.toolbar-links a:hover {
    color: var(--color-text);
}

.icon-download {
    width: 1em;
    height: 1em;
    vertical-align: middle;
}

/* Front matter dropdown removed from template — Introduction and
   Preface are already in the passus combobox/select at all widths. */

.toolbar-items > li { position: relative; }

/* toolbar-submenu styles removed — front matter dropdown eliminated. */

.toolbar-hidden-controls {
    position: absolute;
    width: 0;
    height: 0;
    overflow: hidden;
}

/* Compact overrides for controls inside the toolbar */
.toolbar-ribbon .radio-button-group {
    border-top: none;
    padding: 0;
    display: flex;
    align-items: center;
    gap: 0;
}

.toolbar-ribbon .radio-button-group > legend.component-label {
    /* Visually hidden but keeps accessibility */
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
}

.toolbar-ribbon .radio-button-group .radio-button {
    padding: 0.2ex 0.7ex;
    font-size: 0.95em;
}

.toolbar-ribbon .linenum-toggle-label,
.toolbar-ribbon .tags-toggle-label {
    align-items: center;
    font-size: 0.95em;
    padding: 0.2ex 0.5ex;
    cursor: pointer;
}

/* Tags are always hidden by default, so the toggle is always useful. */
.toolbar-ribbon .tags-toggle-label { display: inline-flex; }

/* Line numbers are visible by default at Stages A and B (≥ --bp-tablet),
   so the toggle is only offered at narrower widths where lines would
   otherwise be hidden.  The entire <li> is hidden (not just the label)
   so it doesn't leave empty flex-gap space in the toolbar. */
.toolbar-items > li.toolbar-linenum { display: none; }

@media (max-width: 649px) /* < --bp-tablet */ {
    .toolbar-items > li.toolbar-linenum      { display: flex; }
    .toolbar-ribbon .linenum-toggle-label    { display: inline-flex; }
}

/* Active state when toggles are on */
body:has(#linenum-toggle:checked) .toolbar-ribbon .linenum-toggle-label,
body:has(#tags-toggle:checked) .toolbar-ribbon .tags-toggle-label {
    background: var(--color-text);
    color: var(--color-bg);
    border-color: var(--color-text);
}

.toolbar-ribbon .icon-passage-nav {
    width: 12px;
    height: 12px;
}

.toolbar-ribbon #passage-component #prev-passage,
.toolbar-ribbon #passage-component #next-passage {
    margin-left: 0.8ex;
    margin-right: 0.8ex;
}

/* Adjust main content top padding to account for both header and toolbar */
body:has(.toolbar-ribbon) main {
    padding-top: calc(75px + var(--toolbar-ribbon-h, 28px));
}

/* ── §12c  Bottom passus navigation ──────────────────────────────────────── */
/* Prev/next links at the bottom of the text.  Fades in as the user
   scrolls near, signalling supplementary navigation.  Centered within
   the content column.

   Fade strategy (progressive enhancement, easy to strip later):
     1. Base: fully visible (safe default if both CSS & JS fail).
     2. @supports (animation-timeline: view()): CSS Scroll-Driven
        Animation handles the fade — Chrome/Edge today.
     3. JS fallback (.js-fade-in class on <html>): IntersectionObserver
        hides the nav initially, adds .is-visible on intersection —
        covers Safari until it ships scroll-driven animations.
   When all browsers support animation-timeline, delete the JS
   fallback and the .js-fade-in / .is-visible rules below. */
/* Reduce main's bottom padding when the bottom nav is present —
   the nav itself provides the visual gap and footer clearance. */
main:has(~ .bottom-passage-nav) {
    padding-bottom: 1.5em;
}

.bottom-passage-nav {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 1em 1em 0.5em;
    margin-top: 0;
    margin-bottom: 1.5em;
    width: 100%;
    max-width: 40em;
    margin-inline: auto;
    position: relative;
}

/* Divider line — pseudo-element so it can animate from center */
.bottom-passage-nav::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 1px;
    background: var(--color-border);
    transform-origin: center;
}

/* ── CSS path: Scroll-Driven Animation (Chrome/Edge) ──────────── */
@supports (animation-timeline: view()) {
    @keyframes bottom-nav-fade-in {
        from { opacity: 0; transform: translateY(8px); }
        to   { opacity: 1; transform: translateY(0); }
    }

    @keyframes divider-expand {
        from { transform: scaleX(0); }
        to   { transform: scaleX(1); }
    }

    .bottom-passage-nav {
        animation: bottom-nav-fade-in linear both;
        animation-timeline: view();
        animation-range: entry 0% entry 40%;
    }

    .bottom-passage-nav::before {
        animation: divider-expand linear both;
        animation-timeline: view();
        animation-range: entry 0% entry 30%;
    }
}

/* ── JS path: IntersectionObserver fallback (Safari) ──────────── */
/* piers.js adds .js-fade-in to <html> when scroll-driven animations
   are NOT supported, then uses IntersectionObserver to add .is-visible.
   Delete this block once animation-timeline has universal support. */
.js-fade-in .bottom-passage-nav {
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 0.8s ease, transform 0.8s ease;
}

.js-fade-in .bottom-passage-nav::before {
    transform: scaleX(0);
    transition: transform 0.6s ease 0.15s;  /* slight delay so line follows fade */
}

.js-fade-in .bottom-passage-nav.is-visible {
    opacity: 1;
    transform: translateY(0);
}

.js-fade-in .bottom-passage-nav.is-visible::before {
    transform: scaleX(1);
}

.bottom-passage-prev,
.bottom-passage-next {
    color: var(--color-accent);
    text-decoration: none;
    padding: 0.4em 0.8em;
    border: 1px solid var(--color-accent);
    border-radius: 3px;
    font-size: 0.85em;
}

.bottom-passage-prev:hover,
.bottom-passage-next:hover {
    background: var(--color-accent);
    color: var(--color-bg);
}

.bottom-passage-prev.disabled,
.bottom-passage-next.disabled {
    visibility: hidden;
}

.bottom-passage-current {
    font-size: 0.8em;
    color: var(--color-text-secondary);
}

/* ── §13  Passus navigation ───────────────────────────────────────────────── */
.toolbar-component#passage-component {
    display: flex;
    flex-direction: row;
    align-items: center;
}

/* Always <a> elements now (disabled: role="button" + aria-disabled,
   enabled: plain link).  Fixed width prevents layout shift when
   visibility:hidden hides the disabled arrow. */
#passage-component #prev-passage,
#passage-component #next-passage {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 12px;            /* match .icon-passage-nav size */
    margin-left: 1.5ex;
    margin-right: 1.5ex;
    color: var(--color-text-disabled);
    text-decoration: none;
    cursor: pointer;
}

#prev-passage a:hover,
#next-passage a:hover {
    color: var(--color-text);
}

.label-above-component h4 { margin: 0; }

#passage-component [aria-disabled="true"] {
    visibility: hidden; /* preserve width for symmetry */
}

span.label-above-component {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-around;
}


/* ── §14  Passus & folio selector layout ─────────────────────────────────── */
.selection-component select { width: 100%; }

.selection-component h4.label-above-component {
    font-size: 100%;
    text-align: center;
    margin: 0;
}


/* ── §15  View-mode radio buttons ─────────────────────────────────────────── */
/* Mobile-only native select (shown in §30 media block; hidden here for desktop) */
.view-select-mobile { display: none; }

.radio-button-group {
    border: none;
    border-top: 1px var(--color-text) solid;
    text-transform: none;
}

.radio-button-group > legend.component-label { line-height: 1; }

.radio-button-group .radio-button {
    background-image: var(--btn-gradient);
    color: var(--color-text-muted);
    font-weight: normal;
    font-family: var(--font-ui);
    padding: 0.5ex 1ex;
}

.radio-button-group .radio-button:first-of-type { border-radius: 3px 0 0 3px; }
.radio-button-group .radio-button:last-of-type  { border-radius: 0 3px 3px 0; }

.radio-button-group label:not(:first-of-type) {
    border-left: 1px var(--color-border-medium) solid;
}

.radio-button-group input[type='radio']:checked + label {
    background-image: var(--btn-gradient-active);
    box-shadow: var(--btn-shadow-active);
    color: var(--color-text-strong);
    text-decoration: underline dotted var(--color-text-strong);
}

.radio-button-group input[type='radio']:disabled + label {
    color: var(--color-text-disabled);
    background-image: var(--btn-gradient-disabled);
}

/* Focus ring for radio buttons */
.radio-button-group input[type='radio']:focus + label.radio-button {
    outline: var(--color-focus) 2px solid;
}

@media (-webkit-min-device-pixel-ratio:0) {
    .radio-button-group input[type='radio']:focus + label.radio-button {
        outline-color: -webkit-focus-ring-color;
        outline-style: auto;
    }
}


/* ── §16  Toggle labels (line numbers, marginalia) ────────────────────────── */
/* display:none default is in §12 above so mobile media queries win cascade. */
.linenum-toggle-label {
    background-image: var(--btn-gradient);
    color: var(--color-text-muted);
    font-weight: normal;
    font-family: var(--font-ui);
    font-size: inherit;
    padding: 0.5ex 1ex;
    border-radius: 3px;
    cursor: pointer;
    user-select: none;
    border-top: 1px var(--color-text) solid;
}

.linenum-toggle-cb:checked + .linenum-toggle-label,
.tags-toggle-cb:checked + .tags-toggle-label {
    background-image: var(--btn-gradient-active);
    box-shadow: var(--btn-shadow-active);
    color: var(--color-text-strong);
    text-decoration: underline dotted var(--color-text-strong);
}

.linenum-toggle-cb:focus + .linenum-toggle-label,
.tags-toggle-cb:focus + .tags-toggle-label {
    outline: var(--color-focus) 2px solid;
}

@media (-webkit-min-device-pixel-ratio:0) {
    .linenum-toggle-cb:focus + .linenum-toggle-label,
    .tags-toggle-cb:focus + .tags-toggle-label {
        outline-color: -webkit-focus-ring-color;
        outline-style: auto;
    }
}




/* ── §19  Intro sidebar, §19b desktop sidebar, §19a intro prose ──────────────
   Moved to edition_intro.css (loaded conditionally on intro pages only). */


/* ── §20  Notes ───────────────────────────────────────────────────────────── */
/* Note markers are <a> elements linking to the note store (stand-off
   annotation pattern).  Progressive enhancement: without JS the link
   navigates to the endnote; with JS the popover intercepts the click. */
a.noteChar {
    all: unset;               /* strip browser button defaults */
    display: inline-block;    /* required for ::first-letter pseudo-element */
    text-indent: 0;           /* override inherited hanging indent from .linetext */
    vertical-align: super;    /* raise as superscript; ::first-letter cancels for first char */
    color: var(--color-text);
    cursor: pointer;
    font-size: 10pt;
    font-family: 'Times New Roman', Times, serif;
    font-weight: bold;
    line-height: 1;           /* prevent button height from disrupting line */
    text-transform: lowercase;
    font-variant-caps: small-caps;
    -webkit-user-select: none; /* keep markers out of text selections */
    user-select: none;
}

/* First letter: full uppercase, cancels small-caps and superscript.
   Net effect on single-letter markers (N, C, T, P): full-size, baseline.
   On multi-letter (LX, LG): first letter at baseline, trailing chars superscript. */
a.noteChar::first-letter {
    font-variant-caps: normal;
    text-transform: uppercase;
    vertical-align: sub;
}

a.noteChar:hover {
    border-bottom: 1px dotted var(--color-note-hover);
}

/* Active state: marker for the currently-open note popover */
a.noteChar[aria-expanded="true"] {
    color: light-dark(red, #ff6666);
}

/* ── §20a  Note store (no-JS endnotes) ───────────────────────────────────── */
/* Visible by default as an endnotes section for no-JS users.
   Hidden via CSS when JS is active (html.js set by piers.js on init),
   which also covers note stores injected later via AJAX (comparison panel). */
html.js .note-store { display: none; }

.note-store {
    margin-top: 2em;
    padding-top: 1em;
    border-top: 1px solid var(--color-border);
    font-size: small;
    font-family: var(--font-ui);
}

.note-store .note-body {
    margin-bottom: 1em;
    padding-left: 1em;
    border-left: 2px solid var(--color-border-light);
}

.note-store .note-backref {
    margin-left: 0.5em;
    text-decoration: none;
    color: var(--color-link);
}

.note-store .note-backref:hover {
    text-decoration: underline;
}




/* ══════════════════════════════════════════════════════════════════════════════
   PART C — RESPONSIVE STAGES
   ══════════════════════════════════════════════════════════════════════════════
   Progressive disclosure (Goal 3):
     Stage A (≥ 900px)  — all streams inline, dual line numbers
     Stage B (650–899px) — Athlone numbers hidden, compact linenum
     Stage C (500–649px) — line numbers hidden, inline marginalia in
                           equal columns, text capped at 24em
     Stage D (< 500px)  — marginalia slide panels
     Stage E (< 400px)  — narrow phone tweaks  [TBD]
   ══════════════════════════════════════════════════════════════════════════════ */


/* ── §25  Stage A: Wide desktop (≥ --bp-desktop) ────────────────────────── */
/* All five content streams visible inline.  Dual line numbers.
   Compare-ind column moves to the far left (before line numbers) so
   the buttons sit beside, not between, text columns. */
@media (min-width: 900px) /* --bp-desktop */ {
    :root { --linenum-w: auto; }

    /* Reorder grid: compare-ind to the left of line numbers.
       Pad the article so indicators don't touch the viewport edge
       at narrower widths within this range. */
    article.passage-container.comparison-mode {
        --compare-ind-w: 16px;
        padding-left: 4px;
        grid-template-columns:
            [compare-ind] var(--compare-ind-w)
            [linenum]     var(--linenum-w)
            [left-marg]   minmax(3em, 1fr)
            [text]        minmax(12em, 32em)
            [right-marg]  minmax(3em, 1fr);
    }

    .comparison-mode .compare-ind-panel {
        display: grid;
        grid-column: compare-ind;
        grid-template-rows: subgrid;
        align-items: start;
        z-index: 2;
    }

    .compare-ind-btn {
        display: flex;
        align-items: center;
        justify-content: end;
        width: 16px;
        padding: 0;
        border: none;
        background: none;
        cursor: pointer;
        -webkit-user-select: none;
        user-select: none;
        font-size: 0;
        color: var(--color-text-secondary);
        opacity: 0.45;
        transition: opacity var(--transition-fast);
    }

    .compare-ind-btn::before {
        content: '';
        display: block;
        width: 11px;
        height: 11px;
        margin-top: 5px;
        background-image:
            linear-gradient(currentColor, currentColor),
            linear-gradient(currentColor, currentColor),
            linear-gradient(currentColor, currentColor);
        background-size: 100% 2px;
        background-position: 0 0, 0 4.5px, 0 9px;
        background-repeat: no-repeat;
        transition: background-size 0.25s ease, background-position 0.25s ease;
    }

    .compare-ind-btn:hover,
    .compare-ind-btn:active { opacity: 1; }

    .compare-ind-btn.compare-active { opacity: 1; }

    .compare-ind-btn.compare-active::before {
        background-size: 100% 3px, 100% 3px, 100% 3px;
        background-position: 0 0, 0 4px, 0 8px;
        outline: 1.5px solid currentColor;
        border-radius: 1.5px;
    }

    /* At wide desktop, show all linenumbers including hidden ones in
       comparison view. */
    .comparison-mode .linenumber.hidden {
        display: inline-block;
        color: var(--color-text-faint);
    }
}


/* ── §26  Stage B: Compact desktop (--bp-tablet to --bp-desktop) ─────────── */
/* Marginalia still inline.  Athlone numbers hidden, compact single line
   numbers.  Compare indicator buttons appear.

   The text column max is reduced from 32em to 26em so that marginalia
   columns get meaningful width at medium viewports (700–899px) instead
   of being squeezed to their 3em floor.

   Left-marg gets 1.3fr vs right-marg 1fr: the extra weight shifts
   the text column rightward, compensating for the linenum column's
   asymmetric space consumption on the left.  This centers the text
   visually between the viewport edges. */
@media (max-width: 899px) and (min-width: 650px) /* --bp-tablet to --bp-desktop */ {
    :root { --linenum-w: auto; }

    /* Override §4a grid: narrower text max, asymmetric margins */
    article.passage-container {
        grid-template-columns:
            [linenum]     var(--linenum-w)
            [left-marg]   minmax(3em, 1.3fr)
            [compare-ind] var(--compare-ind-w)
            [text]        minmax(12em, 26em)
            [right-marg]  minmax(3em, 1fr);
    }

    .linenum-col { font-size: 0.7em; }

    .linenumber {
        white-space: normal;
        text-overflow: clip;
        padding-left: 0.3em;
    }

    /* Stack local num and Athlone num on separate lines */
    .linenum-col .ms-linenum,
    .linenum-col .index-linenum { display: block; white-space: nowrap; }
    .linenum-col .linenumber .index-linenum::before { content: "["; }
    .linenum-col .linenumber .index-linenum::after  { content: "]"; }

    /* Justified text for narrower columns */
    .linetext, .text-col .head, .text-col .trailer, .text-col .p,
    .marginalia-left .marginalia, .marginalia-right .marginalia, .marginalia-center.marginalia {
        text-align: justify;
    }

    /* Container padding.  Exposed as --article-pad-x so #comparison-panel
       can compute its mobile full-bleed negative margin (main's padding
       + this article padding must both be absorbed to reach the viewport
       edges — see edition_compare.css). */
    article.passage-container {
        --article-pad-x: 7px;
        padding-left: var(--article-pad-x);
        padding-right: var(--article-pad-x);
    }

    /* Compare indicator buttons */
    article.passage-container.comparison-mode {
        --compare-ind-w: 16px;
    }

    .comparison-mode .compare-ind-panel {
        display: grid;
        grid-column: compare-ind;
        grid-template-rows: subgrid;
        align-items: start;
        z-index: 2;
    }

    .compare-ind-btn {
        display: flex;
        align-items: center;
        justify-content: start;
        width: 16px;
        padding: 0;
        border: none;
        background: none;
        cursor: pointer;
        user-select: none;
        font-size: 0;
        color: var(--color-text-secondary);
        opacity: 0.45;
        transition: opacity var(--transition-fast);
    }

    .compare-ind-btn::before {
        content: '';
        display: block;
        width: 11px;
        height: 11px;
        margin-top: 5px;
        background-image:
            linear-gradient(currentColor, currentColor),
            linear-gradient(currentColor, currentColor),
            linear-gradient(currentColor, currentColor);
        background-size: 100% 2px;
        background-position: 0 0, 0 4.5px, 0 9px;
        background-repeat: no-repeat;
        transition: background-size 0.25s ease, background-position 0.25s ease;
    }

    .compare-ind-btn:hover,
    .compare-ind-btn:active { opacity: 1; }

    .compare-ind-btn.compare-active { opacity: 1; }

    .compare-ind-btn.compare-active::before {
        background-size: 100% 3px, 100% 3px, 100% 3px;
        background-position: 0 0, 0 4px, 0 8px;
        outline: 1.5px solid currentColor;
        border-radius: 1.5px;
    }

    /* Witness sigils are hidden at ≥650px because line numbers carry the
       cross-witness link in the main text column (compare-link on each
       linenumber). See §26d for the <650 button styling. */
    #compare-container .witness-sigil-panel,
    .witness-sigil { display: none; }

    /* Disable compare links on line numbers (compare-ind replaces them) */
    .comparison-mode .linenumber.hidden { display: none; }

    .comparison-mode a.compare-link {
        pointer-events: none;
        cursor: default;
        color: inherit;
        text-decoration: none;
    }
}


/* ── §26b  Stage C: Tablet (--bp-phone to --bp-tablet) ───────────────────── */
/* Line numbers hidden.  Marginalia remain inline in equal columns flanking
   a capped text column.  The 3-column grid (left-marg | text | right-marg)
   centers the text and gives both margins equal space.

   The text cap is 24em — tighter than the 26em used at 650–899px — so
   that marginalia columns get meaningful width at these narrower viewports.
   Compare indicators appear since line numbers no longer serve as links. */
@media (max-width: 649px) and (min-width: 500px) /* --bp-phone to --bp-tablet */ {
    :root {
        --linenum-w: 0px;
        --compare-ind-w: 0px;
    }

    /* Override §4a grid: 3-column layout, no linenum, equal margins.
       compare-ind uses the variable so it appears in comparison-mode.
       --article-pad-x is re-declared here for the same reason as §26
       (see note above). */
    article.passage-container {
        --article-pad-x: 7px;
        grid-template-columns:
            [linenum]     0px
            [left-marg]   minmax(3em, 1fr)
            [compare-ind] var(--compare-ind-w)
            [text]        minmax(12em, 24em)
            [right-marg]  minmax(3em, 1fr);
        padding-left: var(--article-pad-x);
        padding-right: var(--article-pad-x);
    }

    /* Linenum column: always sized and styled (compact), but hidden via
       opacity/visibility so toggling it doesn't cause a layout reflow
       or scroll jump.  The 0px grid track means it overlays the left
       margin rather than pushing content.

       Negative margin-left pulls the overlay flush to the viewport's
       left edge, escaping main's 1ex padding + article's 7px padding
       (= 15px total).  The extra extent is not clipped here because
       (a) article.passage-container has no overflow:clip at this stage,
       and (b) html,body { overflow-x: clip } catches any overshoot
       past the viewport edge.  Width is bumped so the inner content
       area (after padding) stays 5em as before. */
    .linenum-col {
        overflow: visible;
        min-width: 0;
        margin-left: -15px;
        padding-left: 15px;
        box-sizing: border-box;
        width: calc(5em + 15px);
        min-height: 100%;
        z-index: 100;
        opacity: 0;
        visibility: hidden;
        background: var(--color-bg-glass);
        -webkit-backdrop-filter: var(--glass-blur-strong);
        backdrop-filter: var(--glass-blur-strong);
        transition: opacity var(--transition-fast), visibility var(--transition-fast);
        font-size: 0.7em;
    }

    .linenumber {
        white-space: normal;
        text-overflow: clip;
        padding-left: 0.3em;
    }

    /* Stack local num and Athlone num on separate lines */
    .linenum-col .ms-linenum,
    .linenum-col .index-linenum { display: block; white-space: nowrap; }
    .linenum-col .linenumber .index-linenum::before { content: "["; }
    .linenum-col .linenumber .index-linenum::after  { content: "]"; }

    body:has(#linenum-toggle:checked) .linenum-col {
        opacity: 1;
        visibility: visible;
    }

    /* Justified text for narrower columns */
    .linetext, .text-col .head, .text-col .trailer, .text-col .p,
    .marginalia-left .marginalia, .marginalia-right .marginalia, .marginalia-center.marginalia {
        text-align: justify;
    }

    /* Compare indicator buttons (same as §26). */
    article.passage-container.comparison-mode {
        --compare-ind-w: 16px;
    }

    .comparison-mode .compare-ind-panel {
        display: grid;
        grid-column: compare-ind;
        grid-template-rows: subgrid;
        align-items: start;
        z-index: 2;
    }

    .compare-ind-btn {
        display: flex;
        align-items: center;
        justify-content: start;
        width: 16px;
        padding: 0;
        border: none;
        background: none;
        cursor: pointer;
        user-select: none;
        font-size: 0;
        color: var(--color-text-secondary);
        opacity: 0.45;
        transition: opacity var(--transition-fast);
    }

    .compare-ind-btn::before {
        content: '';
        display: block;
        width: 11px;
        height: 11px;
        margin-top: 5px;
        background-image:
            linear-gradient(currentColor, currentColor),
            linear-gradient(currentColor, currentColor),
            linear-gradient(currentColor, currentColor);
        background-size: 100% 2px;
        background-position: 0 0, 0 4.5px, 0 9px;
        background-repeat: no-repeat;
        transition: background-size 0.25s ease, background-position 0.25s ease;
    }

    .compare-ind-btn:hover,
    .compare-ind-btn:active { opacity: 1; }

    .compare-ind-btn.compare-active { opacity: 1; }

    .compare-ind-btn.compare-active::before {
        background-size: 100% 3px, 100% 3px, 100% 3px;
        background-position: 0 0, 0 4px, 0 8px;
        outline: 1.5px solid currentColor;
        border-radius: 1.5px;
    }

    /* Witness sigil buttons: see shared §26d block below for styling
       (applies to Stage C and Stage D identically). */

    /* Disable compare links on line numbers */
    .comparison-mode .linenumber.hidden { display: none; }

    .comparison-mode a.compare-link {
        pointer-events: none;
        cursor: default;
        color: inherit;
        text-decoration: none;
    }
}


/* ── §26d  Witness sigil buttons (< --bp-tablet) ─────────────────────────── */
/* Bordered-button sigils appear at Stage C and Stage D (< 650px), where
   line numbers are hidden and the sigil column becomes the primary
   cross-witness click target. At ≥ 650px the sigils are hidden (see §26)
   because line numbers in the main text column carry the cross-witness
   link directly. Button styling is shared between the two <650 stages so
   the visual is identical across phone and tablet widths. */
@media (max-width: 649px) /* < --bp-tablet */ {
    #compare-container .witness-sigil-panel {
        display: grid;
        grid-column: compare-ind;
        grid-template-rows: subgrid;
        align-items: start;
        z-index: 2;
        /* Clip any rotated-child sizing quirks (Safari calculates a
           vertical writing-mode element's intrinsic min-size from its
           inline text length, which can push the subgrid track wider
           than declared). min-width:0 lets the track honour its fixed
           16px width; overflow:hidden stops any remainder from bleeding
           into the text column or creating horizontal scroll. */
        min-width: 0;
        overflow: hidden;
        /* Publish the text line's cap-height and line-height as resolved
           lengths so .witness-sigil can size itself relative to the
           adjacent text row (1cap/1lh would otherwise compute against
           the sigil's own shrunken font-size). Requires @property
           registration so the value is computed HERE (where font
           inherits from the text column) rather than on the child. */
        --text-cap: 1cap;
        --text-lh: 1lh;
    }

    .witness-sigil {
        /* Rotated vertical chip. Text runs top-to-bottom (reads like a
           tab label tilted 90°) so any sigil length fits the narrow
           16px compare-ind column regardless of letter count. The chip
           is a fixed-width vertical strip whose height grows with the
           content (multi-letter sigils get taller, not wider). A top
           margin centres the chip on the first text line's centre. */
        box-sizing: border-box;
        --sigil-w: calc(var(--text-cap) + 2px);
        /* Minimum vertical length of the pill so single-letter sigils
           still read as a proper pill (not a cramped square). Locked to
           one text line-height so the pill fills the adjacent line
           vertically; multi-letter sigils grow beyond this as needed. */
        --sigil-min-h: var(--text-lh);
        width: var(--sigil-w);
        max-width: var(--sigil-w);
        min-width: 0;
        min-height: var(--sigil-min-h);
        margin: 0 2px 0 0;
        padding: 2px 1px;
        justify-self: start;
        align-self: start;
        /* Prevent this rotated item from contributing its intrinsic
           block-axis (vertical text length) to the parent grid track's
           min-content size in Safari. */
        contain: layout;

        /* Filled chip, no border — colour + fill carry the affordance. */
        border: 0;
        border-radius: 3px;
        background: light-dark(rgba(0, 100, 200, 0.12),
                               rgba(120, 170, 255, 0.18));

        /* Colour + bold for persistent actionability (no hover needed).
           Use the UI sans-serif to contrast with the Junicode text body
           and signal "chrome/control" rather than "text content". */
        font-family: var(--font-ui);
        font-size: 0.6em;
        font-weight: bold;
        letter-spacing: 0;
        color: var(--color-link);
        /* Rotate text 90° clockwise; reads top-to-bottom. vertical-rl
           + text-orientation:mixed rotates Latin glyphs as whole
           letters (not stacked upright). */
        writing-mode: vertical-rl;
        text-orientation: mixed;
        white-space: nowrap;
        line-height: 1;
        user-select: none;
        /* Flex centre in both axes.  In vertical-rl, justify-content
           controls the inline axis (vertical in physical coords) and
           align-items controls the cross axis (horizontal). Both set
           to center → glyph centred in the pill both ways. */
        display: flex;
        justify-content: center;
        align-items: center;
        text-decoration: none;
    }

    a.witness-sigil:hover,
    a.witness-sigil:focus {
        background: light-dark(rgba(0, 100, 200, 0.22),
                               rgba(120, 170, 255, 0.3));
        text-decoration: none;
    }

    /* Superscripted numerals in rich-text sigils (e.g. Cr¹, Hm²).
       Because the container is in vertical writing-mode, <sup>'s
       vertical-align behaves relative to the rotated baseline — the
       numeral sits "above" (i.e. to the right of) the base letters
       when read left-to-right in world orientation. */
    .witness-sigil sup {
        font-size: 0.75em;
        line-height: 0;
        vertical-align: super;
    }

    /* Non-linked sigils belong to witnesses with no matching reading
       (rendered as <span>, not <a>). Grey fill + muted text signal
       the chip is inert. Default cursor (not text I-beam) reinforces
       non-interactivity. */
    span.witness-sigil {
        background: light-dark(rgba(0, 0, 0, 0.06),
                               rgba(255, 255, 255, 0.08));
        color: var(--color-text-faint);
        cursor: default;
    }
}


/* ── §27  Stage D: Phone slide-panel layout (< --bp-phone) ────────────────── */
/* Marginalia leave inline flow.  .reading-grid defines its own 7-column
   grid (not subgrid) with marginalia panels pushed off-screen via negative
   margins, revealed by slide toggles.  Line numbers go to overlay toggle.

   Progressive disclosure order per spec:
     1. Athlone numbers hidden (< --bp-desktop, §26)
     2. Line numbers hidden, marginalia still inline (< --bp-tablet, §26b)
     3. Marginalia slide panels (< --bp-phone, this section) */
@media (max-width: 499px) /* < --bp-phone */ {
    :root { --linenum-w: 0px; }

    /* Zero <main> and article horizontal padding so the reading-grid's
       negative margins (-160px each side) are calculated against the
       full viewport width.  Without this, main's --main-pad-x (1ex)
       narrows the containing block, causing the right marginalia panel
       to peek in by ~1ex instead of sitting fully off-screen.

       No overflow-x:clip here: html,body already have overflow-x:clip
       globally, which catches the -160px overshoot.  Removing this
       local clip lets the linenum overlay extend leftward (via negative
       margin-left) past article's edge to reach the viewport's left. */
    main:has(article.passage-container) {
        --main-pad-x: 0px;
        padding-left: 0;
        padding-right: 0;
    }

    article.passage-container {
        padding-left: 0;
        padding-right: 0;
    }

    /* Kill any JS-applied right-marg proximity shift (Goal 7).
       Below 500px marginalia are in slide panels, not inline.  This clears
       stale transforms immediately on resize without waiting for JS debounce. */
    .marginalia-right-panel { transform: none !important; }

    /* Justified text for narrow columns */
    .linetext, .text-col .head, .text-col .trailer, .text-col .p {
        text-align: justify;
    }

    /* Passus grid: own 7-column grid with off-screen marginalia panels. */
    .reading-grid {
        --marg-panel-w: 160px;
        --marg-ind-w: 32px;
        --slide-offset: 0px;
        margin-left: calc(-1 * var(--marg-panel-w));
        margin-right: calc(-1 * var(--marg-panel-w));
        grid-template-columns:
            [left-marg]   var(--marg-panel-w)
            [linenum]     0px
            [left-ind]    var(--marg-ind-w)
            [compare-ind] var(--compare-ind-w)
            [text]        1fr
            [right-ind]   var(--marg-ind-w)
            [right-marg]  var(--marg-panel-w);
        transform: translateX(var(--slide-offset));
        transition: transform var(--transition-medium);
    }

    /* Slide toggles */
    body:has(#marg-left-toggle:checked) .reading-grid {
        --slide-offset: var(--marg-panel-w);
    }
    body:has(#marg-right-toggle:checked) .reading-grid {
        --slide-offset: calc(-1 * var(--marg-panel-w));
    }

    .text-col { z-index: 1; }

    /* Hide direct marginalia items (panels contain them) */
    .reading-grid > .marginalia-left,
    .reading-grid > .marginalia-right { display: none; }

    /* Left panel spans left-marg through left-ind */
    .marginalia-left-panel {
        grid-column: left-marg / left-ind;
        isolation: isolate;
        z-index: 1;
    }

    /* Indicator arrow panels */
    .marg-ind-left-panel {
        display: grid;
        grid-column: left-ind;
        grid-template-rows: subgrid;
        align-items: start;
        z-index: 2;
    }

    .marg-ind-right-panel {
        display: grid;
        grid-column: right-ind;
        grid-template-rows: subgrid;
        align-items: start;
        z-index: 2;
    }

    /* Indicator arrow styling */
    .marg-ind-left,
    .marg-ind-right {
        display: flex;
        align-items: center;
        justify-content: center;
        width: var(--marg-ind-w);
        height: 1.5em;
        cursor: pointer;
        user-select: none;
        align-self: start;
        transition: transform var(--transition-medium),
                    opacity var(--transition-fast);
        opacity: 0.45;
    }

    .marg-ind-left::before,
    .marg-ind-right::before {
        content: '';
        display: block;
        width: 11px;
        height: 16px;
        background: currentColor;
        color: var(--color-text-secondary);
        clip-path: polygon(0% 0%, 100% 50%, 0% 100%);
    }

    .marg-ind-left { transform: rotate(180deg); }

    body:has(#marg-left-toggle:checked)  .marg-ind-left  { opacity: 1; transform: rotate(0deg); }
    body:has(#marg-right-toggle:checked) .marg-ind-right { opacity: 1; transform: rotate(180deg); }

    /* Line number column: hidden but available via overlay toggle.
       Compact styling matches the always-visible column at ≥ 650px:
       small font, stacked local/Athlone numbers, tight padding.

       Negative margin-left pulls the overlay flush to the viewport's
       left edge, escaping main's 1ex (~8px) horizontal padding.
       Article padding is 0 at this stage, so the single 8px offset
       covers it.  html,body { overflow-x: clip } catches the overshoot.

       The translateX cancels .reading-grid's own slide transform so
       the overlay stays pinned to the viewport while the marginalia
       panels slide in and out.  Transition matches the reading-grid so
       the cancel stays in sync. */
    .linenum-col {
        overflow: visible;
        min-width: 0;
        margin-left: -8px;
        padding-left: 8px;
        box-sizing: border-box;
        width: calc(5em + 8px);
        min-height: 100%;
        z-index: 100;
        opacity: 0;
        visibility: hidden;
        background: var(--color-bg-glass);
        -webkit-backdrop-filter: var(--glass-blur-strong);
        backdrop-filter: var(--glass-blur-strong);
        transform: translateX(calc(-1 * var(--slide-offset, 0px)));
        transition: opacity var(--transition-fast),
                    visibility var(--transition-fast),
                    transform var(--transition-medium);
        font-size: 0.7em;
    }

    .linenumber {
        white-space: normal;
        text-overflow: clip;
        padding-left: 0.3em;
    }

    /* Stack local num and Athlone num on separate lines */
    .linenum-col .ms-linenum,
    .linenum-col .index-linenum { display: block; white-space: nowrap; }
    .linenum-col .linenumber .index-linenum::before { content: "["; }
    .linenum-col .linenumber .index-linenum::after  { content: "]"; }

    body:has(#linenum-toggle:checked) .linenum-col {
        opacity: 1;
        visibility: visible;
    }

    /* Compare indicator buttons. */
    article.passage-container.comparison-mode {
        --compare-ind-w: 16px;
    }

    .comparison-mode .compare-ind-panel {
        display: grid;
        grid-column: compare-ind;
        grid-template-rows: subgrid;
        align-items: start;
        z-index: 2;
    }

    .compare-ind-btn {
        display: flex;
        align-items: center;
        justify-content: start;
        width: 16px;
        padding: 0;
        border: none;
        background: none;
        cursor: pointer;
        user-select: none;
        font-size: 0;
        color: var(--color-text-secondary);
        opacity: 0.45;
        transition: opacity var(--transition-fast);
    }

    .compare-ind-btn::before {
        content: '';
        display: block;
        width: 11px;
        height: 11px;
        margin-top: 5px;
        background-image:
            linear-gradient(currentColor, currentColor),
            linear-gradient(currentColor, currentColor),
            linear-gradient(currentColor, currentColor);
        background-size: 100% 2px;
        background-position: 0 0, 0 4.5px, 0 9px;
        background-repeat: no-repeat;
    }

    .compare-ind-btn:hover,
    .compare-ind-btn:active { opacity: 1; }
    .compare-ind-btn.compare-active { opacity: 1; }

    .compare-ind-btn.compare-active::before {
        background-size: 100% 3px, 100% 3px, 100% 3px;
        background-position: 0 0, 0 4px, 0 8px;
        outline: 1.5px solid currentColor;
        border-radius: 1.5px;
    }

    /* Witness sigil button styling lives in the shared §26d block
       (applies to both Stage C and Stage D). */

    /* Disable compare links on line numbers */
    .comparison-mode .linenumber.hidden { display: none; }
    .comparison-mode a.compare-link {
        pointer-events: none;
        cursor: default;
        color: inherit;
        text-decoration: none;
    }

    /* ── Return-to-main floating button ────────────────────────────────────────
       Shown by JS (.marg-no-left-ind / .marg-no-right-ind on body) when a slide
       panel is open but no indicators are visible in the viewport.  Floats in
       the empty margin column; tapping unchecks the toggle to revert.

       Positioned in the margin column (--marg-panel-w wide) which is fully
       visible when the grid is slid.  Left margin is on the left edge of the
       viewport; right margin on the right edge.                               */
    .marg-return-btn {
        position: fixed;
        z-index: 200;
        top: 50%;
        width: var(--marg-panel-w, 160px);
        display: flex;
        align-items: center;
        justify-content: center;
        padding: 12px 0;
        cursor: pointer;
        user-select: none;
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.25s ease,
                    transform 0.35s ease-out;
    }

    /* Slide in from each respective edge */
    .marg-return-left  { left: 0;  transform: translateX(-100%) translateY(-50%); }
    .marg-return-right { right: 0; transform: translateX(100%)  translateY(-50%); }

    .marg-return-btn::before {
        content: '';
        display: block;
        width: 32px;
        height: 80px;
        background: var(--color-text-secondary);
        clip-path: polygon(0% 0%, 100% 50%, 0% 100%);
        opacity: 0.5;
    }

    /* Left margin is open → arrow points → toward main text (right, no rotate) */
    /* Right margin is open → arrow points ← toward main text (left, rotate 180) */
    .marg-return-right::before { transform: rotate(180deg); }

    body:has(#marg-left-toggle:checked).marg-no-left-ind   .marg-return-left,
    body:has(#marg-right-toggle:checked).marg-no-right-ind .marg-return-right {
        opacity: 1;
        pointer-events: auto;
        transform: translateX(0) translateY(-50%);
    }
}


/* ── §30  Mobile text-page overrides (< --bp-desktop) ─────────────────────── */
/* Chromeless native strip: 40px toolbar fixed at the bottom, native <select>
   elements styled as borderless tappable text.  Hides by sliding off the
   bottom on scroll-down, reveals on scroll-up (mobile Safari pattern). */
/* ── §30  Compact toolbar (< 900px) ──────────────────────────────────────────
   LAYOUT: 40px-high strip with native <select> elements replacing desktop
   comboboxes and radio groups.  Items use the base max-width / margin-inline
   centering from §28.  At < 650px (phone) the strip is fixed at the bottom
   with hide-on-scroll; at 650–899 (tablet) §30b overrides to sticky-top.
   Phone-only width constraints and edge-to-edge distribution are in
   §30a-phone below.
   HAMBURGER: At < 900px the hamburger label is position:fixed top-right.
   §30b adds padding-right to clear it when the toolbar sticks to the top.
   Phone widths don't need this because the toolbar is at the bottom. */
@media screen and (max-width: 899px) /* < --bp-desktop */ {

    /* ── 30a. Container — bottom strip ───────────────────────── */
    :root { --toolbar-ribbon-h: 40px; }

    .toolbar-ribbon {
        position: fixed;
        top: auto;
        bottom: 0;
        left: 0;
        right: 0;
            z-index: 20;   /* toolbar tier — same as desktop, above footer (100) */
        background: var(--color-bg-subtle);
        border-top: 1px solid var(--color-border);
        height: var(--toolbar-ribbon-h);
        padding: 0 0.25em;
        display: flex;
        align-items: center;
        transform: translateY(0);
        transition: transform var(--transition-toolbar);
    }
    .toolbar-ribbon.toolbar--hidden { transform: translateY(100%); }

    .toolbar-items {
        flex-wrap: nowrap;
        gap: 0;
        overflow: visible;
        height: 100%;
        width: 100%;
        justify-content: space-between;
    }

    /* Toolbar is fixed at bottom — undo desktop top padding, add bottom padding */
    body:has(.toolbar-ribbon) main { padding-top: 0; padding-bottom: 40px; }

    /* ── 30b. Hide desktop elements, show mobile alternatives ── */
    .passage-combobox,
    .folio-combobox                    { display: none !important; }
    #passage-select,
    #folio-select                      { display: block !important; }
    .toolbar-ribbon .label-above-component { display: none; }
    .toolbar-ribbon .radio-button-group    { display: none; }
    .view-select-mobile                { display: block; }
    .toolbar-links a[target="_blank"]  { display: none; }
    /* nav.contents / #contents-button only exist on intro pages; no hide
       rule needed here (and hiding them broke the TOC drawer on mobile). */

    /* ── 30c. Chromeless native selects ──────────────────────── */
    #passage-select,
    #folio-select,
    .view-select-mobile {
        appearance: none;
        -webkit-appearance: none;
        border: none;
        background: transparent;
        font: inherit;
        font-size: 0.8rem;
        font-weight: 500;
        color: var(--color-text);
        padding: 0.2em 1em 0.2em 0.3em;
        cursor: pointer;
        /* Inline SVG ▾ indicator */
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='5'%3E%3Cpath d='M0 0l4 5 4-5z' fill='%23666'/%3E%3C/svg%3E");
        background-repeat: no-repeat;
        background-position: right 0.2em center;
        background-size: 6px 4px;
        min-height: 36px;
        line-height: 36px;
    }
    #folio-select:disabled {
        opacity: 0.4;
        cursor: default;
    }
    #passage-select:focus-visible,
    #folio-select:focus-visible,
    .view-select-mobile:focus-visible {
        outline: 2px solid var(--color-accent);
        outline-offset: 1px;
        border-radius: 3px;
    }
    /* ── 30d. Prev/next passus arrows ────────────────────────── */
    #prev-passage, #next-passage {
        display: inline-flex;
        align-items: center;
        padding: 0.1em;
    }
    /* Keep space when an arrow is at the first/last passus so the
       select doesn't shift.  visibility:hidden preserves the box. */
    #passage-component [aria-disabled="true"] { visibility: hidden; }
    .icon-passage-nav { width: 10px; height: 10px; }

    /* ── 30e. Toggle labels (# and </>) — compact inline ─────── */
    .toolbar-linenum {
        margin-left: 0.25em;   /* breathe from left edge */
    }
    .toolbar-ribbon .linenum-toggle-label {
        font-size: 0.75rem;
        width: 1.8em;
        height: 1.8em;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        border: 1px solid var(--color-border);
        border-radius: 3px;
        cursor: pointer;
    }
    .toolbar-links {
        display: flex;
        gap: 0.4em;
        align-items: center;
    }
    .toolbar-ribbon .tags-toggle-label {
        font-size: 0.75rem;
        width: 2.2em;
        height: 1.8em;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        border: 1px solid var(--color-border);
        border-radius: 3px;
        cursor: pointer;
    }

    /* ── 30f. Dot separators — disabled; space-between layout
         provides sufficient visual separation ──────────────── */
}

/* ── §30a-phone  Phone-only toolbar tweaks (< 650px) ────────────────────────
   At phone widths the toolbar is a tight bottom strip; override the base
   centering/gap so space-between distributes items edge-to-edge.  The
   650–899 band keeps the base max-width / margin-inline centering. */
@media (max-width: 649px) {
    .toolbar-items {
        max-width: none;
        margin-inline: 0;
    }
    .toolbar-links {
        margin-left: 0;   /* reset desktop 3em push */
    }
    #passage-select     { max-width: 5em; }
    #folio-select      { max-width: 4.5em; }
    .view-select-mobile { max-width: 4.5em; }
}


/* ── §30b  Sticky top toolbar at 650–899 (Stage B) ─────────────────────────
   LAYOUT: Same compact controls as §30 (native selects, no comboboxes/radio
   groups), but positioned sticky-top instead of fixed-bottom.  Items use
   the base max-width / margin-inline centering (NOT the phone edge-to-edge
   override from §30a-phone).  padding-right on the ribbon clears the
   fixed hamburger label so the rightmost item doesn't overlap it.
   POSITIONING: The header scrolls away normally; the toolbar initially sits
   below it and becomes pinned at top:0 once the user scrolls past.  The
   existing mobile pinned hamburger label (#top-nav > label, position:fixed
   top-right at < --bp-desktop) stays reachable the whole time.
   Rationale: 78px of permanent chrome (header + toolbar) is too much for
   this viewport; scroll-away header + sticky toolbar gives 40px persistent
   chrome after the first scroll, a smooth gradient into desktop mode. */
@media (min-width: 650px) and (max-width: 899px) /* --bp-tablet to --bp-desktop */ {

    .toolbar-ribbon {
        /* Override §30's fixed-bottom positioning.  sticky works because
           .toolbar-wrap { display: contents }, so .toolbar-ribbon is a
           direct flow child of <body>, and nothing in its ancestor chain
           is an overflow container (main.css explicitly avoids overflow
           on <main> for this reason). */
        position: sticky;
        top: 0;
        bottom: auto;
        /* Cancel §30's hide-on-scroll transform/transition.  JS stops
           toggling .toolbar--hidden at this width (see piers.js), but
           belt-and-braces in case it races. */
        transform: none;
        transition: none;
    }
    .toolbar-ribbon.toolbar--hidden { transform: none; }

    /* Simulate the fixed hamburger as the last toolbar item.
       padding-right (8em) reserves the hamburger's column plus a
       visual gap; edge-to-edge distribution on .toolbar-items
       (max-width:none, margin-inline:0) lets space-between spread
       items across the content area so the gap before the hamburger
       approximates the inter-item gaps. */
    .toolbar-ribbon { padding-right: 8em; }
    .toolbar-items {
        max-width: none;
        margin-inline: 0;
    }
    .toolbar-links { margin-left: 0; }
    #passage-select { max-width: 5em; }
    #folio-select  { max-width: 5em; }

    /* The sticky toolbar occupies its natural flow slot below the header,
       so no body padding is needed.  Override §30's bottom padding
       (which cleared the bottom strip that no longer exists here). */
    body:has(.toolbar-ribbon) main {
        padding-top: 0;
        padding-bottom: 0;
    }

    /* Fragment navigation: targets need to clear the sticky toolbar
       (40px in this band, inherited from §30's --toolbar-ribbon-h).
       The header has scrolled away by the time any fragment nav fires. */
    main [id] {
        scroll-margin-top: calc(var(--toolbar-ribbon-h, 40px) + 0.5rem);
    }

    /* Pinned hamburger (#top-nav > label, position:fixed top:0 right:0
       via main.css §15).  Two states matter in this band:
         • Pre-scroll: header (50px) is at the top, toolbar sits below
           it.  The ideal icon position is margin 7px — centered in
           the 50px header.
         • Post-scroll: header has scrolled away, the sticky 40px
           toolbar is at top:0.  The ideal position is margin 2px —
           centered in the 40px toolbar ((40−36)/2 = 2).

       The *long-lived* state is post-scroll (as soon as the user moves
       a single page down they're stuck there).  So we set margin 2px
       as the static default — browsers without scroll-driven animation
       support (Firefox without the flag, older Safari) get the
       toolbar-centered position at all scroll positions.  Pre-scroll
       the icon sits ~5px high of the header's vertical center, which
       is a minor cosmetic imperfection in the less-visited state.

       In browsers that *do* support scroll-driven animations, layer an
       enhancement on top: slide margin-top from 7px back down to 2px
       as the page scrolls through the first 50px (= header height).
       At scrollY=0 the animation holds at keyframe `from` (7px =
       header-centered); at scrollY ≥ 50 it holds at `to` (2px =
       toolbar-centered, matching the static default). */
    #top-nav > label {
        margin-top: 2px;
    }
    @supports (animation-timeline: scroll()) {
        @keyframes hamburger-tablet-settle {
            from { margin-top: 7px; }
            to   { margin-top: 2px; }
        }
        #top-nav > label {
            animation: hamburger-tablet-settle linear both;
            animation-timeline: scroll(root);
            animation-range: 0 var(--header-height, 50px);
        }
    }
}




/* ══════════════════════════════════════════════════════════════════════════════
   PART H — FOLIO UI
   ══════════════════════════════════════════════════════════════════════════════ */

/* §52 — Folio image lightbox removed.
   Image viewing is now handled by edition_images.css / piers_images.js
   (OpenSeadragon panel), loaded conditionally via textnav:image-panel(). */


/* ── §53  Combobox selectors (passus + folio) ────────────────────────────────
   Accessible combobox replacing native <select>.  The original <select>
   remains in the DOM (hidden) as a data source; setup_combobox() in
   piers.js builds the input + toggle + listbox for each. */
.passage-combobox,
.folio-combobox {
    position: relative;
    display: inline-flex;
    align-items: stretch;
    border: 1px solid var(--color-border-strong);
    border-radius: 3px;
    background: var(--color-bg);
    vertical-align: middle;
}

.passage-combobox input,
.folio-combobox input {
    padding: 0.15em 0.3em;
    font-size: inherit;
    border: none;
    background: transparent;
    outline: none;
    min-width: 0;
    color: inherit;
}

.folio-combobox input { width: 3.2em; }
.passage-combobox input { width: 4.5em; }

.passage-combobox:focus-within,
.folio-combobox:focus-within {
    border-color: var(--color-accent);
    box-shadow: 0 0 0 2px var(--color-accent-ring);
}

/* Disabled combobox (e.g. folio selector when no folios exist) */
.passage-combobox.disabled,
.folio-combobox.disabled {
    opacity: 0.4;
    cursor: default;
}
.passage-combobox.disabled:focus-within,
.folio-combobox.disabled:focus-within {
    border-color: var(--color-border-strong);
    box-shadow: none;
}

/* Dropdown toggle button — narrow arrow column on the right. */
.passage-toggle,
.folio-toggle {
    display: flex;
    align-items: center;
    padding: 0 0.3em;
    border: none;
    border-left: 1px solid var(--color-border);
    background: transparent;
    cursor: pointer;
    font-size: 0.7em;
    color: var(--color-text-secondary);
    line-height: 1;
}

.passage-toggle:hover,
.folio-toggle:hover { background: var(--color-bg-subtle); }

/* Dropdown listbox */
#passage-listbox,
#folio-listbox {
    position: absolute;
    top: calc(100% + 2px);
    left: 0;
    z-index: 200;
    min-width: 100%;
    width: max-content;
    max-width: 12em;
    max-height: 14em;
    overflow-y: auto;
    background: var(--color-bg);
    border: 1px solid var(--color-border-strong);
    border-radius: 3px;
    list-style: none;
    margin: 0;
    padding: 0;
    box-shadow: 0 3px 8px light-dark(rgba(0, 0, 0, 0.18), rgba(0, 0, 0, 0.4));
}

#passage-listbox li,
#folio-listbox li {
    padding: 0.25em 0.6em;
    cursor: pointer;
}

/* Current item: solid accent highlight */
#passage-listbox li.current,
#folio-listbox li.current {
    background: var(--color-accent);
    color: var(--color-text-on-dark);
}

/* Keyboard-active or hover: lighter tint */
#passage-listbox li:hover,
#passage-listbox li.active,
#folio-listbox li:hover,
#folio-listbox li.active {
    background: var(--color-accent-light);
    color: inherit;
}

/* Active on a current item: slightly darker */
#passage-listbox li.current.active,
#folio-listbox li.current.active {
    background: var(--color-accent-strong);
    color: var(--color-text-on-dark);
}

/* Non-interactive group label in combobox dropdown —
   override generic li styles to make fully inert. */
#passage-listbox .combobox-group-label,
#folio-listbox .combobox-group-label {
    padding: 0.35em 0.6em 0.2em;
    font-size: 0.8em;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-text-muted, #888);
    cursor: default;
    background: transparent;
    border-top: 1px solid var(--color-border, #ccc);
    margin-top: 0.15em;
    user-select: none;
    pointer-events: none;
}

/* Visual separator between grouped and ungrouped items */
.combobox-separator {
    height: 0;
    border-top: 1px solid var(--color-border, #ccc);
    margin: 0.25em 0.4em;
    pointer-events: none;
}

/* Cross-text options: subtle visual distinction */
#passage-listbox li.cross-text {
    font-style: italic;
}


/* ── §54  Print — text-page-specific ──────────────────────────────────────── */
@media print {
    #ppea-lightbox       { display: none !important; }
    .toolbar-ribbon      { display: none; }
    .bottom-passage-nav   { display: none; }
    .passage-combobox,
    .folio-combobox      { display: none; }
}
