/* ── Search bar ──────────────────────────────────────────────────── */
.search-bar-wrap {
    border-top: 1px solid var(--rule);
    border-bottom: 1px solid var(--rule);
    padding: 1.25rem 0 1.1rem;
    margin-bottom: 0;
}

.search-input-group {
    max-width: 100%;
}

/* ── Filter bar ──────────────────────────────────────────────────── */
.filter-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 1rem 2rem;
    padding: 0.85rem 0;
    border-bottom: 3px double var(--rule-dark);
    margin-bottom: 2rem;
    /* No z-index here on purpose: it would create a stacking context that caps the dropdown panels
       (z-index 200) below the sticky masthead (z-index 100). The panels carry their own z-index and
       render correctly in the root context — above both the masthead and the results below. */
}

.filter-group {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
}

.filter-label {
    font-family: var(--font-body);
    font-size: 0.74rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ink-soft);
    line-height: 1.2;
}

/* Readable labels for form fields (login etc.) — body font, normal case. */
.auth-label {
    display: block;
    font-family: var(--font-body);
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--ink);
    margin-bottom: 0.2rem;
}

.filter-select {
    font-size: 0.8rem;
    /* Extra right padding leaves room for the .form-select caret. */
    padding: 0.25rem 1.7rem 0.25rem 0.6rem;
    height: auto;
    border-color: var(--rule-dark);
    background-color: var(--paper);
    color: var(--ink);
    min-width: 8rem;
    border-radius: 0;
    background-position: right 0.5rem center;
}

.filter-select:focus {
    box-shadow: none;
    border-color: var(--ink);
}

/* Date-range picker (von/bis) — matches the print aesthetic of .filter-select. */
.filter-date {
    font-size: 0.8rem;
    padding: 0.22rem 0.5rem;
    height: auto;
    border-color: var(--rule-dark);
    background-color: var(--paper);
    color: var(--ink);
    border-radius: 0;
}

.filter-date:focus {
    box-shadow: none;
    border-color: var(--ink);
}

.filter-count {
    opacity: 0.55;
    font-size: 0.65rem;
    margin-left: 0.2rem;
}

.filter-count:empty,
.filter-count[data-zero="true"] {
    display: none;
}

/* ── Newspaper multi-select dropdown ─────────────────────────────── */
/* <details>/<summary> based dropdown — hide the native disclosure marker */
.filter-dropdown {
    position: relative;
}

.filter-dropdown-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    min-width: 9rem;
    font-size: 0.8rem;
    padding: 0.25rem 0.6rem;
    border: 1px solid var(--rule-dark);
    border-radius: 0;
    background: var(--paper);
    color: var(--ink);
    cursor: pointer;
    font-family: var(--font-body);
    text-align: left;
    list-style: none;
}

.filter-dropdown-toggle::-webkit-details-marker { display: none; }
.filter-dropdown-toggle::marker { content: ''; }

.filter-dropdown[open] .filter-dropdown-arrow {
    transform: rotate(180deg);
}

.filter-dropdown-toggle:hover {
    border-color: var(--ink);
}

.filter-dropdown-arrow {
    opacity: 0.5;
    font-size: 0.7rem;
}

.filter-dropdown-panel {
    position: absolute;
    top: calc(100% + 2px);
    left: 0;
    min-width: 14rem;
    background: var(--paper);
    border: 1px solid var(--rule-dark);
    box-shadow: 0 4px 16px rgba(0,0,0,0.12);
    z-index: 200;
    padding: 0.35rem 0;
}

.filter-dropdown-item {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.4rem 0.75rem;
    font-size: 0.82rem;
    cursor: pointer;
    color: var(--ink);
    user-select: none;
}

.filter-dropdown-item:hover {
    background: rgba(200, 184, 154, 0.25);
}

a.filter-dropdown-item {
    text-decoration: none;
}

.filter-dropdown-item.active {
    background: rgba(200, 184, 154, 0.35);
    font-weight: 600;
}

.filter-dropdown-item input[type="checkbox"] {
    accent-color: var(--accent);
    width: 0.85rem;
    height: 0.85rem;
    flex-shrink: 0;
    cursor: pointer;
}

.filter-dropdown-name {
    flex: 1;
}

.filter-dropdown-apply {
    display: block;
    width: calc(100% - 1.5rem);
    margin: 0.45rem 0.75rem 0.2rem;
    padding: 0.35rem 0.75rem;
    border: 1px solid var(--ink);
    background: var(--ink);
    color: var(--paper);
    font-size: 0.75rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    text-align: center;
    cursor: pointer;
    border-radius: 0;
    font-family: var(--font-body);
}

.filter-dropdown-apply:hover { background: var(--accent); border-color: var(--accent); }

.filter-dropdown-clear {
    display: block;
    width: 100%;
    margin-top: 0.3rem;
    padding: 0.35rem 0.75rem;
    border: none;
    border-top: 1px solid var(--rule);
    background: transparent;
    font-size: 0.75rem;
    color: var(--ink-soft);
    text-align: left;
    cursor: pointer;
    font-family: var(--font-body);
    text-decoration: none;
}

.filter-dropdown-clear:hover {
    background: rgba(200, 184, 154, 0.2);
    color: var(--accent);
    text-decoration: none;
}

/* ── Search tips (collapsed by default to keep the search bar quiet) ─ */
.search-tips {
    margin: 0.45rem 0 0;
}

.search-tips-summary {
    display: inline-block;
    cursor: pointer;
    font-size: 0.76rem;
    font-style: italic;
    color: var(--ink-soft);
    user-select: none;
    list-style: none;
}

.search-tips-summary::-webkit-details-marker { display: none; }

.search-tips-summary::before {
    content: "▸ ";
    font-style: normal;
}

.search-tips[open] .search-tips-summary::before {
    content: "▾ ";
}

.search-tips-summary:hover {
    color: var(--accent);
}

.search-hint {
    margin: 0.35rem 0 0;
    max-width: 100%;
    font-size: 0.76rem;
    font-style: italic;
    color: var(--ink-soft);
    line-height: 1.5;
}

/* ── Section heading with a control on the right ─────────────────── */
/* Used by the landing "latest editions" heading, which carries the page-size select. The underline
   moves from the heading to the row so it runs the full width, under the select as well; a bare
   .section-heading elsewhere keeps its own border. */
.section-heading-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    margin: 0 0 1.25rem;
    padding-bottom: 0.4rem;
    border-bottom: 2px solid var(--rule-dark);
}

.section-heading-row .section-heading {
    margin: 0;
    padding-bottom: 0;
    border-bottom: none;
}

.latest-size-form {
    flex: 0 0 auto;
}

/* The steps are two digits, so the filter width meant for newspaper names is far too wide here. */
.latest-size-form .filter-select {
    min-width: 0;
}

/* ── Section heading ─────────────────────────────────────────────── */
.section-heading {
    font-family: var(--font-head);
    font-size: 1.4rem;
    font-weight: 700;
    color: var(--ink);
    margin: 0 0 1.25rem;
    padding-bottom: 0.4rem;
    border-bottom: 2px solid var(--rule-dark);
}

/* ── Newspaper tiles (landing) ───────────────────────────────────── */
/* Fixed column counts, every one of them a divisor of 12 (4 desktop, 6 on 4K, 3 / 2 on phones via
   the mobile overrides below), so every full page of tiles ends on a complete row. auto-fill sizing
   produced 5 or 7 columns depending on the viewport, leaving the last row ragged.
   These counts are why the selectable page sizes are multiples of 12 (LatestPageSizes, F-13):
   changing a column count here to something outside {2,3,4,6} breaks that guarantee. */
/* minmax(0, 1fr) instead of bare 1fr: a bare 1fr track still has min-content as its floor, so a
   single tile with a wide-format thumbnail or a long unbreakable title word inflates its whole
   column on narrow phones, squeezing the others. */
.newspaper-tiles {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 1rem;
}
/* The reading column widens on 4K (--content-max 1500px+): six 250px tiles fit comfortably. */
@media (min-width: 2560px) {
    .newspaper-tiles { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}

.newspaper-tile {
    position: relative; /* anchors the F-16 "new" badge */
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    padding: 1rem 1rem 0.9rem;
    background: var(--card-bg);
    border: 1px solid var(--rule);
    border-top: 3px solid var(--rule-dark);
    color: var(--ink);
    text-decoration: none;
    transition: border-top-color 0.15s, box-shadow 0.15s, transform 0.1s;
}

.tile-thumb {
    display: block;
    width: 100%;
    height: 180px;
    object-fit: cover;
    object-position: top center;
    background: #fff;
    border: 1px solid var(--rule);
    margin-bottom: 0.35rem;
}

.newspaper-tile:hover {
    border-top-color: var(--accent);
    box-shadow: 0 4px 16px rgba(0,0,0,0.12);
    transform: translateY(-2px);
    text-decoration: none;
    color: var(--ink);
}

/* F-16: "new since last login" badge, pinned to the tile's top rule like a kicker label. */
.tile-badge-new {
    position: absolute;
    top: -3px;
    right: 0.6rem;
    padding: 0.15rem 0.5rem 0.1rem;
    background: var(--accent);
    color: #fff;
    font-family: var(--font-head);
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.tile-name {
    font-family: var(--font-head);
    font-weight: 700;
    font-size: 1rem;
    line-height: 1.2;
    color: var(--accent);
}

.tile-date {
    font-size: 0.82rem;
    font-style: italic;
    color: var(--ink);
}

.tile-meta {
    margin-top: 0.15rem;
    font-size: 0.68rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink-soft);
}

.empty-hint {
    font-style: italic;
    color: var(--ink-soft);
}

/* ── Results meta line ───────────────────────────────────────────── */
.results-meta {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    font-size: 0.75rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--ink-soft);
    margin-bottom: 1.5rem;
}

.results-filter-tag {
    background: var(--rule);
    color: var(--ink);
    padding: 0.1rem 0.45rem;
    font-style: italic;
    letter-spacing: 0;
    text-transform: none;
}

/* ── Edition result cards (grouped per edition: thumbnail + per-page hits) ─── */
.edition-card {
    display: flex;
    gap: 1.25rem;
    padding: 1.1rem 0;
    border-top: 1px solid var(--rule);
}

.edition-card:last-child { border-bottom: 1px solid var(--rule); }

.edition-thumb { flex: 0 0 120px; display: block; align-self: flex-start; }

.edition-thumb img {
    width: 120px;
    height: 168px;
    object-fit: cover;
    object-position: top center;
    background: #fff;
    border: 1px solid var(--rule-dark);
}

.edition-body { flex: 1 1 auto; min-width: 0; }

.edition-header {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-bottom: 0.5rem;
}

.edition-hitcount {
    margin-left: auto;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--ink-soft);
}

.edition-hits { list-style: none; margin: 0; padding: 0; }
.edition-hit { border-top: 1px dotted var(--rule); }
.edition-hit:first-child { border-top: none; }

.edition-hit a {
    display: flex;
    gap: 0.6rem;
    padding: 0.4rem 0.5rem;
    color: var(--ink);
    text-decoration: none;
    border-left: 3px solid transparent;
    transition: border-left-color 0.12s, background 0.12s;
}

.edition-hit a:hover {
    border-left-color: var(--accent);
    background: rgba(200, 184, 154, 0.13);
    text-decoration: none;
}

.hit-page {
    flex: 0 0 4.5rem;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--accent);
    white-space: nowrap;
    padding-top: 0.15rem;
}

.hit-fragments { flex: 1 1 auto; min-width: 0; font-size: 0.9rem; line-height: 1.55; }
.hit-fragment { display: block; }
.hit-fragment + .hit-fragment { margin-top: 0.15rem; color: var(--ink-soft); }

/* ── Result meta (shared by the edition cards' header row) ────────── */
.result-newspaper {
    font-family: var(--font-head);
    font-weight: 700;
    font-size: 0.82rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--accent);
    white-space: nowrap;
}

.result-dot {
    color: var(--rule-dark);
    font-size: 0.75rem;
}

.result-date {
    font-size: 0.78rem;
    font-style: italic;
    color: var(--ink-soft);
}

/* ── Highlighted terms ───────────────────────────────────────────── */
mark {
    background-color: #f5d87a;
    color: var(--ink);
    padding: 0 0.12em;
    font-weight: 600;
    border-radius: 0;
}

/* ── Neutral notice (e.g. "page not found" in the viewer) ────────── */
.notice {
    border-left: 3px solid var(--rule-dark);
    background: var(--rule);
    color: var(--ink);
    padding: 0.75rem 1rem;
    font-size: 0.88rem;
    margin-bottom: 1rem;
}

/* ── Error ───────────────────────────────────────────────────────── */
.result-error {
    border-left: 3px solid var(--accent);
    background: #fdf0f0;
    color: var(--ink);
    padding: 0.75rem 1rem;
    font-size: 0.88rem;
    margin-bottom: 1rem;
}

/* ── Inline SVG icons ────────────────────────────────────────────── */
/* Icons inherit the control's colour (currentColor) and size (1em). The small negative
   vertical-align centres them against adjacent label text. */
.icon { vertical-align: -0.125em; }
/* Icon + label buttons get a small gap; icon-only buttons are unaffected. */
.btn .icon, .reader-download .icon { margin-right: 0.4em; }

/* ── Pagination ──────────────────────────────────────────────────── */
.newspaper-pagination {
    display: flex;
    justify-content: center;
    gap: 0.25rem;
    margin-top: 2rem;
    border-top: 1px solid var(--rule);
    padding-top: 1.25rem;
}

.newspaper-pagination .page-link {
    display: inline-block;
    font-family: var(--font-body);
    font-size: 0.8rem;
    color: var(--ink-soft);
    border: 1px solid var(--rule);
    border-radius: 0;
    padding: 0.3rem 0.65rem;
    background: transparent;
    cursor: pointer;
    text-decoration: none;
    transition: background 0.1s;
}

.newspaper-pagination .page-link:hover {
    background: var(--rule);
    color: var(--ink);
    text-decoration: none;
}

.newspaper-pagination .page-item.active .page-link {
    background: var(--ink);
    border-color: var(--ink);
    color: var(--paper);
}

/* ── Reader chrome (back link, edition, page nav, zoom, in-document search, download) ───
   One bar carries every reader control. In the immersive layout (below) it floats over the dark
   stage as the page's title bar; without JS it degrades to a plain bar above the document. */
.reader-chrome {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 1rem;
    padding: 0.5rem 0 0.75rem;
    border-bottom: 1px solid var(--rule);
    margin-bottom: 1rem;
    font-size: 0.8rem;
}

.reader-group { display: flex; align-items: center; gap: 0.3rem; }

.reader-ident { gap: 0.75rem; min-width: 0; color: var(--ink-soft); }
.reader-back { display: inline-flex; align-items: center; }
/* min-width:0 so the edition line truncates when the bar runs out of room, instead of holding its
   content width and pushing the download action onto a second row. */
.reader-ident .viewer-meta { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.reader-btn {
    border: 1px solid var(--rule-dark);
    background: var(--paper);
    color: var(--ink);
    border-radius: 0;
    padding: 0.15rem 0.55rem;
    line-height: 1.4;
    cursor: pointer;
    font-family: var(--font-body);
}

.reader-btn:hover:not(:disabled) { background: var(--rule); }
.reader-btn:disabled { opacity: 0.4; cursor: default; }
/* Pressed state of the spread toggle (single/double page). */
.reader-btn.is-active { background: var(--rule); }

.reader-pageinfo { display: flex; align-items: center; gap: 0.25rem; color: var(--ink-soft); }

#pdf-page-input {
    width: 3.2rem;
    text-align: center;
    padding: 0.1rem 0.2rem;
    border: 1px solid var(--rule-dark);
    border-radius: 0;
    font-family: var(--font-body);
}

/* Zoom percentage doubles as the reset-to-fit button (Ctrl + wheel / +,-,0 do the same). */
.reader-zoom-label {
    min-width: 3.4rem;
    text-align: center;
    color: var(--ink-soft);
    background: transparent;
    border: 0;
    padding: 0.15rem 0.2rem;
    cursor: pointer;
    font-family: var(--font-body);
    font-size: inherit;
    font-variant-numeric: tabular-nums;
}
.reader-zoom-label:hover { color: var(--ink); }

/* min-width:0 so the group may shrink below its content width — otherwise it pushes the download
   action out of the single-row chrome bar in the immersive layout. */
.reader-find { flex: 1 1 14rem; min-width: 0; }
.reader-find-input { flex: 1 1 auto; min-width: 6rem; font-size: 0.8rem; padding: 0.15rem 0.5rem; }
.reader-find-status {
    min-width: 2.5rem;
    text-align: center;
    color: var(--ink-soft);
    font-variant-numeric: tabular-nums;
}

.reader-download { margin-left: auto; font-size: 0.78rem; white-space: nowrap; }

/* ── Immersive reader ───────────────────────────────────────────────────
   The reading surface fills the window on every device: site header gone, page centered on a dark
   stage, controls in the chrome bar floating on top of it. pdfViewer.js enters it on init — it is
   pure fixed positioning, so it needs no user gesture (unlike the Fullscreen API, which the
   fullscreen button adds on click) and works where element fullscreen doesn't (iOS Safari).

   The shell is a flex column: bar first, stage taking the rest. No fixed bar height to keep in sync
   — the bar may wrap to a second row on a narrow phone and the stage simply gets what is left. */
body.is-pdf-immersive { overflow: hidden; }
body.is-pdf-immersive .site-top { display: none; }
body.is-pdf-immersive .newspaper-main { max-width: none; margin: 0; padding: 0; }

body.is-pdf-immersive .reader-shell {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    flex-direction: column;
    background: #111;
}

body.is-pdf-immersive .reader-chrome {
    flex: none;
    gap: 0.5rem 0.75rem;
    margin: 0;
    padding: 0.4rem 0.75rem;
    padding-top: calc(env(safe-area-inset-top, 0px) + 0.4rem);
    border-bottom: 1px solid rgba(255, 255, 255, 0.12);
    background: rgba(17, 17, 17, 0.92);
    backdrop-filter: blur(6px);
}

/* The bar sits on the dark stage, so its controls flip to a dark palette. */
body.is-pdf-immersive .reader-chrome .reader-btn,
body.is-pdf-immersive .reader-chrome .btn,
body.is-pdf-immersive .reader-chrome #pdf-page-input,
body.is-pdf-immersive .reader-chrome .reader-find-input {
    background: rgba(255, 255, 255, 0.06);
    border-color: rgba(255, 255, 255, 0.22);
    color: #f0ece4;
}
body.is-pdf-immersive .reader-chrome .reader-btn.is-active {
    background: rgba(255, 255, 255, 0.22);
    color: #fff;
}
body.is-pdf-immersive .reader-chrome .reader-btn:hover:not(:disabled),
body.is-pdf-immersive .reader-chrome .btn:hover,
body.is-pdf-immersive .reader-chrome .reader-zoom-label:hover,
body.is-pdf-immersive .reader-chrome .reader-download:hover {
    background: rgba(255, 255, 255, 0.16);
    color: #fff;
}
body.is-pdf-immersive .reader-chrome,
body.is-pdf-immersive .reader-chrome .reader-ident,
body.is-pdf-immersive .reader-chrome .reader-pageinfo,
body.is-pdf-immersive .reader-chrome .reader-zoom-label,
body.is-pdf-immersive .reader-chrome .reader-find-status,
body.is-pdf-immersive .reader-chrome .reader-download { color: #d8d4cc; }
body.is-pdf-immersive .reader-chrome .viewer-meta strong { color: #e0b96a; }

/* The search field takes the slack in the single row, but not all of it — the download action stays
   at the right end and the bar keeps its balance on wide screens. */
body.is-pdf-immersive .reader-chrome .reader-find { flex: 1 1 12rem; max-width: 26rem; }
body.is-pdf-immersive .reader-chrome .reader-download { flex: none; }

/* The stage takes whatever the bar leaves, so the bar never covers the page. The page-sized
   container is centered inside it (flex + margin:auto — the auto margins collapse to 0 once the page
   is zoomed larger than the stage, so scrolling still reaches every corner). */
body.is-pdf-immersive .pdf-stage {
    flex: 1 1 auto;
    min-height: 0;
    max-width: none;
    overflow: auto;
    background: #111;
    display: flex;
    /* The whole reading surface — page and the dark margin beside it — belongs to the viewer's own
       pinch (pdfViewer.js), which re-renders sharp. Without this the browser zooms the document
       itself the moment the fingers miss the page, and the two zooms fight each other. */
    touch-action: pan-x pan-y;
}
body.is-pdf-immersive .pdf-viewer-container {
    margin: auto;
    flex: none;
    border: none;
    box-shadow: none;
}

/* ── PDF viewer ──────────────────────────────────────────────────── */
/* Loading state: spinner + download progress, shown until the first page has rendered. It lives in
   the stage, so `margin: auto` centres it on the reading surface (the stage is a flex container in
   the immersive layout) and it stays visible on the dark background. */
.pdf-loading {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.75rem;
    margin: auto;
    padding: 3rem 0;
    text-align: center;
}
/* While loading, the page container is an empty box that would compete with the spinner for the
   stage's auto margins and knock it off centre — hide it until there is something to show. */
.pdf-stage.is-loading .pdf-viewer-container { display: none; }
/* The loading block stays in the DOM for the whole session: pdfViewer.js re-shows it whenever a
   page flip has to wait on the network (skipping into an unfetched part of the issue). */
.pdf-loading.is-hidden { display: none; }

.pdf-loading-text { font-size: 0.85rem; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
body.is-pdf-immersive .pdf-loading-text { color: #d8d4cc; }
body.is-pdf-immersive .newspaper-spinner { border-color: rgba(255, 255, 255, 0.2); border-top-color: #f0ece4; }
.newspaper-spinner {
    display: inline-block;
    width: 2rem;
    height: 2rem;
    border: 3px solid var(--rule);
    border-top-color: var(--ink);
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* Stage: a horizontal-overflow container so a zoomed page scrolls inside the content column instead
   of widening the page and breaking the surrounding layout. This governs the normal (in-page) view;
   the immersive layout above turns the same element into the full-window reading surface. */
.pdf-stage { max-width: 100%; overflow-x: auto; }

/* Container size (width/height), the flex gap and --scale-factor are set by pdfViewer.js. It holds
   one .pdf-page slot per shown page (two side by side in spread mode); inside a slot the three
   layers are absolutely positioned at 0,0 with identical dimensions so the canvas, text layer and
   highlights stay pixel-aligned. */
.pdf-viewer-container {
    position: relative;
    display: flex;
    align-items: flex-start;
    margin: 0 auto;
    box-shadow: 0 4px 24px rgba(0,0,0,0.18);
    border: 1px solid var(--rule-dark);
    /* Allow one-finger panning/scrolling but let the viewer own two-finger pinch-zoom (pdfViewer.js),
       so pinch works inside native fullscreen too and re-renders sharp; this also disables the
       browser's double-tap-to-zoom, freeing double-tap for the fullscreen toggle. */
    touch-action: pan-x pan-y;
}

/* One shown page; slot dimensions are set by pdfViewer.js. In spread mode the gap between the two
   slots shows the dark stage — it reads as the paper's fold. */
.pdf-page {
    position: relative;
    flex: none;
}

.pdf-page canvas {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;
}

/* PDF.js text layer — transparent, selectable glyphs over the raster (copy-paste). */
.textLayer {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 2;
    overflow: clip;
    opacity: 1;
    line-height: 1;
    text-align: initial;
    forced-color-adjust: none;
    transform-origin: 0 0;
}

.textLayer span,
.textLayer br {
    position: absolute;
    color: transparent;
    white-space: pre;
    cursor: text;
    transform-origin: 0 0;
}

.textLayer span.markedContent {
    top: 0;
    height: 0;
}

.textLayer ::selection {
    background: rgba(40, 100, 255, 0.30);
}

.pdf-overlay {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 3;
    pointer-events: none;
}

.pdf-highlight {
    position: absolute;
    background-color: rgba(245, 216, 122, 0.40);
    border: 1px solid rgba(200, 150, 0, 0.55);
    mix-blend-mode: multiply;
}

/* ── Viewer nav ──────────────────────────────────────────────────── */
.viewer-nav {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0.75rem 0 1.25rem;
    border-bottom: 1px solid var(--rule);
    margin-bottom: 1.5rem;
    font-size: 0.85rem;
    color: var(--ink-soft);
}

.viewer-meta strong {
    font-family: var(--font-head);
    font-weight: 700;
    color: var(--accent);
}

/* ── Utility bar (auth + language) & login ───────────────────────── */
.utility-bar {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0.75rem;
    width: 100%;
    max-width: var(--content-max);
    margin: 0 auto;
    padding: 0.35rem clamp(1rem, 3vw, 3rem) 0;
    font-size: 0.75rem;
    color: var(--ink-soft);
}

.lang-switch {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    letter-spacing: 0.04em;
}

.lang-link {
    color: var(--ink-soft);
    text-decoration: none;
    padding: 0.05rem 0.3rem;
    border-bottom: 1px solid transparent;
}

.lang-link:hover { color: var(--ink); }

.lang-link.is-active {
    color: var(--ink);
    font-weight: 600;
    border-bottom-color: var(--accent);
}

.auth-card {
    max-width: 380px;
    margin: 1rem auto;
}

.auth-form {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.auth-form .form-control { margin-bottom: 0.4rem; }

.auth-remember {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.85rem;
    color: var(--ink-soft);
    margin: 0.2rem 0 0.6rem;
}

.auth-form .btn-primary { align-self: flex-start; }

.auth-divider {
    text-align: center;
    font-style: italic;
    color: var(--ink-soft);
    margin: 1rem 0;
}

.auth-sso { width: 100%; }

/* ── Responsive / mobile ─────────────────────────────────────────── */
@media (max-width: 640px) {
    .search-bar-wrap { padding: 1rem 0 0.9rem; }
    .search-input-group { max-width: 100%; }

    /* Filters: each control takes a flexible full-width-ish slot and wraps */
    .filter-bar { gap: 0.7rem 1rem; }
    .filter-group { flex: 1 1 9rem; }
    .filter-select,
    .filter-date,
    .filter-dropdown-toggle { min-width: 0; width: 100%; }
    .filter-dropdown-panel { max-width: 90vw; }

    .results-meta { flex-wrap: wrap; }

    .newspaper-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.75rem; }
    .tile-thumb { height: 150px; }

    /* Edition cards: thumbnail on top, hit rows stack */
    .edition-card { flex-direction: column; gap: 0.6rem; }
    .edition-thumb { flex-basis: auto; }
    .edition-thumb img { width: 110px; height: 154px; }
    .edition-hit a { flex-direction: column; gap: 0.1rem; }
    .hit-page { flex-basis: auto; }

    .newspaper-pagination { flex-wrap: wrap; }

    /* Viewer nav wraps instead of overflowing */
    .viewer-nav { flex-wrap: wrap; gap: 0.5rem; }

    /* PDF reader on phones: the bar keeps what a finger cannot do better itself — back, edition,
       page nav, fullscreen, download. Zoom is the pinch gesture, the in-document search would
       eat the whole row, and two broadsheet pages side by side are unreadable on a phone — all
       three groups give way (pdfViewer.js forces the single-page layout below the breakpoint). */
    .reader-zoom, .reader-find, .reader-spread { display: none; }
    .reader-download-text, .reader-back-text { display: none; }
    .reader-download { margin-left: auto; }
    .reader-chrome { font-size: 0.75rem; gap: 0.4rem; }
    .reader-ident { gap: 0.4rem; flex: 0 1 auto; }
    .reader-back .icon { margin-right: 0; }
    #pdf-page-input { width: 2.6rem; }
}

@media (max-width: 400px) {
    .newspaper-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ── Admin backend (F-08) ────────────────────────────────────────── */
.admin-shell { width: 100%; max-width: 1500px; margin: 1.5rem auto; padding: 0 clamp(1rem, 3vw, 3rem); }
.admin-title { font-family: var(--font-head); font-size: 1.8rem; margin: 0.5rem 0 1rem; }
.admin-h2 { font-size: 1.1rem; margin: 0 0 0.6rem; border-bottom: 2px solid var(--ink); padding-bottom: 0.2rem; }
.admin-h3 { font-size: 0.95rem; margin: 1rem 0 0.4rem; }

/* Sub-navigation as connected tabs (shared by Admin + Settings): each tab is a square, print-style
   box; the active one merges with the rule below it so it reads as joined to the content panel. */
.admin-nav {
    display: flex;
    gap: 0.25rem;
    align-items: flex-end;
    border-bottom: 1px solid var(--rule-dark);
    margin-bottom: 1rem;
    overflow-x: auto;
}
.admin-nav-link {
    color: var(--ink-soft);
    text-decoration: none;
    font-family: var(--font-body);
    font-size: 0.8rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    white-space: nowrap;
    padding: 0.45rem 0.9rem;
    border: 1px solid transparent;
    border-bottom: none;
    margin-bottom: -1px; /* overlap the rule so the active tab can connect to the content below */
    transition: background 0.1s, color 0.1s;
}
.admin-nav-link:hover { color: var(--ink); background: var(--rule); }
.admin-nav-link.is-active {
    color: var(--ink);
    font-weight: 600;
    background: var(--paper);
    border-color: var(--rule-dark);        /* top + left + right */
    border-bottom: 1px solid var(--paper); /* hide the rule under the active tab → looks joined */
}

/* Tab bar docked in the sticky header (NF-09): aligns with the content column and stays put while
   the page scrolls (it lives inside .site-top). */
.subnav-bar {
    background: var(--paper);
    max-width: var(--content-max);
    margin: 0 auto;
    padding: 0 clamp(1rem, 3vw, 3rem);
}
.subnav-bar .admin-nav { margin-bottom: 0; }

.admin-section { margin: 1.75rem 0; }

.admin-cards { display: flex; flex-wrap: wrap; gap: 0.75rem; }
.admin-card {
    display: flex; flex-direction: column; gap: 0.2rem;
    min-width: 130px; padding: 0.8rem 1rem;
    border: 1px solid var(--rule); background: #fff;
}
.admin-card-num { font-size: 1.5rem; font-weight: 700; }
.admin-card-label { font-size: 0.75rem; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 0.03em; }
.admin-health-green { color: #1a7f37; }
.admin-health-yellow { color: #9a6700; }
.admin-health-red { color: #b00020; }

/* Wrapper lets wide admin tables scroll horizontally on narrow screens instead of
   overflowing the page (the publisher/newspaper tables carry several columns). */
.admin-table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.admin-table { width: 100%; min-width: 34rem; border-collapse: collapse; font-size: 0.9rem; }
.admin-table th, .admin-table td { text-align: left; padding: 0.45rem 0.6rem; border-bottom: 1px solid var(--rule); vertical-align: top; }
.admin-table th { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--ink-soft); }
.admin-error { color: #b00020; font-size: 0.8rem; max-width: 360px; }

.admin-muted { color: var(--ink-soft); font-size: 0.8rem; }
.admin-warn { color: #b45309; font-size: 0.8rem; font-weight: 600; }

.admin-inline-actions { display: flex; gap: 0.4rem; align-items: center; flex-wrap: wrap; margin-top: 0.4rem; }
.admin-inline-form { display: inline-flex; gap: 0.4rem; align-items: center; flex-wrap: wrap; margin: 0; }

/* Auto-download status is a full-width sub-row under each newspaper: the main row carries no bottom
   border so the two read as one block, and the sub-row lays the facts out horizontally. */
.admin-table tr.admin-mainrow > td { border-bottom: 0; }
.admin-subrow > td { padding-top: 0; }
.admin-download-row { display: flex; align-items: baseline; gap: 0.5rem 1rem; flex-wrap: wrap; }
.admin-download-facts { display: flex; align-items: baseline; gap: 0.2rem 1.25rem; flex-wrap: wrap; font-size: 0.85rem; }
.admin-download-row .admin-inline-actions { margin-top: 0; margin-left: auto; }
.admin-add { margin-top: 0.75rem; }
.admin-input {
    font-family: var(--font-body, inherit); font-size: 0.9rem;
    padding: 0.3rem 0.5rem; border: 1px solid var(--rule-dark); background: #fff;
}
/* Action cells are real table cells — flex on the td itself would decouple its height and
   bottom border from the row (the separators visibly drifted next to tall or empty cells,
   e.g. the local admin's password form and the "you" row without buttons). The forms and
   buttons inside flow inline and wrap on their own. */
.admin-actions > * {
    display: inline-flex;
    gap: 0.4rem;
    align-items: center;
    vertical-align: top;
    margin: 0 0.4rem 0.25rem 0;
}
.admin-actions > *:last-child { margin-right: 0; }

.admin-btn {
    border: 1px solid var(--rule-dark); background: transparent; color: var(--ink-soft);
    font-size: 0.8rem; padding: 0.3rem 0.6rem; cursor: pointer; font-family: var(--font-body, inherit);
    /* inline-flex + gap spaces an icon from its label, and leaves icon-only buttons centred. */
    display: inline-flex; align-items: center; gap: 0.4em;
}
.admin-btn:hover { background: var(--rule); color: var(--ink); }
.admin-btn-primary { border-color: var(--ink); color: var(--ink); font-weight: 600; }
.admin-btn-danger:hover { background: #b00020; color: #fff; border-color: #b00020; }

.admin-flash { padding: 0.5rem 0.75rem; font-size: 0.85rem; margin: 0.75rem 0; border-left: 3px solid; }
.admin-flash-ok { border-color: #1a7f37; background: #f0fbf3; }
.admin-flash-err { border-color: #b00020; background: #fdf0f1; }

.admin-badge { font-size: 0.72rem; padding: 0.1rem 0.4rem; border: 1px solid; }
.admin-badge-on { color: #1a7f37; border-color: #1a7f37; }
.admin-badge-off { color: #b00020; border-color: #b00020; }

/* ── User menu (logged-in dropdown) & masthead admin link ────────── */
.utility-bar .user-menu { margin-right: auto; position: relative; }

.user-menu-toggle {
    cursor: pointer;
    list-style: none;
    color: var(--ink-soft);
}
.user-menu-toggle::-webkit-details-marker { display: none; }
.user-menu-toggle::marker { content: ''; }
.user-menu-toggle::after { content: ' ▾'; opacity: 0.5; }
.user-menu[open] .user-menu-toggle::after { content: ' ▴'; }

.user-menu-panel {
    position: absolute;
    left: 0;
    top: calc(100% + 4px);
    min-width: 170px;
    background: var(--paper);
    border: 1px solid var(--rule-dark);
    box-shadow: 0 4px 16px rgba(0,0,0,0.12);
    z-index: 200;
    display: flex;
    flex-direction: column;
}
.user-menu-panel form { margin: 0; }

.user-menu-item {
    display: block;
    width: 100%;
    text-align: left;
    padding: 0.5rem 0.85rem;
    font-size: 0.8rem;
    font-family: var(--font-body);
    color: var(--ink-soft);
    background: transparent;
    border: none;
    cursor: pointer;
    text-decoration: none;
}
.user-menu-item:hover { background: var(--rule); color: var(--ink); text-decoration: none; }
.user-menu-logout { border-top: 1px solid var(--rule); }

/* ── Admin: section heads, + buttons, edit/delete actions, modal dialogs ───────────── */
.admin-section-head {
    display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
    margin-bottom: 0.6rem;
}
.admin-section-head .admin-h2 { margin: 0; flex: 1; }
.admin-add-btn {
    flex: 0 0 auto; width: 1.9rem; height: 1.9rem; padding: 0; line-height: 1;
    font-size: 1.2rem; border-radius: 50%; display: inline-flex;
    align-items: center; justify-content: center;
}

.admin-dialog {
    border: 1px solid var(--rule-dark); padding: 0; max-width: 30rem; width: calc(100% - 2rem);
    background: #fff; color: var(--ink); box-shadow: 0 8px 30px rgba(0, 0, 0, 0.18);
}
.admin-dialog::backdrop { background: rgba(0, 0, 0, 0.4); }
/* .admin-field's own display would beat the UA [hidden] rule, silently breaking every conditional
   row (login fields, week-of-month). Re-assert it for everything inside a dialog. */
.admin-dialog [hidden] { display: none !important; }
.admin-dialog-form { display: flex; flex-direction: column; gap: 0.9rem; padding: 1.25rem; }
/* Standalone (non-dialog) settings forms: same column layout, capped width, no dialog padding. */
.admin-form-narrow { max-width: 32rem; }
.admin-dialog-title { font-size: 1.05rem; margin: 0; border-bottom: 2px solid var(--ink); padding-bottom: 0.3rem; }
.admin-field { display: flex; flex-direction: column; gap: 0.25rem; }
.admin-field > span { font-size: 0.8rem; color: var(--ink-soft); }
.admin-field .admin-input { width: 100%; box-sizing: border-box; }
.admin-field .admin-muted { font-size: 0.72rem; }
.admin-dialog-actions { display: flex; justify-content: flex-end; gap: 0.5rem; margin-top: 0.25rem; }

/* Wide dialog (newspaper edit): two-column field grid; full-width rows opt in explicitly.
   Collapses back to one column on narrow screens. */
.admin-dialog--wide { max-width: 46rem; }

/* Download-history dialog: wide table (5 columns incl. error text), capped height, pager below. */
.admin-dialog--history { max-width: 60rem; }
.admin-history-scroll { max-height: 55vh; overflow-y: auto; }
.admin-pager { display: flex; align-items: center; justify-content: center; gap: 0.75rem; }
.admin-pager .admin-btn:disabled { opacity: 0.35; cursor: default; }
.admin-field-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.9rem 1.25rem; align-items: start; }
.admin-field-grid .admin-field-full { grid-column: 1 / -1; }
@media (max-width: 640px) {
    .admin-field-grid { grid-template-columns: 1fr; }
}

/* The download-config group: a quiet framed section instead of the browser-default fieldset. */
.admin-fieldset {
    border: 1px solid var(--rule, #d8d2c4); padding: 0.9rem 1rem 1rem; margin: 0;
}
.admin-fieldset > legend {
    font-size: 0.8rem; letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--ink-soft); padding: 0 0.4rem;
}
.admin-input-mono { font-family: var(--font-mono, monospace); font-size: 0.8rem; }
textarea.admin-input { resize: vertical; }
.admin-input[readonly] { background: var(--rule, #eee); color: var(--ink-soft); cursor: not-allowed; }

/* Publisher logo: small thumbnail in the table, larger preview in the edit dialog. */
.admin-logo-cell { width: 3rem; }
.admin-logo-thumb { max-width: 2.5rem; max-height: 2.5rem; object-fit: contain; display: block; }
.admin-logo-preview { max-width: 8rem; max-height: 5rem; object-fit: contain; border: 1px solid var(--rule, #ccc); padding: 0.2rem; background: #fff; }
.admin-checkbox { flex-direction: row; align-items: center; gap: 0.4rem; font-size: 0.8rem; }

/* Publication-day checkboxes (F-10): a wrapping row of weekday toggles. */
.admin-weekday-set { border: none; margin: 0; padding: 0; }
.admin-weekday-set > legend { font-size: 0.8rem; color: var(--ink-soft); padding: 0; }
.admin-weekday-options { display: flex; flex-wrap: wrap; gap: 0.35rem 0.9rem; margin: 0.25rem 0; }
.admin-weekday-option { white-space: nowrap; }

/* ── Main navigation (always visible; wraps to multiple rows on small screens) ──────── */
.main-nav { margin-top: 0.5rem; }
/* On compact pages (and the scrolled search page) the dateline and its double rule collapse, so the
   title↔menu separator would vanish. Restore it as a top rule on the menu itself — the same 3px
   double rule as the search-page dateline. */
.is-scrolled .main-nav {
    margin-top: 0;
    padding-top: 0.4rem;
    border-top: 3px double var(--ink);
}
.main-nav-list {
    list-style: none; margin: 0; padding: 0.45rem 0.5rem;
    display: flex; justify-content: center; flex-wrap: wrap; gap: 0.3rem 1.6rem;
}
.main-nav-link {
    font-family: var(--font-body); font-size: 0.74rem; letter-spacing: 0.18em;
    text-transform: uppercase; color: var(--ink-soft); text-decoration: none;
    padding: 0.15rem 0.1rem; border-bottom: 2px solid transparent; white-space: nowrap;
}
.main-nav-link:hover { color: var(--ink); border-bottom-color: var(--rule); }
.main-nav-link.is-active { color: var(--accent); border-bottom-color: var(--accent); }

@media (max-width: 640px) {
    .main-nav-list { gap: 0.25rem 1.1rem; }
    .main-nav-link { font-size: 0.7rem; letter-spacing: 0.12em; }
}

/* "Why the Morgue?" (overview) — text beside the 1942 NYT-morgue photograph; stacks on narrow screens. */
.about-morgue { display: flex; gap: 1.75rem; align-items: flex-start; }
.about-morgue-text { flex: 1 1 24rem; line-height: 1.7; }
.about-morgue-text p { margin: 0 0 0.9rem; }
.about-morgue-figure { flex: 0 1 18rem; margin: 0; }
.about-morgue-figure img {
    width: 100%; height: auto; display: block;
    border: 1px solid var(--rule-dark, #999); filter: sepia(0.15);
}
.about-morgue-figure figcaption {
    margin-top: 0.4rem; font-size: 0.72rem; font-style: italic;
    color: var(--ink-soft); line-height: 1.45;
}
@media (max-width: 640px) {
    .about-morgue { flex-direction: column; }
    .about-morgue-figure { flex-basis: auto; max-width: 24rem; }
}

/* ── Search-alert subscriptions (F-15) ───────────────────────────── */
.subscription-form {
    border: 1px solid var(--rule);
    padding: 0.8rem 1rem;
    margin-bottom: 0.8rem;
}

.subscription-exclusions summary {
    cursor: pointer;
    color: var(--accent);
    font-size: 0.9rem;
}

.subscription-exclusion {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    margin: 0.25rem 1rem 0.25rem 0;
    font-size: 0.9rem;
}

/* Recipient choice (own account address vs. a typed foreign one). */
.subscription-recipient > span {
    display: block;
    font-size: 0.9rem;
    margin-bottom: 0.25rem;
}

.subscription-recipient-choice {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin: 0.2rem 0;
    font-size: 0.9rem;
}

.subscription-recipient-choice .admin-input {
    flex: 0 1 22rem;
    min-width: 0;
}

.subscription-test-hit {
    border-left: 3px solid var(--rule-dark);
    padding-left: 1rem;
    margin-bottom: 0.9rem;
}

.subscription-test-fragment {
    margin: 0.15rem 0;
    color: var(--ink);
    font-size: 0.92rem;
}

/* One-off historic backfill, opened from a newspaper row (F-10). A <details> panel rather than a
   dialog: it needs no JavaScript, and the action is a plain POST like every other admin form. */
.admin-backfill { position: relative; display: inline-block; }
.admin-backfill > summary { list-style: none; cursor: pointer; }
.admin-backfill > summary::-webkit-details-marker { display: none; }
.admin-backfill-panel {
    position: absolute;
    top: calc(100% + 2px);
    right: 0;
    z-index: 200;
    min-width: 15rem;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.6rem;
    text-align: left;
    background: var(--paper);
    border: 1px solid var(--rule-dark);
    box-shadow: 0 4px 16px rgba(0,0,0,0.12);
}
.admin-backfill-form { display: flex; flex-direction: column; gap: 0.3rem; }

/* Interfaces section on the overview page (API + MCP). */
.interface-text {
    margin: 0.2rem 0 0.3rem;
    font-size: 0.9rem;
    color: var(--ink);
}
.interface-url {
    margin: 0 0 0.8rem;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.85rem;
    /* Long enough to overflow a phone; break rather than widen the page. */
    overflow-wrap: anywhere;
}

/* Changelog on the overview page (one list per release). */
.changelog-list {
    margin: 0.2rem 0 0.6rem 1.2rem;
    padding: 0;
    font-size: 0.9rem;
    color: var(--ink);
}
.changelog-list li { margin: 0.2rem 0; }
