/* reader.css — the reading surface.
 *
 * One typeface family. Two weights. One accent. Nothing else.
 *
 * Every rule here is in service of one sentence: the text is the interface.
 * There are no gradients, no decorative shadows, no icon set, no stock imagery
 * and no animation beyond a fast, purposeful transition — because a stranger
 * arriving at a Bible should see a book, not a product tour.
 *
 * The measure is held at 60-70 characters, which is why the column is set in
 * `ch` and not in pixels: it is a typographic measurement and it should be
 * written as one.
 */

:root {
  /* The search magnifier. A mask, not an <img>: it inherits colour, costs no
     request, and cannot fall out of step with the palette. */
  --find-glyph: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round"><circle cx="11" cy="11" r="7"/><path d="M20 20l-3.6-3.6"/></svg>');
  color-scheme: dark light;

  /* Warm dark ground. Most listening is at night, and a blue-black screen at
   * 1 a.m. is a lamp pointed at the reader's face. */
  --ground: #14110e;
  --ground-lift: #1c1815;
  --ink: #ece4d8;
  /* AAA, not AA. Measured against --ground: 8.6:1. The old #a2978a was 6.6:1,
   * which passes AA and fails droide's rule for this fleet — 7:1 for body
   * text, and never a colour darker than #8a9aa8 on a dark ground. Secondary
   * text on a READING site is not decoration: it is the standfirst, the
   * chapter counts and the countdown. */
  --ink-quiet: #b9aea0;
  --rule: #2e2822;

  /* The one accent. Ember, not gold: it has to survive AAA against the ground
   * as well as against the light theme's paper. */
  --ember: #e0a45c;
  /* --ember-deep is 4.3:1 on the dark ground, and that is DELIBERATE and
   * checked: it is never used for text. It is the dial's starting stroke and
   * the failed notice's rule — non-text graphics, where WCAG asks 3:1, not
   * 7:1. Lightening it to AAA would flatten the dial's colour journey to
   * nothing. If it is ever put on a word, it must change. */
  --ember-deep: #a86a24;
  /* The ONE colour outside the accent family, and it earns its place: it means
   * finished, and nothing else on the site is allowed to use it. A state
   * colour, not a second brand colour. Tuned to sit on the warm dark ground
   * without turning acid. */
  --done: #5cc98c;

  --measure: 66ch;
  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua",
           Charter, "Bitstream Charter", Georgia, "Times New Roman", serif;
}

@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --ground: #f7f3ec;
    --ground-lift: #fffdf9;
    --ink: #1d1913;
    --ink-quiet: #4a4238; /* 8.9:1 on paper; was 6.4:1 */
    --rule: #ddd4c6;
    --ember: #7a4409;     /* 7.1:1 on paper; was 5.9:1, which failed AAA */
    --ember-deep: #5e3305;
    /* Darker on paper, or it reads as a highlighter pen. */
    --done: #155c39;      /* 7.2:1 on paper; the brighter green was 4.8:1 */
  }
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--serif);
  /* 22px base, per droide's UX standard: "presbyopic eyes need real size, not
   * incremental bumps", and this is a Bible — its readers skew exactly there.
   * It scales up on a wide screen and never down: the floor is the standard.
   * Body text scales with the viewport; rem-based controls use the explicit
   * 16px root and have their own readable size floors. */
  font-size: clamp(1.375rem, 1.28rem + 0.42vw, 1.55rem);
  line-height: 1.7;
  font-weight: 400;
  text-rendering: optimizeLegibility;
}

.sr, .skip:not(:focus) {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

.skip:focus {
  position: fixed; inset: 0.5rem auto auto 0.5rem;
  z-index: 10; padding: 0.6rem 1rem;
  background: var(--ember); color: var(--ground);
  border-radius: 2px;
}

/* ------------------------------------------------------------- the frame --
 * anav's bar, and the one line it needs from us.
 *
 * anav sets `.anav-brand { color: var(--anav-fg) }` and then, LATER in the same
 * stylesheet, `.anav a { color: inherit }`. The brand IS an <a>, and 0-1-1 beats
 * 0-1-0, so the brand always inherits from the page rather than from the theme.
 * On a site whose body text is light that is invisible; on this one, whose light
 * theme sets near-black ink, the wordmark rendered as a dark smudge on a dark
 * bar and was effectively unreadable.
 *
 * MEASURED, not guessed: getComputedStyle on .anav-brand returned rgb(29,25,19)
 * — this stylesheet's --ink — while --anav-fg on the same element was #f1ece3.
 * CDP's matched-rules dump named `.anav a { color: inherit }` as the winner.
 *
 * So we supply what anav assumes: a colour on the container for `inherit` to
 * resolve against. This is not an override of anav's design — it is the same
 * value anav was already trying to use.
 */
.anav { color: var(--anav-fg, #f1ece3); }

/* ------------------------------------------------------------------ search --
 * The search field is on EVERY page and covers every book. It is the whole
 * navigation: there are no nested menus anywhere on this site.
 */

/* The search field, and nothing else. The BRAND lives in anav's bar directly
 * above; carrying a second wordmark here was two logos in 60 vertical pixels. */

/* THE SEARCH READS AS A SEARCH.
 *
 * It was a transparent input under a 1px underline with a text "Go" beside it,
 * which is indistinguishable from a horizontal rule with words near it — the
 * reader could not tell the site was searchable at all. It also sat about ten
 * pixels above the masthead's own border, so the top of every page opened with
 * two parallel lines.
 *
 * Now it is a filled, rounded field with a magnifier: the shape people have
 * been taught to type into. The underline is gone, which removes one of those
 * two lines as a side effect.
 */
/* IN THE NAV NOW, at a quarter of the width it had.
 *
 * It used to be a full-measure field in a bar of its own; that bar existed only
 * to hold it, so both are gone and the field sits in anav's actions slot. A
 * quarter of the reading measure is enough for "1 Sam 2" and short enough to
 * belong in a top bar rather than dominate it. It grows back on a narrow screen
 * where the bar has nothing else to hold. */
.find {
  display: flex;
  align-items: center;
  flex: 0 1 auto;
  width: 100%;
  max-width: calc(var(--measure) * 0.25);
  min-width: 11rem;
  gap: 0.5rem;
  padding: 0.15rem 0.5rem 0.15rem 0.75rem;
  background: var(--ground-lift);
  border: 1px solid var(--rule);
  border-radius: 999px;
  transition: border-color 160ms ease, box-shadow 160ms ease;
}
.find:hover { border-color: color-mix(in oklab, var(--rule), var(--ink) 25%); }
.find:focus-within {
  border-color: var(--ember);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--ember), transparent 82%);
}

/* The magnifier, drawn as a mask so it takes the current text colour and needs
 * no image request and no second file to keep in step with the palette. */
.find::before {
  content: "";
  flex: none;
  width: 1em;
  height: 1em;
  background-color: var(--ink-quiet);
  mask: var(--find-glyph) center / contain no-repeat;
  -webkit-mask: var(--find-glyph) center / contain no-repeat;
}
.find:focus-within::before { background-color: var(--ember); }

.find input {
  flex: 1;
  min-width: 0;
  padding: 0.4rem 0.2rem;
  border: 0;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 0.95rem;
}
.find input::placeholder { color: var(--ink-quiet); opacity: 1; }
.find input:focus { outline: none; }

/* The action sits INSIDE the field, as a pill of its own, so the whole control
 * reads as one object rather than a word floating beside a line. */
.find button {
  flex: none;
  border: 0;
  border-radius: 999px;
  background: color-mix(in oklab, var(--ember), transparent 88%);
  color: var(--ember);
  font: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  padding: 0.3rem 0.75rem;
  cursor: pointer;
  transition: background-color 160ms ease;
}
.find button:hover { background: color-mix(in oklab, var(--ember), transparent 78%); }
.find button:focus-visible { outline: 2px solid var(--ember); outline-offset: 2px; }

/* ------------------------------------------------------------------ pages -- */

main {
  max-width: var(--measure);
  margin: 0 auto;
  padding: clamp(2rem, 7vw, 4.5rem) clamp(1rem, 5vw, 2rem) 4rem;
}

/* THE CHAPTER PAGE STARTS HIGH.
 *
 * A landing page wants air above its opening line; a chapter does not. Here the
 * top of the screen carried the masthead, then 4.5rem of padding, then the
 * chapter nav, then the title, then the player — five things before a word of
 * scripture, on the one page whose entire job is the scripture. The generous
 * `main` padding stays for the pages that open with a lede.
 */
.reading {
  padding-top: clamp(0.5rem, 1.4vw, 0.9rem);
}

.lede {
  font-size: clamp(1.8rem, 1.3rem + 2.2vw, 2.9rem);
  line-height: 1.15;
  font-weight: 400;
  margin: 0 0 1rem;
  text-wrap: balance;
}

.standfirst { color: var(--ink-quiet); margin: 0 0 2.5rem; }
.quiet { color: var(--ink-quiet); font-size: 0.82rem; }

.books { list-style: none; margin: 0; padding: 0; }
/* No rule per row. Sixty-six books meant sixty-six horizontal lines, which is
 * a table's worth of furniture for what is a list of names. The rows are
 * separated by their own padding and lift on hover instead. */
.books li + li { border-top: 1px solid color-mix(in oklab, var(--rule), transparent 55%); }
.books a {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  padding: 0.65rem 0.25rem;
  color: var(--ink);
  text-decoration: none;
  transition: color 90ms linear, background-color 90ms linear;
}
.books a:hover, .books a:focus-visible {
  color: var(--ember);
  background: var(--ground-lift);
  outline: none;
}
.books a:focus-visible { outline: 2px solid var(--ember); outline-offset: -2px; }
/* The chapter count, doubled. At 0.78rem it was a footnote beside the name;
   it is the one piece of information on the row besides the book itself. */
.books .ch { color: var(--ink-quiet); font-size: 1.56rem; font-variant-numeric: tabular-nums; line-height: 1; }

/* THE TWO TESTAMENTS, marked rather than merely listed.
 *
 * Sixty-six names in one column is a directory. The canon has one structural
 * division that every reader already knows, and naming it in full turns the
 * list into something with a shape. The rule is short and centred under the
 * words rather than a full-width border — the page has few enough lines now
 * that adding one back should be deliberate. */
/* THE TOC HEADINGS, at the size a Bible's own table of contents gives them.
   They divide sixty-six books into the two halves every reader already knows,
   and at 0.82rem they read as a label on the list rather than a division of
   it. Letter-spacing eases off as the size climbs — tracking that suits small
   caps pulls a large word apart. */
.testament {
  margin: 2.5rem 0 0.25rem;
  font-size: 1.8rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ember);
}
.testament:first-of-type { margin-top: 1.5rem; }
.testament::after {
  content: "";
  display: block;
  width: 2.5rem;
  height: 2px;
  margin-top: 0.5rem;
  background: var(--ember);
  opacity: 0.55;
}

/* -------------------------------------------------------------- scripture -- */

.chapter-title {
  font-weight: 400;
  font-size: clamp(1.5rem, 1.2rem + 1.4vw, 2.2rem);
  margin: 0 0 0.9rem;
  display: flex;
  align-items: baseline;
  gap: 0.4ch;
}
.chapter-title .no { color: var(--ember); font-variant-numeric: lining-nums; }

.listen { margin: 0 0 1.75rem; }

/* The one primary action on the page. Everything else recedes. */
/* THE ONE PRIMARY ACTION, AND IT NOW LOOKS LIKE ONE.
 *
 * It was a transparent box with a 1px outline and a 2px radius, which reads as
 * a bordered label rather than something to press — the filled state existed
 * only on hover, so a reader who never hovered never saw a button at all.
 * Filled by default now, pill-shaped like the search field, so the two controls
 * on the site speak the same language. */
.play {
  display: inline-block;
  padding: 0.8rem 1.7rem;
  border: 1px solid transparent;
  border-radius: 999px;
  background: var(--ember);
  color: var(--ground);
  font: inherit;
  font-size: 1.02rem;
  font-weight: 600;
  cursor: pointer;
  transition: background-color 140ms ease, transform 140ms ease;
}
.play:hover, .play:focus-visible { background: var(--ember-deep); color: var(--ground); }
.play:active { transform: translateY(1px); }
.play:focus-visible { outline: 2px solid var(--ember); outline-offset: 3px; }
.play[disabled] { opacity: 0.55; cursor: progress; }

.listen .quiet { margin: 0.6rem 0 0; }

/* The form is a layout no-op: the button IS the control, and wrapping it in a
 * real <form method="post"> is what makes the page work with no JavaScript. */
.ask { margin: 0; }

/* THE ASKING STATES ARE CENTRED. Idle and failed are a single control and one
 * line of explanation with nothing else on screen; left-aligning them under a
 * centred dial-shaped hole in the page just looked unplaced. The READING states
 * are not touched — scripture stays left-aligned, where it is read. */
.listen[data-state="idle"],
.listen[data-state="failed"] {
  text-align: center;
}

/* ------------------------------------------------------------- generating --
 * A chapter of synthesis is a long silence, and a silent button is
 * indistinguishable from a broken one. So the wait is SHOWN, with pubvoice's
 * own sentences_done — never a spinner, which would keep turning just as
 * happily if the job had died.
 */
.progress { margin: 0; }

/* THE DIAL.
 *
 * A chapter takes around a minute to record, and a 3px bar asks a reader to
 * squint at a hairline for that whole time. This is the one place on the site
 * where something is deliberately large: it is the only thing happening, the
 * reader is waiting on it, and it should be readable from across a room.
 *
 * It NEVER advances on its own. Every movement is a real reading from
 * pubvoice's sentences_done, eased between two measurements — so the dial
 * cannot claim progress the job has not made.
 */
.dial {
  --fill: 0;
  position: relative;
  width: clamp(9rem, 34vw, 12rem);
  aspect-ratio: 1;
  margin: 0 auto;
}

.dial svg { width: 100%; height: 100%; transform: rotate(-90deg); }

.dial circle {
  fill: none;
  stroke-width: 11;
  stroke-linecap: round;
}
.dial-track { stroke: var(--rule); }

/* THE COLOUR TRAVELS WITH THE FILL, and stays inside the one accent family the
 * UI standard allows: it starts in the accent's deep register, arrives at the
 * full accent, and finishes bright. That is a change of temperature, not a
 * second accent colour — a red-to-green progress bar would be a palette this
 * site does not have.
 *
 * color-mix does the interpolation from --fill (0-100), so the palette lives
 * here and JavaScript only ever reports a number.
 */
.dial-run {
  stroke: color-mix(in oklab, var(--ember-deep), var(--ember) calc(var(--fill) * 1%));
  transition: stroke-dashoffset 500ms linear, stroke 500ms linear;
}

/* DONE IS GREEN, and it is the only green on the site.
 *
 * The ring closes, the colour lands, a soft halo blooms once and settles. The
 * halo is a filter on the stroke rather than a box-shadow, so it follows the
 * ARC and not the square the SVG sits in — a rectangular glow behind a circle
 * is the tell of a progress ring that was decorated rather than designed.
 */
.dial-done .dial-run {
  stroke: var(--done);
  filter: drop-shadow(0 0 7px color-mix(in oklab, var(--done), transparent 45%));
  transition: stroke 450ms ease, filter 450ms ease, stroke-dashoffset 450ms ease;
}
.dial-done .dial-track { stroke: color-mix(in oklab, var(--done), transparent 82%); }
.dial-done .dial-pct { color: var(--done); }
.dial-done .dial-eta { color: color-mix(in oklab, var(--done), var(--ink-quiet) 55%); }

/* One settle, then still. Scripture is not a slot machine. */
.dial-done { animation: dial-settle 620ms cubic-bezier(0.22, 1, 0.36, 1); }
@keyframes dial-settle {
  0%   { transform: scale(1); }
  42%  { transform: scale(1.045); }
  100% { transform: scale(1); }
}

.dial-centre {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.15em;
  line-height: 1;
}
.dial-pct {
  font-size: clamp(1.9rem, 7vw, 2.6rem);
  font-variant-numeric: tabular-nums lining-nums;
  color: var(--ink);
}
.dial-eta {
  /* A quarter larger: it is the answer to "how much longer", read from across
     a room, inside a ring built to be read from across a room. */
  font-size: 1rem;
  color: var(--ink-quiet);
  font-variant-numeric: tabular-nums;
  min-height: 1em;
}

/* The line under the dial. Centred beneath it and a quarter larger, because
 * during a wait it is the only thing on the page worth reading — and it sits
 * under a control that is deliberately the biggest thing on the site. */
/* The line under the dial: centred, and given the WIDTH IT HAS. It was capped
 * at 34rem, which forced a short sentence to wrap onto two lines under a dial
 * that is already the largest thing on the page. It is one line now, and on any
 * ordinary screen it stays one line. */
.going {
  margin: 0.9rem 0 0;
  text-align: center;
  color: var(--ink);
  font-size: 1.19rem;
  line-height: 1.4;
  text-wrap: balance;
}
.going .secs { font-variant-numeric: tabular-nums; }
.going strong { color: var(--ember); font-variant-numeric: tabular-nums; }

/* A failure is a state the reader can see and act on, not a wait that never
 * ends. It reads in the accent's darker register so it is plainly not a
 * success, without shouting. */
.notice.failed { border-left-color: var(--ember-deep); margin-bottom: 1rem; }

/* THE PLAYER, CENTRED AND TALLER.
 *
 * This is a NATIVE <audio> element, and a browser does not let a stylesheet
 * reach the play button inside it — there is no standard hook for it. What a
 * stylesheet CAN set is the element's height, and every engine scales the
 * controls to fill it. So 2.5rem to 3.5rem is the 40% increase, applied to the
 * whole control; the play button grows with it because it is the largest thing
 * in there.
 *
 * The WebKit rule below reaches the button directly where that is possible. It
 * is an enhancement and nothing depends on it: Firefox ignores it and gets the
 * taller control, which is the point of doing it by height first.
 */
.player {
  display: block;
  width: 100%;
  max-width: 34rem;
  height: 3.5rem;
  margin: 0 auto;
  color-scheme: dark;
}
.player::-webkit-media-controls-play-button,
.player::-webkit-media-controls-mute-button {
  transform: scale(1.4);
}

/* A READY CHAPTER IS CENTRED, like the states either side of it. The player is
 * one wide control with a line under it and nothing else on screen; left-
 * aligning it while the idle and waiting states are centred made pressing play
 * shift the page's whole balance. Scripture below is untouched. */
.listen[data-state="ready"] {
  text-align: center;
}

@media (prefers-reduced-motion: reduce) {
  .dial-run { transition: none; }
  .dial-done { animation: none; }
}

/* THE READER'S OWN SIZE, and only over the scripture.
 *
 * A- and A+ in the top bar drive --reading-scale. It is applied in `em`, so it
 * multiplies the inherited 22px base rather than replacing it: the nav, the
 * footer and the player keep the sizes they were designed at, and only the text
 * a person is actually reading grows. Bounded 0.9-1.6 in reading.js — below
 * that it undercuts droide's 22px floor, above it a verse wraps every four
 * words on a phone.
 *
 * Default 1 with no script and no stored choice, so the page is correct before
 * a single byte of JavaScript runs. */
.scripture {
  margin: 0;
  font-size: calc(1em * var(--reading-scale, 1));
}

/* Verse numbers HANG in the margin: visible to the eye, out of the reading
 * line, and never spoken. On a narrow screen there is no margin to hang into,
 * so they sit inline and superior rather than overlapping the text. */
.v {
  position: relative;
  margin: 0 0 1.15rem;
  padding-left: 0;
}
/* The verse number is a BUTTON now, and must not look like one: a page of
 * scripture with 31 buttons down its margin is a form. It keeps the margin
 * number's exact appearance and gains a cue on hover and focus only. */
.vn {
  appearance: none;
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  cursor: pointer;
  color: var(--ink-quiet);
  font-size: 0.72em;
  font-variant-numeric: lining-nums tabular-nums;
  vertical-align: super;
  margin-right: 0.45ch;
  user-select: none;
}

@media (min-width: 46rem) {
  .v { padding-left: 0; }
  .vn {
    position: absolute;
    left: -3.2ch;
    top: 0.15em;
    vertical-align: baseline;
    font-size: 0.75em;
    margin: 0;
    text-align: right;
    width: 2.6ch;
  }
}

/* A translator's note. It is a marker the reader may choose to read — never
 * inlined into the sentence, and never spoken. */
.note {
  border: 0;
  background: transparent;
  color: var(--ember);
  font: inherit;
  font-size: 0.8em;
  vertical-align: super;
  padding: 0 0.15ch;
  cursor: help;
}
.note:focus-visible { outline: 2px solid var(--ember); outline-offset: 1px; }

/* THE VERSE BEING SPOKEN.
 *
 * "Gently" is the whole brief. A wash of the accent at low alpha behind the
 * words, and a rule in the margin so the position is carried by TWO signals —
 * colour alone fails a reader who cannot distinguish it, and the fleet's
 * accessibility rule is that the highlight must never be the only indication
 * of where we are.
 *
 * The verse does not move, resize or change weight when it lights. Anything
 * that reflows the column makes the whole page twitch once per verse for four
 * minutes.
 *
 * THE WASH IS PAINTED ENTIRELY WITH SHADOWS, never with padding. Padding on a
 * block <p> reflows the column the moment it lights, which is the twitch the
 * paragraph above forbids. A shadow has no layout at all: three copies of the
 * same tint, spread vertically and offset sideways, give a box that is wider on
 * the LEFT than the right — the margin the verse number hangs into — and a
 * little taller than the line.
 *
 * THE TINT IS OPAQUE, AND THAT IS THE WHOLE REASON THERE IS NO INNER FRAME.
 * An outer box-shadow is clipped to OUTSIDE the border box, so two shadows that
 * both reach past the box overlap each other in the band around it. At 12%
 * alpha that band painted twice — one rectangle drawn inside the other, a
 * visible frame a third of the way in from the silhouette. Mixing the same 12%
 * of ember into the ground instead gives a colour that is IDENTICAL to the eye
 * and cannot compound: overlap it as many times as you like and it stays one
 * flat shape. Never put a translucent colour back here.
 *
 * The three offsets are named, so the box can be retuned in one place.
 */
.v {
  --hl: color-mix(in oklab, var(--ember) 12%, var(--ground));
  /* The same colour at zero alpha. Transitioning from plain `transparent` is a
   * fade from transparent BLACK; this fades from the wash's own hue. */
  --hl-off: color-mix(in srgb, var(--hl), transparent 100%);
  --hl-left: 1.5ch;   /* more room on the number's side */
  --hl-right: 0.85ch;
  --hl-y: 0.3em;      /* a tad above and below */

  /* The resting shape the lit one grows FROM. Without it the browser has
   * `none` on one side of the transition and the box can snap in rather than
   * fade in — the marking jumping into place is the exact thing being fixed. */
  background: var(--hl-off);
  box-shadow: 0 0 0 0 var(--hl-off),
              0 0 0 0 var(--hl-off),
              0 0 0 0 var(--hl-off);
  /* A SECOND, to match the second the highlight now runs AHEAD of the voice:
   * it finishes arriving exactly as the reader is spoken to. */
  transition: background 1000ms ease, box-shadow 1000ms ease;
}
.v.speaking {
  background: var(--hl);
  box-shadow: 0 0 0 var(--hl-y) var(--hl),
              calc(var(--hl-left) * -1) 0 0 var(--hl-y) var(--hl),
              var(--hl-right) 0 0 var(--hl-y) var(--hl);
  border-radius: 4px;
}
.v.speaking .vn { color: var(--ember); }

@media (hover: hover) {
  .vn:hover { color: var(--ember); }
}
.vn:focus-visible { outline: 2px solid var(--ember); outline-offset: 2px; border-radius: 2px; }

/* Confirmation lives ON the number that was clicked — a toast in a corner is a
 * second place to look for the answer to "did that work". */
.vn.copied::after {
  content: "link copied";
  position: absolute;
  margin-left: 0.6ch;
  font-size: 0.62em;
  letter-spacing: 0.02em;
  color: var(--done);
  white-space: nowrap;
}

/* A verse you can hear from is a verse you can click. The cue is quiet until
 * the pointer is on it — 31 permanently-underlined verses would be a page of
 * links, not a page of scripture. */
.scripture .v.seekable { cursor: pointer; }
@media (hover: hover) {
  .scripture .v.seekable:hover .vn {
    color: var(--ember);
    text-decoration: underline;
    text-underline-offset: 0.2em;
  }
}

@media (prefers-reduced-motion: reduce) {
  .v, .v.speaking { transition: none; }
}

/* The speed announcement. Bottom centre, out of the reading column, gone in a
 * second and a half — a reader changing speed wants confirmation, not a
 * permanent readout. */
.announce {
  position: fixed;
  left: 50%;
  bottom: 1.5rem;
  transform: translateX(-50%);
  margin: 0;
  padding: 0.45rem 1rem;
  background: var(--ground-lift);
  border: 1px solid var(--rule);
  border-radius: 999px;
  color: var(--ink);
  font-size: 0.78rem;
  pointer-events: none;
  z-index: 5;
}
.announce:empty { display: none; }

.notice {
  border-left: 2px solid var(--ember);
  padding: 0.75rem 0 0.75rem 1rem;
  margin: 0 0 2.5rem;
  color: var(--ink-quiet);
  font-size: 0.95rem;
}

/* ----------------------------------------------------------------- onward --
 * One chapter at a time. The reader clicks. Nothing rolls on by itself, and
 * that is a decision, not an omission.
 */

/* The top copy carries no rule above it and sits tighter — it is a way out,
 * not a conclusion. Only the bottom one closes the chapter. */

.onward {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  margin-top: 3.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--rule);
  font-size: 0.95rem;
}

/* THE TOP COPY CARRIES NO RULE, and this block must stay BELOW .onward.
 *
 * The element is class="onward onward-top". Both selectors are a single class,
 * so they have identical specificity and the LATER one wins — which meant this
 * block sat above .onward and every override in it silently lost: the line was
 * drawn anyway, and the 3.5rem top margin applied, pushing the whole page down.
 *
 * Reading either rule alone shows nothing wrong. Only their ORDER decides.
 * (The same trap as anav's .anav a{color:inherit} beating .anav-brand earlier
 * in this service's life.)
 *
 * It is a way OUT of the chapter, not a conclusion. Only the bottom copy closes
 * anything, and only the bottom copy draws a line.
 */
.onward-top {
  margin: 0 0 1rem;
  padding-top: 0;
  border-top: 0;
  font-size: 0.9rem;
}
.onward a { color: var(--ember); text-decoration: none; }
.onward a:hover { text-decoration: underline; text-underline-offset: 0.25em; }
.onward a:focus-visible { outline: 2px solid var(--ember); outline-offset: 3px; }

/* The one line of provenance under everything. It is the site's own statement
   about what this text is and what it costs, and at 0.82rem inside the reading
   measure it read as boilerplate. A quarter wider than the column and 40%
   larger: still quiet, no longer fine print. */
.footing {
  max-width: min(48rem, 100%);
  margin: 0 auto;
  padding: 2rem clamp(1rem, 5vw, 2rem) 3rem;
  /* NO border-top. The chapter nav above already draws one a couple of
     centimetres higher, and two parallel rules that close nothing between them
     read as a mistake. Space separates the footer now. */
  color: var(--ink-quiet);
  font-size: 1.15rem;
  line-height: 1.5;
}
.footing p { margin: 0 0 0.4rem; }
/* 18px at the 22px base — droide's floor for readable content is 15px, and a
 * licence line is content, not a badge. */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}

/* ------------------------------------------------------ waiting on the dial --
 *
 * While a chapter is being made, the page BEHIND the dial softens: the verses,
 * both chapter navigations and the title recede, and the only things left sharp
 * are the ring, the number and countdown inside it, and the sentence under it.
 *
 * The reason is that the dial is a genuinely long wait — around a minute — and
 * a page that keeps every element at full contrast around it is asking the eye
 * to choose. Nothing else on the page can be acted on until the recording
 * exists, so nothing else should be competing for attention.
 *
 * IT IS A SOFTENING, NOT A CURTAIN. 3px and 55% opacity: the text stays plainly
 * a chapter of scripture and its shape is still readable, so the page does not
 * appear to have been replaced by a modal. Scripture is never hidden on this
 * site, and this must not be the first place it is.
 *
 * :has() scopes it to the generating state, so a page that is idle, ready or
 * failed is untouched and no class has to be added or removed by script.
 */
.reading:has(.listen[data-state="generating"]) .scripture,
.reading:has(.listen[data-state="generating"]) .onward,
.reading:has(.listen[data-state="generating"]) .chapter-title {
  filter: blur(3px);
  opacity: 0.55;
  transition: filter 420ms ease, opacity 420ms ease;
  /* The blurred text is decoration for the duration: it must not be reachable
     by tab, because focus would land on something the reader cannot read. */
  pointer-events: none;
  user-select: none;
}

/* IT LIFTS THE MOMENT THE READER REACHES FOR IT.
 *
 * "You can keep reading while you wait" is a promise the page makes two lines
 * below the dial, and a blur that could not be undone would break it. Hovering
 * the passage, or focusing anything inside it from the keyboard, restores it in
 * full — so the softening is a default, not a lock.
 */
.reading:has(.listen[data-state="generating"]) .scripture:hover,
.reading:has(.listen[data-state="generating"]) .scripture:focus-within {
  filter: none;
  opacity: 1;
  pointer-events: auto;
  user-select: auto;
}

/* Nobody who has asked not to be moved gets a transition; the end state is the
 * same, it simply arrives at once. */
@media (prefers-reduced-motion: reduce) {
  .reading:has(.listen[data-state="generating"]) .scripture,
  .reading:has(.listen[data-state="generating"]) .onward,
  .reading:has(.listen[data-state="generating"]) .chapter-title {
    transition: none;
  }
}

/* THE DIAL LEAVES BY SHRINKING, not by being replaced mid-frame.
 *
 * The ring closing is the moment the whole wait built towards. Cutting straight
 * to the player threw that away and jolted the page as one element of one
 * height became another of a different one. It scales down and fades instead,
 * and the swap happens after the transition has run.
 */
.dial-leaving {
  transform: scale(0.82);
  opacity: 0;
  transition: transform 400ms cubic-bezier(0.4, 0, 0.2, 1), opacity 400ms ease;
}

@media (prefers-reduced-motion: reduce) {
  .dial-leaving { transition: opacity 200ms linear; transform: none; }
}

/* A- / A+ in the bar. Deliberately quiet: they are for the reader who needs
   them and should not compete with the search field beside them. */
.textsize {
  display: flex;
  gap: 0.15rem;
  flex: none;
}
.textsize button {
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: transparent;
  color: var(--ink-quiet);
  font: inherit;
  font-size: 0.85rem;
  line-height: 1;
  padding: 0.35rem 0.6rem;
  cursor: pointer;
  transition: color 140ms ease, border-color 140ms ease;
}
.textsize button:hover { color: var(--ember); border-color: var(--ember); }
.textsize button:focus-visible { outline: 2px solid var(--ember); outline-offset: 2px; }
.textsize button[disabled] { opacity: 0.4; cursor: default; }

/* Browse and offline library: the same warm reading ground, with enough
   structure to find a book or select a recording without a long scroll. */
.canon, .download-library { max-width: 1120px; }
.opening { padding: 1rem 0 3rem; max-width: 850px; }
.opening .lede { font-size: clamp(3rem, 7vw, 5.6rem); letter-spacing: -.045em; line-height: 1.05; }
.opening .lede em { color: var(--ember); font-weight: 400; }
.opening .standfirst { max-width: 46ch; margin: 1.5rem 0; }
.eyebrow { color: var(--ember); font: 600 .9375rem/1.5 system-ui,sans-serif; letter-spacing: .13em; text-transform: uppercase; margin: 0 0 1.2rem; }
.actions, .chapter-download { display: flex; align-items: center; flex-wrap: wrap; gap: 1rem 1.5rem; }
.actions a, .chapter-download a { font-size: 1rem; }
.actions .play { text-decoration: none; }
.reading-note { display: flex; gap: 1.5rem; align-items: baseline; border-top: 1px solid var(--rule); padding-top: 1.5rem; margin-top: 3rem; color: var(--ink-quiet); }
.reading-note > span { white-space: nowrap; font: 600 .9375rem/1.5 system-ui,sans-serif; color: var(--ember); }
.reading-note p { margin: 0; font-size: 1.1rem; }
.reading-note a { display: inline-block; font-size: 1rem; margin-left: .4rem; }
.start-points { display: grid; grid-template-columns: repeat(3,minmax(0,1fr)); gap: 1px; background: var(--rule); border: 1px solid var(--rule); border-radius: 16px; overflow: hidden; }
.start-points a { display: flex; flex-direction: column; gap: .6rem; background: var(--ground-lift); padding: 1.5rem; text-decoration: none; }
.start-points a:hover { background: var(--ground); }
.start-points span { font: 400 .9375rem/1.5 system-ui,sans-serif; color: var(--ink-quiet); }
.start-points strong { color: var(--ink); font-weight: 400; }
.browse-heading, .library-heading { display: flex; justify-content: space-between; gap: 2rem; align-items: end; padding-top: 3.5rem; }
.browse-heading h2, .plan-note h2, .offline-intro h2 { font-size: clamp(1.8rem,4vw,2.6rem); font-weight: 400; line-height: 1.15; margin: 0 0 1.3rem; }
.browse-heading .eyebrow { margin-bottom: .7rem; }
.canon .books { display: grid; grid-template-columns: repeat(3,minmax(0,1fr)); gap: 0 1.6rem; }
.canon .books li { min-width: 0; border-bottom: 1px solid var(--rule); }
.canon .books a { font-size: 1.1rem; min-height: 56px; padding: .6rem .25rem; gap: .5rem; }
.canon .books .ch { font-size: .9375rem; }
.canon .testament { font: 600 1.25rem/1.5 system-ui,sans-serif; letter-spacing: .035em; margin: 2rem 0 .75rem; text-transform: none; }
.canon .testament::after { display: none; }
.plan-note { border-top: 1px solid var(--rule); margin-top: 4rem; padding: 3rem 0 0; max-width: 760px; }
.plan-note p:not(.eyebrow) { color: var(--ink-quiet); }
.plan-note > a { font-size: 1.1rem; }
.breadcrumb { font: 400 .9375rem/1.6 system-ui,sans-serif; color: var(--ink-quiet); }
.library-heading { padding-top: 2rem; align-items: center; }
.library-heading > a { font-size: 1rem; }
.allowance { display: flex; justify-content: space-between; align-items: center; gap: 1rem; background: var(--ground-lift); border: 1px solid var(--rule); border-radius: 12px; padding: 1.3rem 1.5rem; margin: 1.5rem 0 .5rem; }
.allowance strong { color: var(--ember); font-size: 2.5rem; font-weight: 400; white-space: nowrap; }
.allowance strong span { font-size: 1.2rem; color: var(--ink); }
.allowance > span { font: 400 .9375rem/1.6 system-ui,sans-serif; color: var(--ink-quiet); text-align: right; }
.download-library > .quiet { font-size: .9375rem; }
.download-library .standfirst { margin-top: 2rem; }
.library-tools { display: flex; flex-wrap: wrap; gap: .75rem; align-items: end; margin: 1.5rem 0; }
.library-tools label { flex: 1 1 220px; font: 400 1rem/1.6 system-ui,sans-serif; }
.library-tools input { width: 100%; margin-top: .35rem; border: 1px solid var(--rule); background: var(--ground-lift); color: var(--ink); font: inherit; padding: .75rem 1rem; border-radius: 8px; min-height: 48px; }
.secondary { background: transparent; color: var(--ember); border: 1px solid var(--ember); padding: .65rem 1rem; border-radius: 999px; font: 500 1rem/1.5 system-ui,sans-serif; cursor: pointer; min-height: 48px; }
.secondary:hover { background: var(--ground-lift); }
.recordings { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); gap: 0 1.5rem; }
.recording { display: flex; align-items: center; gap: .65rem; border-bottom: 1px solid var(--rule); padding: .75rem 0; min-width: 0; cursor: pointer; }
.recording input { width: 24px; height: 24px; flex: none; accent-color: var(--ember); }
.recording span { flex: 1; font-size: 1.1rem; }
.recording a { font-size: .9375rem; padding: .5rem; }
.recording:has(input:checked) { background: var(--ground-lift); }
.download-toolbar { position: sticky; bottom: .7rem; display: flex; align-items: center; justify-content: space-between; gap: 1rem; border: 1px solid var(--rule); border-radius: 12px; background: var(--ground-lift); padding: 1rem; margin-top: 2rem; }
.download-toolbar span { font-size: 1rem; }
.offline-intro, .empty-library { padding: 2rem 0; }
.chapter-download { border-block: 1px solid var(--rule); padding: 1rem 0; margin-bottom: 2rem; }
.chapter-download form { margin: 0; }
.chapter-download .quiet { width: 100%; margin: 0; font-size: .9375rem; }
.textsize button { min-height: 44px; min-width: 44px; font-size: .9375rem; }
.find button { min-height: 44px; font-size: .9375rem; }
:focus-visible { outline: 2px solid var(--ember); outline-offset: 4px; }
[hidden] { display: none !important; }
/* A reader may keep reading while recording. Blur and pointer-events:none
   previously made that promise impossible on touch and with a keyboard. */
.reading:has(.listen[data-state="generating"]) .scripture,
.reading:has(.listen[data-state="generating"]) .onward,
.reading:has(.listen[data-state="generating"]) .chapter-title { filter: none; opacity: 1; pointer-events: auto; user-select: auto; }
@media (max-width: 700px) {
 .canon .books { grid-template-columns: repeat(2,minmax(0,1fr)); gap: 0 1rem; }
 .start-points { grid-template-columns: 1fr; }
 .start-points a { flex-direction: row; justify-content: space-between; align-items: center; padding: 1rem 1.2rem; }
 .browse-heading { display: block; }
 .browse-heading > .quiet br { display: none; }
 .recordings { grid-template-columns: 1fr; }
 .allowance { flex-direction: column; align-items: start; }
 .allowance > span { text-align: left; }
 .download-toolbar { flex-wrap: wrap; bottom: 0; }
 .download-toolbar .play { width: 100%; }
 .reading-note { gap: .8rem; }
 .library-heading { align-items: start; gap: 1rem; }
 .library-heading .lede { font-size: 2.5rem; }
}
@media (max-width: 390px) {
 .canon .books a { font-size: 1rem; }
 .canon .books { gap: 0 .75rem; }
}

main a { color: var(--ember); text-underline-offset: .2em; }
main a:visited { color: var(--ember); }
main a.play:visited { color: var(--ground); }
.library-heading > a { white-space: nowrap; min-height: 44px; display: inline-flex; align-items: center; }
.anav .textsize { display: none; }
body:has(main.reading .scripture) .anav .textsize { display: flex; }
.anav .textsize button { color: var(--anav-fg); border-color: var(--anav-border); width: 44px; flex: 0 0 44px; padding: .35rem; margin: 0; }
.anav .find { --ground-lift: #1c2028; --ink: #f1ece3; --ink-quiet: #b9c0cd; --ember: #cfa978; --rule: #414957; margin: 0; }
.anav .find button { width: auto; margin: 0; line-height: 1.5; }

/* Pico styles every label, including the shared nav's menu label. Keep the
   menu's three strokes spaced and centred, with a full touch target. */
@media (max-width: 860px) {
  .anav .anav-burger { display: inline-flex; align-items: center; width: 44px; min-width: 44px; min-height: 44px; }
}

/* One reading room across the reader, newsroom and Lighthouse store. The SDK
   owns commerce; this scope owns the site's typography, palette and frame. */
html { font-size: 16px; }
body { min-height: 100svh; display: flex; flex-direction: column; }
body > main { flex: 1 0 auto; width: 100%; }
body > .footing { margin-top: auto; }
.quiet { font-size: max(.9375rem, .82em); }
.anav { flex: none; font-family: system-ui,sans-serif !important; }
.anav .anav-wrap { max-width: 1160px; }
.anav .anav-brand { font-family: system-ui,sans-serif; }
.anav .find input { background-image: none; font-family: system-ui,sans-serif; font-size: 15px; }
.anav .find input:focus { background-image: none; }
.anav .anav-list { padding: 0; }
.anav .anav-list a { margin: 0; }
.anav .anav-burger { margin: 0; cursor: pointer; }
.anav .anav-burger:focus-visible { outline: 2px solid var(--anav-accent); outline-offset: 3px; }
.opening { margin-inline: auto; text-align: center; max-width: 900px; padding-block: clamp(2.5rem,7vw,5rem); }
.opening .lede { font-size: clamp(2.8rem,5.2vw,4.7rem); line-height: 1.08; max-width: 900px; margin-inline: auto; }
.opening .standfirst { max-width: 620px; margin-inline: auto; }
.opening .actions { justify-content: center; }
.hero-plans { max-width: 580px; margin: 1.5rem auto; font: 400 1rem/1.7 system-ui,sans-serif; color: var(--ink-quiet); }
.opening .reading-note { justify-content: center; max-width: 650px; margin: 2.4rem auto 0; text-align: left; }
.page-intro { max-width: 800px; margin: 0 auto 2.5rem; text-align: center; padding-top: clamp(1.5rem,5vw,3.5rem); }
.page-intro .lede { font-size: clamp(2.5rem,5vw,4rem); margin: .6rem auto 1.3rem; line-height: 1.12; }
.page-intro .standfirst { margin-inline: auto; max-width: 620px; font-size: 1.3rem; }
.news-column { max-width: 760px; margin: 0 auto; }
.news-page .ablog-list__lede, .news-page .ablog-list__foot { display: none; }
.news-page .ablog-list__empty { margin: 0; padding: clamp(1.5rem,4vw,3rem); background: var(--ground-lift); border: 1px solid var(--rule); border-radius: 16px; text-align: center; font-size: 1.25rem; color: var(--ink-quiet); opacity: 1; }
.news-page .ablog-list__link { background: var(--ground-lift); border: 1px solid var(--rule); border-radius: 16px; padding: clamp(1.4rem,4vw,2.5rem); color: var(--ink); }
.news-page .ablog-list__head { font: 400 clamp(1.5rem,3vw,2rem)/1.25 var(--serif); color: var(--ink); margin-bottom: 1rem; }
.news-page .ablog-list__teaser { font-size: 1.15rem; color: var(--ink-quiet); opacity: 1; }
.news-page .ablog-list__meta { font: 400 .9375rem/1.6 system-ui,sans-serif; color: var(--ink-quiet); opacity: 1; margin-top: 1.2rem; }
.page-next { display: flex; justify-content: center; align-items: center; gap: 1.5rem; flex-wrap: wrap; margin: 2.5rem auto; font-size: 1.1rem; }
.newsletter-page { max-width: 800px; padding-top: 3.5rem; }
.newsletter-page > .eyebrow { text-align: center; margin-bottom: 2rem; }
.newsletter-context { font-size: 1rem; color: var(--ink-quiet); }
.newsletter-page .anews { --anews-bg: var(--ground-lift); --anews-fg: var(--ink); --anews-muted: var(--ink-quiet); --anews-border: var(--rule); --anews-font: system-ui,sans-serif; }
.chapter-search { max-width: 680px; margin: 2rem auto; }
.chapter-search label, .chapter-chooser label { display: block; font: 500 1rem/1.6 system-ui,sans-serif; margin-bottom: .5rem; }
.chapter-search > div { display: flex; gap: .75rem; }
.chapter-search input, .chapter-chooser select { min-width: 0; min-height: 48px; border: 1px solid var(--rule); border-radius: 8px; padding: .7rem 1rem; background: var(--ground-lift); color: var(--ink); font: 400 1.1rem/1.5 system-ui,sans-serif; }
.chapter-search input { flex: 1; width: 100%; }
.chapter-search .play { flex: none; }
.search-examples { display: flex; justify-content: center; gap: 1.5rem; flex-wrap: wrap; font-size: 1.1rem; }
.results-title { max-width: 760px; margin: 3rem auto 1rem; font-size: 1.5rem; font-weight: 400; }
.canon .books.search-results { max-width: 760px; margin-inline: auto; grid-template-columns: 1fr; }
.state-card { max-width: 680px; margin: 2rem auto; padding: 2rem; border: 1px solid var(--rule); border-radius: 16px; background: var(--ground-lift); }
.state-card h2 { font-size: 1.5rem; font-weight: 400; }
.state-card p { font-size: 1.15rem; color: var(--ink-quiet); }
.chapter-chooser { display: flex; align-items: center; justify-content: center; gap: .7rem; margin: 1.4rem 0 2rem; flex-wrap: wrap; }
.chapter-chooser label { margin: 0; }
.chapter-chooser select { max-width: 100%; }
.chapter-chooser .secondary { border-radius: 8px; }
/* Pico's page-wide rules must not change the store's shared chrome. */
:root:has(main.container) { --pico-font-size: 16px; --pico-font-family: var(--serif); --pico-background-color: var(--ground); --pico-color: var(--ink); --pico-muted-color: var(--ink-quiet); --pico-primary: var(--ember); --pico-primary-hover: var(--ember); --pico-primary-background: var(--ember); --pico-primary-border: var(--ember); --pico-primary-inverse: var(--ground); --pico-card-background-color: var(--ground-lift); }
body:has(main.container) { font-family: var(--serif); background: var(--ground); color: var(--ink); }
body:has(main.container) :is(h1,h2,h3,h4) { color: var(--ink); font-family: var(--serif); }
body:has(main.container) .lh-muted { color: var(--ink-quiet); opacity: 1; }
body:has(main.container) .anav { --pico-font-family: system-ui,sans-serif; }
body:has(main.container) main { max-width: 1120px; }
body:has(main.container) main :is(p,li) { font-size: max(1rem,1em); }
body:has(main.container) .anav .find input { margin: 0; box-shadow: none; }
@media (max-width: 860px) {
  .anav .anav-wrap { column-gap: .5rem; padding-inline: 20px; }
  .anav .anav-brand { flex: 1 0 auto; max-width: calc(100% - 60px); }
  .anav .anav-brand > span:last-child { overflow: visible; text-overflow: clip; }
  .anav .anav-burger { order: 1; flex: 0 0 44px; }
  .anav .anav-actions { order: 3; flex: 1 0 100%; width: 100%; max-width: none; min-height: 0; padding: 0 0 12px; gap: .5rem; }
  .anav .anav-list { order: 2; }
  .anav .find { width: 100%; flex: 1; }
  .anav .find input { width: 100%; max-width: none; }
  .anav .textsize { flex: none; gap: 3px; }
  .anav .textsize button { width: 44px; }
  .opening { padding-top: 2rem; }
  .opening .reading-note > span { display: none; }
}
@media (max-width: 480px) {
  .chapter-search > div { flex-direction: column; }
  .chapter-search .play { width: 100%; }
  .chapter-chooser label { width: 100%; text-align: center; }
  .page-next { gap: 1rem; }
  .opening .actions { flex-direction: column; }
}
.anav .anav-burger { background: transparent; border: 0; color: var(--anav-fg); box-shadow: none; padding: 0; }
.anav :is(a,span,li,div,button,label,input) { font-family: system-ui,sans-serif; }
.anav .find input { padding: .5rem .35rem; height: 44px; }
body:has(main.container) main.container { font-size: 1.125rem; }
body:has(main.container) .lh-hero h1 { font-weight: 400; font-size: clamp(2rem,4vw,3.5rem); max-width: 740px; }
body:has(main.container) .lh-hero p.sub { font-size: 1.2rem; max-width: 620px; }
body:has(main.container) .lh-blocks { display: grid; grid-template-columns: repeat(3,minmax(0,1fr)); gap: 1.5rem; max-width: none; border-top: 1px solid var(--rule); padding-top: 2rem; }
body:has(main.container) .lh-blocks section { margin: 0; text-align: left; }
body:has(main.container) .lh-blocks h2 { font-size: 1.3rem; line-height: 1.3; }
body:has(main.container) .lh-blocks p { font-size: 1.05rem; line-height: 1.7; }
@media (max-width: 860px) {
  .anav .find { max-width: none; }
  body:has(main.container) .lh-blocks { grid-template-columns: 1fr; gap: 1.8rem; }
}
.anav .anav-list, .anav .anav-list li, .anav .anav-list a { color: var(--anav-fg); }
body:has(main.container) .lh-card h2 { font-size: 1.5rem; line-height: 1.2; }
body:has(main.container) .lh-card .lh-price { font-size: 2.5rem; line-height: 1.2; margin: .7rem 0; }
body:has(main.container) .lh-card .lh-price small { font-size: 1rem; }
body:has(main.container) .lh-card .lh-summary { font-size: 1.125rem; line-height: 1.55; }
body:has(main.container) .lh-card .lh-feats li { font-size: 1.05rem; line-height: 1.5; }
body:has(main.container) .lh-recommend { font-size: .9375rem; letter-spacing: .07em; }
body:has(main.container) .lh-card button { font: 600 1rem/1.5 system-ui,sans-serif; min-height: 48px; }
.newsletter-page .anews :is(.anews__privacy,.anews__aside,.anews__label,.anews__legend,.anews__intro,.anews__cue) { font-size: 1rem; opacity: 1; color: var(--ink-quiet); }
.newsletter-page .anews .anews__input { border: 1px solid var(--ink-quiet); color: var(--ink); background: var(--ground-lift); min-height: 48px; }
.newsletter-page .anews .anews__input::placeholder { color: var(--ink-quiet); opacity: 1; }
.newsletter-page .anews { --anews-muted-opacity: 1; --anews-accent: var(--ember); }
.download-library .library-heading { padding-top: 1.3rem; }
.download-library .library-heading .lede { font-size: clamp(2rem,4vw,3rem); }
.download-library .library-heading .eyebrow { margin-bottom: .7rem; }
.download-library .standfirst { font-size: 1.2rem; margin-top: 1.5rem; }
.download-library .offline-intro { padding: .3rem 0 1rem; }
.download-library .offline-intro p { font-size: 1.2rem; line-height: 1.6; margin-top: .5rem; }
.download-library .plan-note { padding-top: 2rem; margin-top: 2rem; }
.download-library .plan-note p { font-size: 1.15rem; }
.download-library .allowance-refresh { margin-block: .4rem 1rem; }
.download-policy { margin-top: 2rem; padding: 1rem 0; border-block: 1px solid var(--rule); font-size: 1.05rem; }
.download-policy summary { cursor: pointer; min-height: 44px; display: flex; align-items: center; gap: .5rem; color: var(--ember); }
.download-policy summary::before { content: "+"; font: 400 1.3rem system-ui,sans-serif; }
.download-policy[open] summary::before { content: "−"; }
.newsletter-page .anews :is(.anews__face,.anews__tick) { border-color: var(--ink-quiet); }
.newsletter-page .anews { --anews-submit-fg: var(--ground); --anews-check-fg: var(--ground); }
body:has(main.container) :is(.lh-trust,.lh-powered,.lh-powered span) { font-size: .9375rem; }
/* These sellables grant chapter-download plans, not developer API access. The
   scope labels are SDK diagnostics; the authored features explain the benefit. */
body:has(main.container) :is(.lh-unlocks,.lh-label:has(+ .lh-unlocks)) { display: none; }
body:has(main.container) .lh-show:not(:has(.lh-show-media img,.lh-show-media .lh-ico)) { grid-template-columns: minmax(0,1fr); max-width: 800px; margin-inline: auto; padding: clamp(1.25rem,4vw,2.5rem); gap: 0; }
body:has(main.container) .lh-show-media:not(:has(*)) { display: none; }
body:has(main.container) .lh-show-main > :is(h1,.lh-summary-lead,.lh-price) { text-align: center; margin-inline: auto; }
body:has(main.container) .lh-show-main > h1 { font-size: clamp(2rem,4vw,3rem); font-weight: 400; }
body:has(main.container) .lh-show-main .lh-buy { justify-content: center; }
body:has(main.container) .lh-show-main .lh-assure { max-width: none; font-size: 1rem; }
body:has(main.container) .lh-show details summary { min-height: 44px; padding-block: .65rem; font-size: 1.05rem; }

/* Kept outside the changing dial so keyboard focus survives each poll. */
.spoken-updates {
  display: block;
  width: auto;
  margin: .5rem auto 1rem;
  padding: .4rem .8rem;
  font-size: .82rem;
}
.spoken-updates[hidden] { display: none; }

/* Responsive reading room: generous on a monitor, reachable with one thumb. */
.canon { max-width: 1240px; }
.canon .opening { padding-top: clamp(1.5rem,4vw,3.5rem); }
.opening .lede { max-width: 850px; font-size: clamp(2.75rem,5.5vw,5rem); }
.opening .browse-link { display: block; flex-basis: 100%; font-family: system-ui,sans-serif; }
.opening .reading-note { border-block: 1px solid var(--rule); padding-block: 1.25rem; }
.start-points { gap: 12px; background: transparent; border: 0; overflow: visible; }
.start-points a { border: 1px solid var(--rule); border-radius: 16px; padding: 1.5rem; transition: border-color 160ms ease, background-color 160ms ease; }
.start-points a:hover { border-color: var(--ember); }
.start-points strong::after { content: " ↗"; color: var(--ember); font-size: 1rem; }
.resume-reading { display: flex; justify-content: space-between; align-items: center; gap: 1.5rem; margin: 0 0 2rem; padding: 1.4rem 1.7rem; border: 1px solid var(--ember); border-radius: 16px; background: var(--ground-lift); text-decoration: none; }
.resume-reading > span:first-child { display: grid; gap: .3rem; }
.resume-reading .eyebrow { margin: 0; font-size: .9375rem; }
.resume-reading strong { color: var(--ink); font-size: 1.5rem; font-weight: 400; }
.resume-reading #resume-detail { color: var(--ink-quiet); font: 400 1rem/1.5 system-ui,sans-serif; }
.resume-reading > span:last-child { font: 500 1rem/1.5 system-ui,sans-serif; }
.book-finder { max-width: 620px; margin: .5rem 0 2rem; }
.book-finder label { display: block; margin-bottom: .5rem; font: 500 1rem/1.5 system-ui,sans-serif; }
.book-filter-field { display: flex; gap: .75rem; }
.book-filter-field input { min-width: 0; width: 100%; min-height: 52px; padding: .75rem 1rem; border: 1px solid var(--rule); border-radius: 10px; background: var(--ground-lift); color: var(--ink); font: 400 1.05rem/1.5 system-ui,sans-serif; }
.book-filter-field input::placeholder { color: var(--ink-quiet); opacity: 1; }
.book-finder .quiet { font: 400 .9375rem/1.5 system-ui,sans-serif; margin: .6rem 0 0; }
.canon .testament { text-transform: none; letter-spacing: -.02em; font-size: 2rem; margin-block: 2.5rem 1rem; }
.canon .books { grid-template-columns: repeat(3,minmax(0,1fr)); gap: .25rem 2rem; }
.canon .books a { min-height: 68px; align-items: center; padding: .7rem .5rem; border-radius: 8px; }
.canon .books .bk { font-size: 1.25rem; }
.canon .books .ch { display: grid; gap: .1rem; justify-items: end; font-size: 1.1rem; line-height: 1.25; }
.chapter-unit { font: 400 .9375rem/1.3 system-ui,sans-serif; }
#books, #old-testament, #new-testament { scroll-margin-top: 2rem; }
.reading .chapter-title { font-size: clamp(2.8rem,5vw,4rem); letter-spacing: -.04em; margin-bottom: 1rem; }
.reading .chapter-chooser { justify-content: start; margin-block: 1rem 1.5rem; }
.reading .chapter-chooser label { width: 100%; text-align: left; }
.reading .chapter-chooser select { flex: 1; }
.reading .listen[data-state="ready"] { position: sticky; top: max(.5rem,env(safe-area-inset-top)); z-index: 4; padding: 1rem; border: 1px solid var(--rule); border-radius: 18px; background: var(--ground-lift); margin-bottom: 1.5rem; }
.reading .listen[data-state="ready"] .player { width: 100%; max-width: none; margin: 0; }
.reading .listen[data-state="ready"] .quiet { font-size: .9375rem; margin: .5rem 0; }
.player-tools { display: flex; align-items: center; justify-content: space-between; gap: .5rem; margin-top: .7rem; font: 400 1rem/1.4 system-ui,sans-serif; }
.projector-open { min-height: 44px; padding: .4rem .6rem; font: inherit; }
.player-tools label { display: flex; align-items: center; gap: .5rem; }
.player-tools select { font: inherit; color: var(--ink); background: var(--ground); border: 1px solid var(--rule); border-radius: 8px; min-height: 44px; padding: .4rem; }
.player-chapters { display: grid; grid-template-columns: auto minmax(0,1fr) auto; align-items: center; gap: .5rem; margin-top: .75rem; padding-top: .5rem; border-top: 1px solid var(--rule); font: 400 .9375rem/1.35 system-ui,sans-serif; }
.player-chapters a { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: .35rem .5rem; border-radius: 8px; color: var(--ember); text-decoration: none; white-space: nowrap; }
.player-chapters a:hover, .player-chapters a:focus-visible { background: var(--ground); outline: 2px solid var(--ember); outline-offset: 2px; }
.player-chapter-title { min-width: 0; text-align: center; color: var(--ink-quiet); overflow-wrap: anywhere; }
.reading-guide { display: flex; justify-content: space-between; flex-wrap: wrap; gap: .5rem; margin: 1rem 0 1.5rem; padding-bottom: .8rem; border-bottom: 1px solid var(--rule); font: 400 .9375rem/1.5 system-ui,sans-serif; color: var(--ink-quiet); }
.reading-guide > span:first-child { color: var(--ember); }
.reading .v { scroll-margin-top: 240px; }
.reading .onward a { min-height: 48px; display: inline-flex; align-items: center; }
.play:hover, .play:focus-visible { background: var(--ember); color: var(--ground); outline: 2px solid var(--ember); outline-offset: 4px; }
@media (min-width: 1100px) {
  .reading { max-width: 960px; padding-inline: 4rem; }
  .reading .scripture { max-width: 62ch; }
  .reading .chapter-title { font-size: 4.5rem; }
}
@media (min-width: 701px) and (max-width: 1000px) {
  .canon .books { grid-template-columns: repeat(2,minmax(0,1fr)); }
}
@media (max-width: 700px) {
  .canon .books { grid-template-columns: repeat(2,minmax(0,1fr)); gap: .25rem 1rem; }
  .canon .books a { align-items: start; flex-direction: column; gap: .3rem; }
  .canon .books .ch { display: flex; align-items: baseline; gap: .35rem; }
  .canon .books .bk { font-size: 1.15rem; }
  .start-points { gap: .65rem; }
  .start-points a { padding: 1rem 1.2rem; }
  .resume-reading { padding: 1.2rem; gap: 1rem; }
  .resume-reading > span:last-child { max-width: 5rem; }
  .reading .listen[data-state="ready"] { padding: .65rem; border-radius: 12px; }
  .reading .listen[data-state="ready"] .quiet { display: none; }
  .reading .chapter-title { font-size: 3rem; }
  .reading .chapter-download { gap: .75rem; }
  .reading .onward { gap: 1rem; font-size: 1rem; }
}
@media (max-height: 500px) {
  .reading .listen[data-state="ready"] { position: static; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { scroll-behavior: auto !important; transition-duration: 0s !important; }
}

.reading .chapter-download { margin-top: 2rem; }
@media (max-width: 390px) {
  .player-tools { gap: .35rem; font-size: .9375rem; }
  .player-tools label { gap: .25rem; }
  .player-tools select { padding-inline: .15rem; }
}

/* Fullscreen scripture: one sharp verse, with quiet context above and below. */
html.projecting { overflow: hidden; }
.projector { position: fixed; inset: 0; width: 100vw; height: 100dvh; max-width: none; max-height: none; margin: 0; padding: 0; border: 0; background: #111310; color: #f4efe4; overflow: hidden; }
.projector::backdrop { background: #111310; }
.projector-controls { position: absolute; top: max(.75rem,env(safe-area-inset-top)); right: max(1rem,env(safe-area-inset-right)); z-index: 1; display: flex; gap: .6rem; }
.projector-controls button { display: inline-flex; align-items: center; justify-content: center; width: 48px; height: 48px; padding: 0; border: 1px solid #77796f; border-radius: 50%; background: #1d201b; color: #eeeadd; font: 400 1.8rem/1 system-ui,sans-serif; cursor: pointer; }
.projector-controls .projector-play { background: #e0a45c; border-color: #e0a45c; color: #171910; }
.projector-controls svg { width: 24px; height: 24px; }
.projector-controls button:hover { filter: brightness(1.15); }
.projector-controls button:disabled { opacity: .5; cursor: wait; }
.projector-controls button:focus-visible { outline: 2px solid #e0a45c; outline-offset: 3px; }
.projector-feedback { position: absolute; top: 3.9rem; right: 1rem; max-width: calc(100% - 2rem); margin: .5rem 0; color: #e0a45c; font: 400 .875rem/1.4 system-ui,sans-serif; text-align: right; }
.projector-verses { box-sizing: border-box; position: relative; top: 50%; transform: translateY(-50%); height: calc((100% - 6.5rem) * .6); max-width: 1400px; margin: auto; padding: 0 clamp(1.25rem,7vw,7rem); display: grid; grid-template-rows: minmax(0,1fr) minmax(0,2.8fr) minmax(0,1fr); gap: clamp(.42rem,1.8vh,1.2rem); text-align: center; }
.projector-context { margin: 0; font-size: calc(clamp(1rem,2.1vw,2rem) * var(--reading-scale,1)); line-height: 1.5; opacity: .38; filter: blur(.35px); overflow: hidden; align-content: center; }
.reading .listen[data-state="generating"] .progress,
.projector-loading .progress { position: fixed; z-index: 10; left: 50%; top: 50%; transform: translate(-50%,-50%); width: min(32rem,calc(100vw - 2rem)); pointer-events: none; }
.reading .listen[data-state="generating"] .progress .going,
.projector-loading .going { position: absolute; top: 100%; width: 100%; }
.reading .listen[data-state="generating"] .dial { background: var(--ground); border-radius: 50%; }
.reading:has(.listen[data-state="generating"]) .scripture,
.reading:has(.listen[data-state="generating"]) .scripture:hover,
.reading:has(.listen[data-state="generating"]) .scripture:focus-within,
.projector.is-preparing .projector-verses { filter: blur(3px); opacity: .35; }
.projector-loading { --ink: #f4efe4; --ink-quiet: #c5c0b5; --rule: #494b43; --ground: #111310; }
.projector-loading .dial { background: #111310; border-radius: 50%; }
.projector.is-preparing .projector-feedback { visibility: hidden; }
.projector-playback { position: relative; width: 48px; height: 48px; }
.projector-controls .projector-seek { position: absolute; inset: -6px; width: 60px; height: 60px; overflow: visible; pointer-events: none; border-radius: 50%; }
.projector-seek circle { fill: none; stroke-width: 4; pointer-events: stroke; cursor: pointer; }
.projector-seek .seek-track { stroke: #494b43; }
.projector-seek .seek-fill { stroke: #e0a45c; stroke-dasharray: 100; stroke-dashoffset: 100; transform: rotate(-90deg); transform-origin: 32px 32px; }
.projector-seek[aria-disabled="true"] { opacity: .35; }
.projector-seek:focus-visible { outline: 2px solid #f4efe4; outline-offset: 3px; }
.projector-time { box-sizing: border-box; position: absolute; top: 60px; left: 50%; transform: translateX(-50%); width: 172px; height: 30px; padding: 0 8px; display: grid; grid-template-columns: 62px 12px 1fr; align-items: center; white-space: nowrap; color: #ded9cc; background: #1d201b; border: 1px solid #575b4d; border-radius: 16px; font: 12px/1 system-ui,sans-serif; font-variant-numeric: tabular-nums; pointer-events: none; }
.timer-elapsed { text-align: right; padding-right: 4px; }
.timer-remaining { text-align: left; padding-left: 4px; }
.timer-divider { color: #e0a45c; text-align: center; }
.projector-time.timer-empty { visibility: hidden; }
.projector-current { display: flex; flex-direction: column; justify-content: center; min-height: 0; gap: .7rem; }
.projector-reference { flex: 0 0 auto; margin: 0; color: #e0a45c; font: 400 clamp(1.3125rem,1.8vw,1.65rem)/1.4 system-ui,sans-serif; letter-spacing: .06em; }
.projector-text { min-height: 0; margin: 0; font-size: calc(clamp(1.5rem,3.6vw,3.7rem) * var(--reading-scale,1)); line-height: 1.45; overflow: hidden; }
@media (max-height: 500px) {
  .projector-verses { height: calc((100% - 4rem) * .6); gap: .3rem; }
  .projector-current { gap: .25rem; }
}

/* One compact chapter row; controls keep a comfortable touch target. */
.chapter-actions { display: contents; }
.reading .chapter-chooser { flex-wrap: nowrap; gap: .65rem; margin: .75rem 0 1rem; }
.reading .chapter-chooser label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
.chapter-chooser.auto-submit > button[type="submit"] { display: none; }
.chapter-play { flex: 0 0 48px; width: 48px; height: 48px; display: inline-flex; align-items: center; justify-content: center; border: 0; border-radius: 50%; background: var(--ember); color: var(--ground); cursor: pointer; }
.chapter-play[hidden] { display: none; }
.chapter-play svg { width: 24px; height: 24px; }
.chapter-play:disabled { opacity: .5; cursor: wait; }
.chapter-play:focus-visible { outline: 2px solid var(--ember); outline-offset: 3px; }
.playback-enhanced .listen .ask { display: none; }
.listen:not([data-state="ready"]) .player-chapters { display: none; }
.playback-enhanced .listen[data-state="idle"] { margin: 0; }
.reader-settings-ready .spoken-updates { display: none; }
.reading > .projector-open { margin: 0 0 1rem; }
.reading .onward-top { margin-block: 0 .65rem; }
.reading .chapter-title { margin-block: .5rem .75rem; }
.reader-settings-open { display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; padding: 0; border: 1px solid currentColor; border-radius: 50%; background: transparent; color: inherit; font: 24px/1 system-ui,sans-serif; cursor: pointer; }
.reader-settings { box-sizing: border-box; width: 400px; max-width: calc(100vw - 24px); max-height: calc(100dvh - 24px); padding: 20px; border: 1px solid color-mix(in srgb,var(--ember) 40%,var(--rule)); border-radius: 24px; background: linear-gradient(145deg,color-mix(in srgb,var(--ember) 7%,var(--ground-lift)),var(--ground-lift) 45%); color: var(--ink); font: 16px/1.5 system-ui,sans-serif; box-shadow: 0 24px 80px rgb(0 0 0 / .35), inset 0 1px 0 color-mix(in srgb,var(--ember) 15%,transparent); }
.reader-settings::backdrop { background: rgb(0 0 0 / .55); backdrop-filter: blur(4px); }
.reader-settings header { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.reader-settings h2 { margin: 0; font: 600 20px/1.4 system-ui,sans-serif; }
.settings-eyebrow { display: block; margin-bottom: 5px; color: var(--ember); font: 600 10px/1.4 system-ui,sans-serif; letter-spacing: 1.5px; }
.reader-settings button { min-width: 44px; min-height: 44px; border: 1px solid var(--rule); border-radius: 8px; background: var(--ground); color: var(--ink); font: 16px/1 system-ui,sans-serif; cursor: pointer; }
.reader-settings .settings-close { font-size: 24px; border-radius: 50%; border-color: transparent; background: transparent; }
.settings-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 12px; margin-top: 10px; border: 1px solid var(--rule); border-radius: 16px; background: color-mix(in srgb,var(--ground) 70%,transparent); }
.settings-row > span { min-width: 0; font-size: 14px; font-weight: 500; }
.reader-settings .textsize { display: flex; align-items: center; gap: 0; padding: 3px; border: 1px solid var(--rule); border-radius: 14px; background: var(--ground); }
.reader-settings .textsize button { border-color: transparent; background: transparent; border-radius: 10px; }
.reader-settings button:hover:not(:disabled) { background: color-mix(in srgb,var(--ember) 12%,var(--ground)); }
.reader-settings button:disabled { opacity: .35; cursor: default; }
.reader-settings output { min-width: 44px; text-align: center; font-size: 14px; }
.reader-settings .settings-row small { display: block; margin-top: 4px; color: var(--ink-quiet); font: 13px/1.5 system-ui,sans-serif; }
.reader-settings label.settings-row { cursor: pointer; }
.reader-settings label.settings-row:has(input:checked) { border-color: color-mix(in srgb,var(--ember) 40%,var(--rule)); }
.reader-settings input[type="checkbox"] { appearance: none; position: relative; flex: 0 0 48px; width: 48px; height: 28px; margin: 0; border: 1px solid var(--ink-quiet); border-radius: 20px; background: var(--rule); cursor: pointer; }
.reader-settings input[type="checkbox"]::after { content: ""; position: absolute; width: 20px; height: 20px; left: 3px; top: 3px; border-radius: 50%; background: var(--ink-quiet); }
.reader-settings input[type="checkbox"]:checked { background: var(--ember); border-color: var(--ember); }
.reader-settings input[type="checkbox"]:checked::after { left: 23px; background: var(--ground-lift); }
.reader-settings input[type="checkbox"]:disabled { opacity: .4; cursor: default; }
.reader-settings.settings-projector { --ground: #181b16; --ground-lift: #22261f; --ink: #f4efe4; --ink-quiet: #bcbcaf; --rule: #42483b; --ember: #e0a45c; }
.reader-settings button:focus-visible, .reader-settings-open:focus-visible { outline: 2px solid var(--ember); outline-offset: 3px; }

.reading .chapter-title { font-size: clamp(2rem,4vw,3.25rem); line-height: 1.15; }
.reading .listen .chapter-chooser { margin: 0 0 .5rem; }
.chapter-chooser .projector-open { flex: 0 0 48px; width: 48px; height: 48px; min-height: 48px; padding: 0; font: 26px/1 system-ui,sans-serif; border-radius: 50%; }
.reading .listen[data-state="ready"] .player[hidden] { display: none; }
.player-tools:has(input[type="range"]) { gap: .7rem; margin-top: .25rem; }
.player-tools input[type="range"] { flex: 1; min-width: 0; height: 28px; margin: 0; accent-color: var(--ember); }
.playback-clock { white-space: nowrap; color: var(--ink-quiet); font: 13px/1.4 system-ui,sans-serif; font-variant-numeric: tabular-nums; }
.player-tools > label:empty { display: none; }
.reader-settings .settings-speed select { box-sizing: border-box; min-height: 44px; padding: 8px; border: 1px solid var(--rule); border-radius: 8px; background: var(--ground); color: var(--ink); font: 16px/1.4 system-ui,sans-serif; }
.anav .reader-settings-open { width: 44px; height: 44px; padding: 0; font: 24px/1 system-ui,sans-serif; }
.settings-row[hidden] { display: none; }

.chapter-chooser .projector-open svg { width: 22px; height: 22px; }
