/* believeinjesus.org.uk — all site styles.
   Linked from <head>. Sections: theme, reset, base, logo, gospel reader, CTAs. */

/* ---------- Theme ----------
   Every colour in this file comes from a token here; there are no literals
   below except where a value is genuinely not a theme colour. Three states,
   the usual arrangement:

     - light      the default, on bare :root
     - system     no `data-theme` attribute, so the media query decides
     - explicit   `data-theme="dark"` / `"light"` stamped on the root element
                  by the bootstrap script in <head>, from localStorage

   The dark palette is written out twice on purpose — once for the media query
   and once for the explicit attribute — because CSS has no way to share one
   block between them without `light-dark()`, which is too new to rely on for
   an audience that includes old phones. **Keep the two copies in step.**

   The media-query copy is guarded with `:not([data-theme="light"])` so that a
   visitor who has deliberately chosen light is not overridden by their OS.

   `color-scheme` matters as well as the tokens: it is what makes the native
   <select> dropdowns and scrollbars follow the theme. */

:root {
    color-scheme: light;

    --ground: #fecb31;          /* the page itself — brand yellow */
    --ground-ink: #1a1a1a;      /* logo and footer text, on the ground */
    --panel: #fff;              /* the reading card */
    --ink: #1a1a1a;             /* body text */
    --rule: #ececec;            /* hairline dividers and card borders */
    --hover: #f4f4f4;           /* quiet hover fill */
    --accent: #fecb31;          /* brand yellow, on a panel */
    --flip: #1a1a1a;            /* inverted control: fill … */
    --flip-ink: #fecb31;        /* … and its text */
    --focus: #1a1a1a;           /* focus ring */
    --field: #fff;              /* select and input backgrounds */
    --field-border: #d8d8d8;
    --highlight: #fffdf5;       /* the promoted church card, admin callout */
    --stripe: #fafafa;          /* admin table banding */
    --shadow: rgb(0 0 0 / 0.15);
    --shadow-strong: rgb(0 0 0 / 0.35);
    --cta-bg: #fecb31;
    --cta-ink: #1a1a1a;
    --cta-bg-hover: #1a1a1a;
    --cta-ink-hover: #fecb31;
    --error-bg: #fff4f4;
    --error-border: #f3c2c2;
    --error-ink: #8a1f1f;

    /* The London map in the church finder. `water` is not only the Thames: it
       is everything the boroughs do not cover, so it also fills the corners of
       the frame that are Surrey and Essex. That is why it is a cool neutral
       rather than a blue — it has to read as "not London" as well as "river",
       and a proper blue would make London look like an island. */
    --map-land: #e8e3d7;
    --map-line: #cfc8b9;
    --map-water: #eef1f4;

    /* Reading size, set by the A-/A+ controls and remembered in localStorage.
       A multiplier rather than a size, so the scripture's own 1.125rem base
       stays the one place the type size is decided. */
    --reading-scale: 1;
}

/* Dark — copy 1 of 2: the visitor's explicit choice. */
:root[data-theme="dark"] {
    color-scheme: dark;

    /* Warm near-blacks rather than neutral grey, so the brand yellow sits on
       them without looking like it belongs to a different palette. */
    --ground: #17150f;
    --ground-ink: #f0e9da;
    --panel: #211e18;
    --ink: #ece5d6;
    --rule: #38342b;
    --hover: #2c2822;
    --accent: #fecb31;
    --flip: #fecb31;            /* inverts the other way round in the dark */
    --flip-ink: #1a1a1a;
    --focus: #fecb31;
    --field: #2c2822;
    --field-border: #4a453a;
    --highlight: #2b2519;
    --stripe: #262219;
    --shadow: rgb(0 0 0 / 0.45);
    --shadow-strong: rgb(0 0 0 / 0.6);
    --cta-bg: #fecb31;
    --cta-ink: #1a1a1a;
    --cta-bg-hover: #ffe48c;    /* brighter, not darker: inverting to black
                                   would vanish against the panel */
    --cta-ink-hover: #1a1a1a;
    --error-bg: #2e1a1a;
    --error-border: #5e2b2b;
    --error-ink: #f4b9b9;
    --map-land: #34302a;
    --map-line: #47423a;
    --map-water: #14120d;
}

/* Dark — copy 2 of 2: the operating system's preference, unless light was
   asked for explicitly. Keep in step with copy 1 above. */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        color-scheme: dark;

        --ground: #17150f;
        --ground-ink: #f0e9da;
        --panel: #211e18;
        --ink: #ece5d6;
        --rule: #38342b;
        --hover: #2c2822;
        --accent: #fecb31;
        --flip: #fecb31;
        --flip-ink: #1a1a1a;
        --focus: #fecb31;
        --field: #2c2822;
        --field-border: #4a453a;
        --highlight: #2b2519;
        --stripe: #262219;
        --shadow: rgb(0 0 0 / 0.45);
        --shadow-strong: rgb(0 0 0 / 0.6);
        --cta-bg: #fecb31;
        --cta-ink: #1a1a1a;
        --cta-bg-hover: #ffe48c;
        --cta-ink-hover: #1a1a1a;
        --error-bg: #2e1a1a;
        --error-border: #5e2b2b;
        --error-ink: #f4b9b9;
        --map-land: #34302a;
        --map-line: #47423a;
        --map-water: #14120d;
    }
}

/* ---------- Reset ----------
   Tailwind's preflight used to supply this. With the CDN dropped, these are
   the parts the layout actually relies on: border-box sizing, no body margin,
   a sane line-height, and no default margins on the headings, paragraphs and
   lists that the classes below position themselves. Remove any of it and
   spacing shifts. */

*, *::before, *::after { box-sizing: border-box; }

/* Preflight carried this too, and losing it is a genuine trap rather than a
   cosmetic difference: the UA stylesheet's `[hidden] { display: none }` is
   beaten by any author `display` rule, so a `display: flex` on the element
   itself makes `el.hidden = true` silently do nothing. That is exactly what
   happened to the install bar, which sat visible from first paint however
   often the script set `hidden`. `!important` because the point is to win
   against the element's own display. */
[hidden] { display: none !important; }

h1, h2, h3, p { margin: 0; }
ul, ol { margin: 0; padding: 0; }
button, select { font: inherit; color: inherit; margin: 0; }

/* ---------- Base ---------- */

body {
    margin: 0;
    /* was Tailwind's min-h-screen + p-4 */
    min-height: 100vh;
    padding: 1rem;
    line-height: 1.5;
    background-color: var(--ground);
    color: var(--ground-ink);
    /* Libre Franklin is the site's sans: headings, calls to action and all the
       chrome. It replaced Trade Gothic LT Condensed, which was pulled from
       cdnfonts and is no longer requested — nothing else used it, the logo
       being SVG paths rather than type. Only 400, 700 and 800 are loaded, so
       keep to those three weights. The fallbacks are the platform UI faces,
       which also carry the scripts Libre Franklin does not (it covers Latin
       and Vietnamese only, so Chinese or Arabic chrome falls through to them). */
    font-family: 'Libre Franklin', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
}

/* ---------- Logo ---------- */

/* The top padding is separation from the row of controls above, which is in
   the flow now rather than floating over this. */
.logo_wrapper {
    padding-top: 1.5rem;
    margin-bottom: 24px;
}
/* The logo is a link home — chapter 1, keeping language and translation. */
.logo {
    max-width: 240px;
    height: 78px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: transform 0.3s ease;
    color: var(--ground-ink);
}
/* The SVG's paths carry no `fill` of their own, so without this they default
   to black and the logo disappears in dark mode. */
.logo svg { fill: currentColor; }
.logo:hover {
    transform: scale(1.05);
}
.logo:focus-visible { outline: 2px solid var(--focus); outline-offset: 6px; border-radius: 0.3rem; }

/* ---------- Gospel reader ---------- */

/* The single white card holding the reader, the calls to action and the
   prev/next links. Sections inside it are plain — the panel owns the
   background, radius, shadow and padding. */
.panel {
    /* The "about this book" button is positioned against this — the corner of
       the card, not of the reader inside it, so it clears the card's padding
       rather than sitting on the book title. */
    position: relative;
    max-width: 44rem;
    margin: 0 auto 2rem;
    background: var(--panel);
    color: var(--ink);
    border-radius: 1rem;
    box-shadow: 0 10px 25px -5px var(--shadow);
    padding: 2rem 1.5rem 2.5rem;
}
@media (min-width: 768px) { .panel { padding: 3rem; } }

.reader-eyebrow {
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    opacity: 0.5;
}
/* 800 is the heaviest weight loaded, and the book title is the one place that
   wants it. */
.reader-title { font-size: 2.5rem; font-weight: 800; line-height: 1.1; margin: 0.25rem 0 0; }
/* Larger than the plain eyebrow: this one is a control, not just a label. */
.reader-reference { font-size: 1rem; }

/* ---------- Chapter menu ----------
   The title and reference are the <summary> of a <details> holding the chapter
   links, so the whole heading block is the click target. Same pattern as the
   language menu: native disclosure, plain links, no JavaScript needed. */

.chapter-menu { position: relative; margin-bottom: 1rem; }

/* Grid rather than a wrapper element, because <summary> takes phrasing and
   heading content — a <div> around the two headings would not be valid. The
   caret is placed explicitly in column 2 across both rows; the headings
   auto-place down column 1. */
.chapter-menu-toggle {
    display: grid; grid-template-columns: 1fr auto;
    align-items: center; column-gap: 0.75rem;
    padding: 0.25rem 0.5rem;
    margin-inline: -0.5rem;   /* so the headings stay flush with the scripture */
    border-radius: 0.5rem; cursor: pointer;
    list-style: none;   /* kill the default disclosure triangle */
    transition: background-color 0.15s ease;
}
.chapter-menu-toggle::-webkit-details-marker { display: none; }
.chapter-menu-toggle > :is(h1, h2) { grid-column: 1; }
.chapter-menu-toggle:hover { background: var(--hover); }
.chapter-menu-toggle:hover .reader-reference { opacity: 0.8; }
.chapter-menu-toggle:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.chapter-menu[open] .chapter-menu-toggle { background: var(--hover); }

.chapter-menu-caret {
    grid-column: 2; grid-row: 1 / span 2;
    width: 1.25rem; height: 1.25rem; opacity: 0.4;
    transition: transform 0.15s ease;
}
.chapter-menu[open] .chapter-menu-caret { transform: rotate(180deg); }

/* A grid of numerals, not a list of "Chapter N" rows: 16 of them fit in one
   compact block, and each link carries the spelled-out label for screen
   readers. inset-inline-start so it opens from the heading's edge in RTL too. */
.chapter-menu-list {
    position: absolute; inset-inline-start: 0; top: calc(100% + 0.25rem);
    z-index: 40;
    list-style: none; margin: 0; padding: 0.5rem;
    background: var(--panel); border-radius: 0.6rem;
    box-shadow: 0 10px 30px -6px var(--shadow-strong);
    display: grid; grid-template-columns: repeat(8, 2rem); gap: 0.15rem;
    max-width: calc(100vw - 3rem);
    max-height: min(60vh, 20rem); overflow-y: auto;
    overscroll-behavior: contain;   /* scrolling the menu must not scroll the page */
}

/* ---------- Top bar: reading controls and language menu ----------
   Deliberately the one part of the page that does NOT mirror: the four
   controls keep the same order whichever way the page reads. They are chrome,
   not text, and a visitor who switches language should find them where they
   left them.

   `direction: ltr` is what holds that order, and positions are physical for
   the same reason: without it a flex row in an RTL document lays its items
   out right-to-left, and the globe would swap ends with the text-size
   buttons. */

/* A centred row of four, in the flow above the logo. It used to be absolutely
   positioned in the top right corner, out of flow so that it added no height
   — which meant it overlapped the logo. It is in flow now precisely so that
   it reserves its own space and the logo has room to breathe beneath it. */
.lang-menu-bar {
    position: relative; z-index: 50;   /* relative only so the z-index applies */
    max-width: 44rem; margin: 0 auto;
    direction: ltr;
    display: flex; justify-content: center; align-items: center; gap: 0.4rem;
}

/* Text size and theme. Every one of these does nothing without JavaScript, so
   they are hidden until the bootstrap script in <head> marks the root element
   — revealed before first paint, so there is no pop-in, and never shown as
   dead controls. */
.reader-tools { display: none; }
:root[data-js] .reader-tools { display: flex; gap: 0.4rem; }

.lang-menu { position: relative; }

/* One control shape for the whole bar: a round panel-coloured button that
   inverts on hover. */
.lang-menu-toggle,
.tool-btn {
    display: flex; align-items: center; justify-content: center;
    width: 2.5rem; height: 2.5rem;
    border: 0; padding: 0;
    border-radius: 50%; cursor: pointer;
    background: var(--panel); color: var(--ink);
    box-shadow: 0 2px 8px var(--shadow);
    transition: background-color 0.15s ease, color 0.15s ease;
    list-style: none;   /* kill the default disclosure triangle */
}
.lang-menu-toggle::-webkit-details-marker { display: none; }
.lang-menu-toggle svg,
.tool-btn svg { width: 1.25rem; height: 1.25rem; }
.lang-menu-toggle:hover,
.tool-btn:hover:not(:disabled) { background: var(--flip); color: var(--flip-ink); }
.lang-menu-toggle:focus-visible,
.tool-btn:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.lang-menu[open] .lang-menu-toggle { background: var(--flip); color: var(--flip-ink); }

/* "A-" and "A+" as type rather than icons: it needs no translating, and the
   two sizes read as smaller/larger at a glance. */
.tool-btn { font-size: 0.95rem; font-weight: 700; line-height: 1; }
.tool-btn-sub { font-size: 0.7em; vertical-align: 0.1em; }
.tool-btn:disabled { opacity: 0.4; cursor: default; }

/* Sun or moon, whichever the theme is not. Same three states as the palette:
   light by default, dark by media query unless light was chosen explicitly,
   dark by attribute when it was chosen. */
.tool-icon-sun { display: none; }
:root[data-theme="dark"] .tool-icon-moon { display: none; }
:root[data-theme="dark"] .tool-icon-sun { display: block; }
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .tool-icon-moon { display: none; }
    :root:not([data-theme="light"]) .tool-icon-sun { display: block; }
}

/* A list of links rather than a <select>. 45 entries, so it scrolls.
   `right`, not `inset-inline-end`: the globe it hangs from does not mirror,
   so the list must open the same way — leftward from the globe — whichever
   direction the page reads in. */
.lang-menu-list {
    position: absolute; right: 0; top: calc(100% + 0.4rem);
    list-style: none; margin: 0; padding: 0.3rem;
    background: var(--panel); border-radius: 0.6rem;
    box-shadow: 0 10px 30px -6px var(--shadow-strong);
    max-height: min(65vh, 26rem); overflow-y: auto;
    min-width: 13rem; max-width: calc(100vw - 2.5rem);
    overscroll-behavior: contain;   /* scrolling the list must not scroll the page */
}
.lang-menu-list a {
    display: block; padding: 0.4rem 0.65rem; border-radius: 0.35rem;
    font-size: 0.9rem; line-height: 1.35; color: var(--ink); text-decoration: none;
    white-space: nowrap;
}
.lang-menu-list a:hover { background: var(--accent); color: var(--cta-ink); }
.lang-menu-list a:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.lang-menu-list a[aria-current] { background: var(--flip); color: var(--flip-ink); font-weight: 700; }

/* ---------- "About this book" ----------
   What Mark is, and how to read it. It lives at the top of the reading card,
   behind a small button in the corner, and opens by pushing the reading down
   rather than covering it — so it is part of the page while it is open and
   costs nothing while it is shut.

   It used to be an overlay hanging off the top bar, which needed anchoring to
   the centre of that bar and sizing against it to stay on screen. In the flow
   it needs none of that. */

/* Left as an ordinary block. Its only child while closed is the summary, which
   is taken out of flow below, so the element collapses to no height and nothing
   beneath it shifts — without `display: contents`, which is a risky thing to
   put on a <details> when the disclosure itself depends on how the UA treats
   the children. */

/* The quiet control shape used *on* a panel, as against the top bar's, which
   is a raised panel-coloured button sitting on the yellow ground. On white it
   has to do the opposite — recede until wanted — so it is a muted glyph with no
   fill until hover. The church finder's close button is the same thing in the
   same place, so it shares this rather than repeating it. */
.info-menu-toggle,
.church-close {
    display: flex; align-items: center; justify-content: center;
    width: 2rem; height: 2rem;
    padding: 0; border: 0; border-radius: 50%;
    background: transparent; color: var(--ink); opacity: 0.45;
    cursor: pointer;
    transition: opacity 0.15s ease, background-color 0.15s ease;
}
.info-menu-toggle svg,
.church-close svg { width: 1.1rem; height: 1.1rem; }
.info-menu-toggle:hover,
.church-close:hover { opacity: 1; background: var(--hover); }
.info-menu-toggle:focus-visible,
.church-close:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; opacity: 1; }

/* Lifted into the card's corner, which is what leaves the <details> itself with
   no height while it is closed. */
.info-menu-toggle {
    position: absolute; top: 0.6rem; inset-inline-end: 0.6rem; z-index: 2;
    list-style: none;   /* kill the default disclosure triangle */
}
.info-menu-toggle::-webkit-details-marker { display: none; }
/* Open, it is no longer a quiet control but the thing holding the note open,
   and it is the only way to close it again — so it inverts and says so. */
.info-menu[open] .info-menu-toggle { opacity: 1; background: var(--flip); color: var(--flip-ink); }

/* The slide itself. A grid with one row going 0fr → 1fr is the one way to
   animate to a height nobody can know in advance — the note is three
   paragraphs, and its height changes with the language, the reading size and
   the width of the screen. The inner element is what gets clipped, which is
   why `min-height: 0` and `overflow: hidden` sit on it rather than here. */
.info-menu-panel { display: grid; grid-template-rows: 1fr; }

.info-menu-inner {
    min-height: 0; overflow: hidden;
    /* Inside the clipped box, so it slides with the text instead of appearing
       at full size the moment the note opens. */
    padding-bottom: 1.75rem;
    text-align: start;
    font-size: 0.95rem; line-height: 1.65; color: var(--ink);
}
/* The hairline between the note and the reading, drawn the same way the panel
   separates its other sections. A pseudo-element rather than a border on the
   box, so the space above and below it is clipped along with everything else. */
.info-menu-inner::after {
    content: ''; display: block;
    margin-top: 1.5rem;
    border-top: 1px solid var(--rule);
}

/* <details> gives no closing animation — the content is simply gone — so this
   runs on open only, which is the half anyone notices. */
@keyframes info-slide-down {
    from { grid-template-rows: 0fr; opacity: 0; }
    to   { grid-template-rows: 1fr; opacity: 1; }
}
.info-menu[open] .info-menu-panel { animation: info-slide-down 0.3s ease; }
@media (prefers-reduced-motion: reduce) {
    .info-menu[open] .info-menu-panel { animation: none; }
}

.info-heading {
    font-size: 1rem; font-weight: 800; line-height: 1.3;
    margin: 0 0 0.5rem;
}
.info-menu-inner p { margin: 0 0 1.1rem; }
.info-menu-inner p:last-child { margin-bottom: 0; }

/* Web addresses in the note, linked by th_linked(). Underlined in the brand
   yellow like .reader-more rather than set in a link colour, since the address
   sits inside a sentence and reads as part of it. */
.info-menu-inner a {
    color: inherit; text-decoration: none;
    box-shadow: inset 0 -2px 0 var(--accent);
    transition: background-color 0.15s ease;
}
.info-menu-inner a:hover { background: var(--accent); color: var(--cta-ink); }
.info-menu-inner a:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

/* Scripture text — USFM classes emitted by the API. The set varies by
   version: BSB uses only p/pc/q1/q2, but NIVUK adds m, li1, li4, it, tl, qt,
   wj and iex. All block-level ones need explicit spacing, since the reset
   above strips default margins. */

/* 1.125rem is the base; --reading-scale is the A-/A+ multiplier, which the
   bootstrap script restores from localStorage before first paint. Nothing
   else on the page scales — the chrome stays put while the reading grows. */
.scripture {
    font-size: calc(1.125rem * var(--reading-scale, 1));
    line-height: 1.85; color: var(--ink);
}

/* Block: paragraphs */
.scripture .p,
.scripture .m,
.scripture .pc { margin: 0 0 1.15rem; }
.scripture .pc { text-align: center; }

/* Block: poetry and lists. Logical properties so indents flip in RTL. */
.scripture .q1  { margin: 0 0 0.25rem; padding-inline-start: 1.5rem; }
.scripture .q2  { margin: 0 0 0.25rem; padding-inline-start: 3rem; }
.scripture .li1 { margin: 0 0 0.25rem; padding-inline-start: 1.5rem; }
.scripture .li4 { margin: 0 0 0.25rem; padding-inline-start: 3rem; }
.scripture :is(.q1, .q2, .li1, .li4) + :is(.p, .m) { margin-top: 1.15rem; }

/* Block: editorial notes, e.g. "[The earliest manuscripts do not have
   verses 9–20.]" — not scripture, so set apart from it. */
.scripture .iex {
    margin: 1.15rem 0; font-size: 0.9em; font-style: italic; opacity: 0.65;
}

/* Inline. `wj` (words of Jesus) is deliberately left unstyled — it is the
   hook if red-letter text is ever wanted. */
.scripture .it,
.scripture .tl { font-style: italic; }

.scripture .yv-vlbl {
    font-size: 0.7em; font-weight: 700; vertical-align: super;
    opacity: 0.45; margin-inline-end: 0.25em; user-select: none;
}

/* The way out of the four-verse opening: the same chapter, whole. Deliberately
   not a .cta-item — it belongs to the reading rather than to the list of
   things to do next, so it is a text link with the brand rule under it rather
   than a yellow button competing with the four below. The arrow lives in the
   translated string, so RTL languages can point it the other way or drop it. */
.reader-more {
    display: inline-block;
    margin-top: 1.5rem;
    font-size: 0.95rem; font-weight: 700;
    color: var(--ink); text-decoration: none;
    padding-bottom: 0.15rem;
    box-shadow: inset 0 -2px 0 var(--accent);
    transition: box-shadow 0.15s ease;
}
.reader-more:hover { box-shadow: inset 0 -0.9em 0 var(--accent); }
.reader-more:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; border-radius: 0.2rem; }

/* ---------- Serif scripture ----------
   Merriweather sets the reading itself — and only the reading; the headings
   and the rest of the chrome stay in Libre Franklin. Applied through the
   `reader--serif` class that index.php adds only for Latin-script languages
   (yv_is_latin_script()) — the font has no glyphs beyond Latin, Cyrillic and
   Vietnamese, so anywhere else it would degrade to a per-browser fallback.
   The <head> requests three faces and no more: 400 and 400 italic for the
   text, 800 for the verse labels. Georgia is the fallback while the webfont
   swaps in, being the closest thing installed everywhere. */

.reader--serif .scripture {
    font-family: Merriweather, Georgia, 'Times New Roman', serif;
}
/* 800 rather than their usual 700: that is the only bold weight loaded for
   Merriweather, so asking for 700 here would get a synthesised one. */
.reader--serif .scripture .yv-vlbl { font-weight: 800; }

/* All chapter navigation, at the foot of the panel below the calls to action:
   prev/next first, then the numbered list. Deliberately quiet, so it never
   competes with the reading. */
.reader-nav {
    margin-top: 1.75rem; padding-top: 1.25rem;
    border-top: 1px solid var(--rule);
}
.reader-steps {
    display: flex; flex-wrap: wrap; gap: 1rem;
    justify-content: space-between; margin-bottom: 1.25rem;
}
.reader-step {
    font-size: 0.8rem; letter-spacing: 0.06em; font-weight: 700;
    text-decoration: none; color: var(--ink); opacity: 0.6;
    transition: opacity 0.15s ease;
}
.reader-step:hover { opacity: 1; text-decoration: underline; }
.reader-step[aria-disabled="true"] { opacity: 0.2; pointer-events: none; }

.chapter-nav {
    list-style: none; margin: 0; padding: 0;
    display: flex; flex-wrap: wrap; gap: 0.15rem;
}
/* Shared with the chapter menu at the top of the reader, so the numerals look
   the same wherever they appear. Only the resting opacity differs: the foot
   nav is deliberately recessive, a menu you have just opened is not. */
.chapter-nav a,
.chapter-menu-list a {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 1.75rem; height: 1.75rem;
    font-size: 0.8rem; text-decoration: none;
    color: var(--ink); opacity: 0.35; border-radius: 0.3rem;
    transition: opacity 0.15s ease, background-color 0.15s ease;
}
.chapter-nav a:hover,
.chapter-menu-list a:hover { opacity: 1; background: var(--hover); }
.chapter-nav a[aria-current="page"],
.chapter-menu-list a[aria-current="page"] {
    opacity: 1; font-weight: 700;
    box-shadow: inset 0 -2px 0 var(--accent);
}
.chapter-menu-list a { opacity: 0.75; width: 100%; height: 2rem; }

/* ---------- Admin ---------- */

.admin-head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }
.admin-label { font-size: 0.7rem; font-weight: 700; letter-spacing: 0.15em;
               text-transform: uppercase; opacity: 0.45; }
.admin-error { background: var(--error-bg); border: 1px solid var(--error-border); color: var(--error-ink);
               padding: 0.75rem 1rem; border-radius: 0.5rem; margin: 1rem 0; font-size: 0.9rem; }
.admin-meta  { font-size: 0.85rem; opacity: 0.7; margin: 0.75rem 0 1.25rem; }
.admin-dim   { opacity: 0.5; }
.admin-check { background: var(--highlight); border: 2px solid var(--ink); border-radius: 0.6rem;
               padding: 0.9rem 1.1rem; margin-bottom: 1.25rem; font-size: 0.9rem; }
.admin-check ul { margin: 0.5rem 0 0; padding-inline-start: 1.2rem; list-style: disc; }

.admin-search { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: center; }
.admin-filter {
    font: inherit; flex: 1 1 18rem; min-width: 0; padding: 0.5rem 0.7rem;
    background: var(--field); color: var(--ink);
    border: 1px solid var(--field-border); border-radius: 0.4rem;
}
.admin-filter:focus { outline: 2px solid var(--focus); outline-offset: 1px; border-color: var(--focus); }

/* 8,500 rows: cap the height and scroll inside, rather than a mile-long page. */
.admin-tablewrap { max-height: 70vh; overflow: auto; border: 1px solid var(--rule); border-radius: 0.5rem; }
.admin-table { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
.admin-table th, .admin-table td { padding: 0.35rem 0.6rem; text-align: left; white-space: nowrap; }
.admin-table thead th {
    position: sticky; top: 0; background: var(--flip); color: var(--flip-ink);
    font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase;
}
.admin-table tbody tr:nth-child(even) { background: var(--stripe); }
.admin-table code { font-size: 0.8rem; }

/* ---------- Page footer ----------
   Translation picker and the licence notice, below the calls to action. */

.page-footer {
    max-width: 44rem;
    margin: 0 auto;
    padding: 0 1.5rem 2.5rem;
    display: flex; flex-direction: column; gap: 1rem;
    align-items: flex-start;
}
@media (min-width: 768px) { .page-footer { padding-inline: 2.5rem; } }

/* max-width alone is not enough: the form is a content-sized flex item, so
   min-width:0 is what actually lets the select shrink inside the footer
   instead of pushing past it on a long label like
   "New International Version (Anglicised) (NIVUK)". */
.reader-translation {
    display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
    max-width: 100%; min-width: 0;
}
.reader-translation label {
    font-size: 0.7rem; font-weight: 700; letter-spacing: 0.15em;
    text-transform: uppercase; opacity: 0.45;
}
.reader-translation select {
    font: inherit; font-size: 0.85rem;
    padding: 0.3rem 0.45rem;
    border: 1px solid rgb(0 0 0 / 0.2); border-radius: 0.4rem;
    background: var(--field); color: var(--ink); cursor: pointer;
    max-width: 100%; min-width: 0; flex: 0 1 auto;
    text-overflow: ellipsis;
}
.reader-translation select:hover { border-color: var(--focus); }
.reader-translation select:focus { outline: 2px solid var(--focus); outline-offset: 1px; }
.reader-translation button { font: inherit; font-size: 0.85rem; padding: 0.3rem 0.6rem; }

/* pre-line keeps the line breaks in multi-line licence blocks (NIVUK). */
.reader-credit { font-size: 0.7rem; line-height: 1.5; opacity: 0.5;
                 margin: 0; white-space: pre-line; }
.reader-error { background: var(--error-bg); border: 1px solid var(--error-border); color: var(--error-ink);
                padding: 1rem 1.25rem; border-radius: 0.5rem; }

/* ---------- Calls to action ---------- */

/* A section of .panel, not a card of its own. */
.cta { margin-top: 2.5rem; padding-top: 1.5rem; border-top: 1px solid var(--rule); }

.cta-heading {
    font-size: 0.7rem; font-weight: 700; letter-spacing: 0.2em;
    text-transform: uppercase; opacity: 0.45; margin: 0 0 1rem;
}
.cta-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.6rem; }
/* Three parts in a row: icon, label, and the arrow from ::after. The icon and
   label sit together at the start and the arrow is pushed to the far end by
   its own auto margin — `justify-content: space-between` would instead strand
   the label in the middle between them. `text-align: start`, not `left`, so a
   wrapped label aligns correctly once the page mirrors. */
.cta-item {
    display: flex; align-items: center; gap: 0.8rem;
    width: 100%; text-align: start; font: inherit; font-size: 1.05rem; font-weight: 700;
    color: var(--cta-ink); text-decoration: none; cursor: pointer;
    background: var(--cta-bg); border: 0; border-radius: 0.6rem;
    padding: 0.9rem 1.15rem;
    transition: background-color 0.15s ease, color 0.15s ease;
}
.cta-item:hover { background: var(--cta-bg-hover); color: var(--cta-ink-hover); }
.cta-item::after { content: '\2192'; font-weight: 700; opacity: 0.6; margin-inline-start: auto; }

/* currentColor, so each icon inverts with its button on hover and follows the
   theme. Slightly lighter than the label, which stays the thing being read. */
.cta-icon {
    flex: 0 0 auto; width: 1.4rem; height: 1.4rem;
    opacity: 0.8;
}
/* The chevron has to point the other way once the page mirrors. */
[dir="rtl"] .cta-item::after { content: '\2190'; }

/* Revealed by the "find a church" action, not shown up front, and sitting
   inside that action's own <li> directly beneath the button — so it is drawn
   as a panel attached to the button rather than as a further section of the
   page. The top margin matches .cta-list's gap, so the spacing is the same as
   between any two actions. */
.church-finder {
    margin-top: 0.6rem;
    padding: 1rem 1.15rem 1.15rem;
    border: 1px solid var(--rule); border-radius: 0.6rem;
}

/* The area control and the close button on one line: the close stays in the
   corner without being positioned over a select whose width depends on the
   longest borough name. nowrap so it cannot drop onto a line of its own. */
.church-finder-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 1rem; flex-wrap: nowrap;
}
.church-finder-head .reader-control { min-width: 0; }

/* Shape shared with .info-menu-toggle, up in the "About this book" section —
   the same quiet round control on the same white panel. Only its place in the
   flex row belongs to it. */
.church-close { flex: 0 0 auto; }

.church-finder select {
    font: inherit; font-size: 0.9rem;
    padding: 0.35rem 0.5rem;
    border: 1px solid var(--field-border); border-radius: 0.4rem;
    background: var(--field); color: var(--ink); cursor: pointer; max-width: 100%;
}
.church-finder select:hover { border-color: var(--focus); }
.church-finder select:focus { outline: 2px solid var(--focus); outline-offset: 1px; }

/* The three options that are not boroughs — "Near me", "Point on a map" and
   "Somewhere else" — are the select's direct children, because the 33 boroughs
   are nested inside the <optgroup>. So `>` picks out exactly those three and
   nothing else, and they carry a little more weight than the long list they
   sit either side of.

   This is emphasis only. The separating is done by the <optgroup> in the
   markup, because an <option> is drawn by the platform and Safari and most
   mobile browsers ignore nearly everything you style on one — so anything that
   mattered could not live here. */
.church-finder select > option { font-weight: 700; }
.church-finder select optgroup { font-style: normal; }
.church-finder select optgroup option { font-weight: 400; }

.cta-status { margin: 1rem 0 0; font-size: 0.9rem; opacity: 0.7; }

/* ---------- The London map ----------
   Offered when there is no location to be had, and from the area dropdown.
   Geometry from lib/london-map.php, generated by tools/build-london-map.php. */

.church-map { margin-top: 1rem; }
.church-map-prompt { margin: 0 0 0.6rem; font-size: 0.9rem; opacity: 0.7; }

.church-map-svg {
    display: block; width: 100%; height: auto;
    border: 1px solid var(--rule); border-radius: 0.6rem;
    /* The backing rect is square, so without this it squares off the corners. */
    overflow: hidden;
    /* No double-tap-to-zoom delay on a control whose whole job is one tap. */
    touch-action: manipulation;
}

/* Behind everything, and the reason a tap on the Thames still works. It is
   painted rather than left transparent because an unfilled shape takes no
   pointer events at all. */
.church-map-field { fill: var(--map-water); }

.church-map-svg path[data-lad] {
    fill: var(--map-land);
    stroke: var(--map-line);
    /* viewBox units, where one unit is about 58 m. The Thames is the gap
       between these shapes — see lib/london-map.php — and this stroke is drawn
       either side of it, so much above 1 and the river closes up at Kew. */
    stroke-width: 1;
    stroke-linejoin: round;
    cursor: pointer;
    transition: fill 0.12s ease;
}

/* Guarded, or a tap leaves a borough stuck looking hovered on a phone. */
@media (hover: hover) {
    .church-map-svg path[data-lad]:hover { fill: var(--accent); }
}

/* Where they tapped. pointer-events off so it never blocks a second try. */
.church-map-pin {
    fill: var(--flip); stroke: var(--panel); stroke-width: 3;
    pointer-events: none;
}

/* Open Government Licence attribution. Small, but it does not get to be
   invisible — it is a condition of using the boundaries. */
.church-map-credit { margin: 0.4rem 0 0; font-size: 0.65rem; opacity: 0.55; }

.cta-results { margin-top: 1.25rem; }
.cta-results:empty { display: none; }

.church {
    border: 1px solid var(--rule); border-radius: 0.6rem;
    padding: 0.85rem 1rem; margin-bottom: 0.5rem;
}
.church-top {
    border: 2px solid var(--ink); background: var(--highlight);
    padding: 1.1rem 1.15rem; margin-bottom: 0.9rem;
}
.church-name { font-weight: 700; font-size: 1.05rem; margin: 0 0 0.15rem; }
.church-top .church-name { font-size: 1.3rem; }
.church-meta { font-size: 0.85rem; opacity: 0.65; margin: 0; }
.church-links { margin-top: 0.5rem; display: flex; flex-wrap: wrap; gap: 0.75rem; }
.church-links a { font-size: 0.8rem; font-weight: 700; color: var(--ink); }

.cta-more { font-size: 0.7rem; font-weight: 700; letter-spacing: 0.15em;
            text-transform: uppercase; opacity: 0.45; margin: 1.25rem 0 0.6rem; }

/* ---------- Install invitation ----------
   Shown by index.php only when there is something to offer, and only once the
   visitor is reading. Fixed to the foot of the viewport, with `has-install-bar`
   adding the room so it never covers the last line of the reading. */

.install-bar {
    position: fixed; inset-inline: 0; bottom: 0; z-index: 60;
    display: flex; flex-wrap: wrap; gap: 0.75rem 1.25rem;
    align-items: center; justify-content: center;
    /* env() keeps it clear of the iPhone home indicator in an installed
       window, and resolves to 0 everywhere else. */
    padding: 0.85rem 1rem calc(0.85rem + env(safe-area-inset-bottom, 0px));
    background: var(--panel); color: var(--ink);
    border-top: 1px solid var(--rule);
    box-shadow: 0 -8px 24px -10px var(--shadow);
}
body.has-install-bar { padding-bottom: 7rem; }

.install-text { font-size: 0.9rem; line-height: 1.4; margin: 0; max-width: 30rem; }
.install-actions { display: flex; align-items: center; gap: 0.5rem; }
.install-go,
.install-dismiss {
    font: inherit; font-size: 0.85rem; font-weight: 700;
    padding: 0.5rem 0.9rem; border: 0; border-radius: 0.5rem; cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease, opacity 0.15s ease;
}
.install-go { background: var(--cta-bg); color: var(--cta-ink); }
.install-go:hover { background: var(--cta-bg-hover); color: var(--cta-ink-hover); }
.install-dismiss { background: transparent; color: var(--ink); opacity: 0.6; }
.install-dismiss:hover { opacity: 1; background: var(--hover); }
.install-go:focus-visible,
.install-dismiss:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
