/* ==========================================================================
   FILE: style.css — "The look"
   --------------------------------------------------------------------------
   The new Faith For You design: eggshell white, white cards with hairline
   borders, deep navy accents, a brown cross. Generous whitespace, calm,
   reverent — premium, never a chatbot.

   Palette (locked):
     eggshell background  #f8f7f3     white cards          #ffffff
     hairline borders     #e8e6df     deep navy accent     #1f2a3a
     brown cross          #7a4a2e     body text            #4a4640
     muted labels         #a89f8d

   Type:
     headings & wordmark  Cormorant Garamond (warm serif)
     Scripture text       Georgia (serif, italic)
     UI text              Source Sans 3 (clean sans)

   Motion (all GPU-friendly — transform + opacity only):
     1. Splash: cross scales in (~1.1s, ease-out), title rises at ~0.9s,
        tagline ~0.3s later, whole splash fades at ~2.4s.
     2. App cascades in with staggered rise+fade as the splash exits.
     3. A watermark cross breathes behind the content at ~5% opacity.
   index.html tags <html> with .splash-pending / .splash-skip before first
   paint; app.js advances the timeline by adding .app-enter / .is-fading /
   .is-gone. With JS off, no class is set and the page simply shows itself.
   ========================================================================== */

:root {
  /* Tells the browser which way round we are, so scrollbars, form controls
     and the space behind an overscroll follow the page instead of staying
     stubbornly light. */
  color-scheme: light;

  --bg: #f8f7f3;
  --card: #ffffff;
  --hairline: #e8e6df;
  --hairline-deep: #d8d2c3;
  --navy: #1f2a3a;
  --navy-soft: #2c3a52;
  --cross-brown: #7a4a2e;
  --ink-heading: #1f2a3a;
  --ink-body: #4a4640;
  --muted: #a89f8d;
  /* The one affirmative color, used only by a settled quiz answer. Muted on
     purpose — it sits with the parchment rather than announcing itself, and
     it has no negative counterpart: nothing in this app is marked in red. */
  --sage: #5c7355;
  --sage-tint: #f1f4ee;

  /* THE FIVE HIGHLIGHT WASHES. Sage was here first, for a settled quiz
     answer; the other four are built to its weight — same lightness, same
     low saturation, all of them things the parchment already contains
     (leaf, earth, dune, dusk, shade) rather than the yellow-pink-green of a
     highlighter pack.

     There is NO RED and there will not be one: nothing in this app is
     marked in red, and a colour someone might reach for to mean "wrong"
     does not belong on a verse.

     Each has a mid tone for the swatch and the border, and a tint for the
     wash behind the words. The tint is what a reader actually sees, so the
     five tints sit within a few points of each other in lightness — no
     colour shouts louder than another just because of which one it is. */
  --clay: #85604e;
  --sand: #7f7150;
  --sky: #4f6b80;
  --lavender: #675d80;

  /* THE FIVE HIGHLIGHT WASHES, and they are their OWN tokens for a reason.
     They used to reuse --sage-tint and friends, but --sage-tint is also the
     settled quiz answer, the saved state of a verse card, and the "Save 17%"
     chip — and the quiz's is muted ON PURPOSE, so deepening it there would
     have changed three surfaces nobody asked about.

     The first set was too faint to read as a mark: every one measured 1.11
     to 1.15 against the white card, and sage against sky was 1.02 — which is
     to say identical. A blue highlight looked like a sage one because both
     looked like nothing. These measure 1.43 to 1.56 against the card, the
     closest pair is 23 apart in RGB rather than 8, and body text still
     reads at 6:1 or better on every one of them.

     Still no red, still parchment: leaf, terracotta, dune, dusk, shade. */
  --hl-sage: #c8dcbd;
  --hl-clay: #f0c9ae;
  --hl-sand: #e9d79a;
  --hl-sky: #bfd6e8;
  --hl-lavender: #d6c9ec;

  --serif: "Cormorant Garamond", Georgia, "Times New Roman", serif;
  --scripture: Georgia, "Times New Roman", serif;
  --sans: "Source Sans 3", -apple-system, BlinkMacSystemFont, "Segoe UI",
    Roboto, sans-serif;

  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  /* CHANNELS, so a translucent tint can follow the theme. Every rgba() in
     this file is built from one of these rather than from a literal —
     otherwise a hover meant as "a little darker" stays dark on a dark
     surface and simply disappears. */
  --ink-rgb: 31, 42, 58;
  --bg-rgb: 248, 247, 243;
  --brown-rgb: 122, 74, 46;

  /* Text that sits ON a --navy surface. --navy inverts to a light tone in
     dark mode, so this has to invert with it. */
  --on-navy: #ffffff;
  --on-navy-rgb: 255, 255, 255;

  /* The one warm-red the app allows itself, and only for an error message —
     never for a mark on a verse. */
  --error-bg: #fdf9f4;
  --error-line: #ecdfd2;
  --error-ink: #8a4b32;

  --shadow-card: 0 1px 2px rgba(var(--ink-rgb), 0.04),
    0 10px 30px rgba(var(--ink-rgb), 0.05);
  --shadow-card-hover: 0 1px 2px rgba(var(--ink-rgb), 0.05),
    0 14px 40px rgba(var(--ink-rgb), 0.07);
}

/* ==========================================================================
   DARK MODE — the same palette, inverted, and nothing else
   --------------------------------------------------------------------------
   THE USE CASE IS A PHONE, ONE-HANDED, AT NIGHT. Parchment at full
   brightness in a dark room is a face full of light.

   This is NOT a second design language. Every value below is the same TOKEN
   the light theme uses, given its counterpart: the card still sits above the
   background, the hairline still separates them, the muted label is still
   the quietest thing on the page. Nothing was restyled — only re-coloured —
   which is why no rule outside this block mentions a theme.

   NO PURE BLACK AND NO PURE WHITE. The parchment palette is warm on both
   sides of the line: a warm near-black (#14120e) under a soft off-white
   (#f2efe6), the same way #f8f7f3 was never #ffffff.

   --navy INVERTS FROM DARK TO LIGHT. It is the emphasis surface — primary
   buttons, the active translation, the active collection chip — so in dark
   it becomes the light one, and --on-navy carries the text that sits on it.
   That is why those two are a pair and why every rgba() in this file is
   built from a channel token rather than a literal.

   THREE STATES, and the order matters. :root is light. The media block
   covers "follow the system", and is written :not([data-theme="light"]) so
   an explicit light choice still wins under a dark system. The last block
   covers an explicit dark choice under a light system. Between them every
   combination of system setting and stored preference lands somewhere.
   ========================================================================== */

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    --bg: #14120e;
    --card: #1e1b16;
    --hairline: #2f2b23;
    --hairline-deep: #423d33;

    /* The emphasis surface, now the light one. */
    --navy: #e9e5da;
    --navy-soft: #d3cec1;
    --on-navy: #14120e;
    --on-navy-rgb: 20, 18, 14;

    --cross-brown: #c1906c;
    --ink-heading: #f2efe6;
    --ink-body: #ddd7c9;
    --muted: #948c7c;

    --ink-rgb: 242, 239, 230;
    --bg-rgb: 20, 18, 14;
    --brown-rgb: 193, 144, 108;

    /* The five washes, rebuilt as DARKER-than-card rather than lighter, so a
       highlight still reads as something laid over the words rather than as
       a hole cut in the page. Same five hues, same relative order. */
    --sage: #9db394;
    --sage-tint: #242b20;
    --clay: #c09a84;
    --sand: #bdae86;
    --sky: #8fb0c6;
    --lavender: #a99cc4;

    /* Lighter than the card rather than darker, so a mark still reads as
       something laid OVER the words. 1.46 to 1.77 against the card, against
       1.09 to 1.18 before; text on them 6.8:1 or better. */
    --hl-sage: #38492f;
    --hl-clay: #573624;
    --hl-sand: #474319;
    --hl-sky: #264357;
    --hl-lavender: #3d3159;

    --error-bg: #2a1f18;
    --error-line: #45322a;
    --error-ink: #e2a58a;

    /* A shadow cannot be seen against a dark ground the way it is against a
       light one, so it does more of its work with depth and less with
       spread. */
    --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.35),
      0 10px 30px rgba(0, 0, 0, 0.32);
    --shadow-card-hover: 0 1px 2px rgba(0, 0, 0, 0.4),
      0 14px 40px rgba(0, 0, 0, 0.42);
  }
}

/* Chosen dark, whatever the system says. Same values — kept as one list
   rather than two so the two states cannot drift apart. */
:root[data-theme="dark"] {
  color-scheme: dark;

  --bg: #14120e;
  --card: #1e1b16;
  --hairline: #2f2b23;
  --hairline-deep: #423d33;

  --navy: #e9e5da;
  --navy-soft: #d3cec1;
  --on-navy: #14120e;
  --on-navy-rgb: 20, 18, 14;

  --cross-brown: #c1906c;
  --ink-heading: #f2efe6;
  --ink-body: #ddd7c9;
  --muted: #948c7c;

  --ink-rgb: 242, 239, 230;
  --bg-rgb: 20, 18, 14;
  --brown-rgb: 193, 144, 108;

  --sage: #9db394;
  --sage-tint: #242b20;
  --clay: #c09a84;
  --sand: #bdae86;
  --sky: #8fb0c6;
  --lavender: #a99cc4;

  --hl-sage: #38492f;
  --hl-clay: #573624;
  --hl-sand: #474319;
  --hl-sky: #264357;
  --hl-lavender: #3d3159;

  --error-bg: #2a1f18;
  --error-line: #45322a;
  --error-ink: #e2a58a;

  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.35),
    0 10px 30px rgba(0, 0, 0, 0.32);
  --shadow-card-hover: 0 1px 2px rgba(0, 0, 0, 0.4),
    0 14px 40px rgba(0, 0, 0, 0.42);
}


/* ----- base --------------------------------------------------------------- */

* {
  box-sizing: border-box;
}

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

/* No scrollbar flash while the splash holds the stage. */
html.splash-pending:not(.app-enter) {
  overflow: hidden;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink-body);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

::selection {
  background: rgba(var(--ink-rgb), 0.12);
}

.is-hidden {
  display: none !important;
}

/* Visually hidden, still read by screen readers (input label). */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

button {
  font-family: inherit;
}

a:focus-visible,
button:focus-visible,
textarea:focus-visible,
input:focus-visible,
select:focus-visible {
  outline: 2px solid rgba(var(--ink-rgb), 0.45);
  outline-offset: 2px;
}

/* ==========================================================================
   LAUNCH SPLASH
   ========================================================================== */

#splash {
  display: none; /* only shown when the head script says so */
  position: fixed;
  inset: 0;
  z-index: 60;
  background: var(--bg);
  align-items: center;
  justify-content: center;
  transition: opacity 0.65s ease;
}

html.splash-pending #splash {
  display: flex;
}

html.splash-pending #splash.is-fading {
  opacity: 0;
  pointer-events: none;
}

html.splash-pending #splash.is-gone {
  display: none;
}

.splash-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 0 24px;
  /* Optical centering: sit a touch above true center. */
  transform: translateY(-4vh);
}

/* 1) The cross: small + faint -> full, smooth ease-out (~1.1s). */
.splash-cross {
  width: 84px;
  height: auto;
  color: var(--cross-brown);
  transform-origin: 50% 50%;
  animation: crossIn 1.1s var(--ease-out) both;
}

@keyframes crossIn {
  from {
    transform: scale(0.55);
    opacity: 0.12;
  }
  to {
    transform: scale(1);
    opacity: 1;
  }
}

/* 2) The name rises at ~0.9s, the tagline ~0.3s later. */
.splash-title {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 2.15rem;
  letter-spacing: 0.01em;
  color: var(--ink-heading);
  margin: 28px 0 0;
  animation: riseIn 0.85s var(--ease-out) 0.9s both;
}

.splash-tagline {
  font-size: 0.95rem;
  color: var(--muted);
  margin: 10px 0 0;
  animation: riseIn 0.8s var(--ease-out) 1.2s both;
}

@keyframes riseIn {
  from {
    opacity: 0;
    transform: translateY(16px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* ==========================================================================
   APP ENTRANCE — staggered cascade, triggered as the splash fades
   ========================================================================== */

/* While the splash is on stage, the app waits unseen… */
html.splash-pending .cascade {
  opacity: 0;
}

/* …then each piece rises into place, slightly after the one before. */
html.splash-pending.app-enter .cascade {
  animation: riseIn 0.75s var(--ease-out) both;
}

html.splash-pending.app-enter .cascade-1 { animation-delay: 0.02s; }
html.splash-pending.app-enter .cascade-2 { animation-delay: 0.1s; }
html.splash-pending.app-enter .cascade-3 { animation-delay: 0.18s; }
html.splash-pending.app-enter .cascade-4 { animation-delay: 0.28s; }
html.splash-pending.app-enter .cascade-5 { animation-delay: 0.4s; }

/* Returning within the session: no splash, just a quick quiet fade. */
html.splash-skip .app-shell {
  animation: quickIn 0.35s ease both;
}

@keyframes quickIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* ==========================================================================
   WATERMARK CROSS — behind everything, ~5% opacity, slow breathe
   ========================================================================== */

.watermark {
  position: fixed;
  inset: 0;
  z-index: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  color: var(--cross-brown);
  opacity: 0.05;
}

.watermark svg {
  width: min(440px, 70vw);
  height: auto;
  animation: breathe 9s ease-in-out infinite alternate;
}

@keyframes breathe {
  from { transform: scale(1); }
  to { transform: scale(1.035); }
}

/* ==========================================================================
   ASK-PAGE AMBIENT SCENE — one still photo, slow CSS-only zoom
   --------------------------------------------------------------------------
   Proof of concept for a clock-aligned scene rotation, not built yet — ONE
   scene, Ask page only. A still photo with transform: scale over 90s, no
   video file. Same shape as .watermark above (fixed, pointer-events:none,
   very low opacity) but scoped one level deeper — inside #page-ask in the
   markup, not the whole shell — so #page-ask[hidden] removes it on every
   other page the same way it removes everything else there.

   z-index: -1, not 0. .watermark can use z-index:0 because .app-shell is
   ALSO explicitly positioned with z-index:1 above it — two positioned
   siblings, compared directly. .hero and #ask-slot are plain, unpositioned
   flow content; a positioned sibling at z-index:0 would paint OVER them,
   not under. Negative z-index paints behind normal flow content
   unconditionally, so nothing else on the page needs touching for this. */
.ask-bg {
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
  opacity: 0.1;
}

/* The cross watermark and this photo are both full-bleed, centered, very
   low opacity — together they show as a pale cross-shaped smear over the
   water rather than reading as one clean scene. One ambient layer at a
   time: while Ask is the visible page, its own photo replaces the
   watermark rather than sitting on top of it. #page-ask carries no
   [hidden] attribute in the markup (it's the default page), so this also
   holds correctly before app.js's showPage() ever runs. */
body:has(#page-ask:not([hidden])) .watermark {
  display: none;
}

.ask-bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  animation: askBgZoom 90s ease-in-out infinite alternate;
}

/* Scaling UP from 1 — the image already covers its box at scale(1)
   (object-fit: cover), so growing only ever shows MORE of the photo,
   never a gap at the edge. */
@keyframes askBgZoom {
  from { transform: scale(1); }
  to { transform: scale(1.06); }
}

/* Content always sits above the watermark. */
.app-shell {
  position: relative;
  z-index: 1;
}

/* ==========================================================================
   TOP BAR
   ========================================================================== */

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  max-width: 1060px;
  margin: 0 auto;
  padding: 22px 28px 16px;
}

.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1.45rem;
  letter-spacing: 0.01em;
  color: var(--ink-heading);
}

.wordmark svg {
  width: 13px;
  height: auto;
  color: var(--cross-brown);
}

.topbar-actions {
  display: flex;
  align-items: center;
  gap: 12px;
}

/* ----- topbar page nav: Ask · Conversations · Learning --------------------
   Same tokens as the sidebar's .p-mode items, laid out horizontally, so the
   two navs read as one system. Conversations carries [hidden] until the tier
   allows it — removed, not disabled. */

.topbar-nav {
  display: flex;
  align-items: center;
  gap: 4px;
}

.tb-nav {
  border: 0;
  background: transparent;
  border-radius: 11px;
  padding: 8px 14px;
  cursor: pointer;
  color: var(--ink-body);
  font-family: var(--sans);
  font-size: 0.95rem;
  font-weight: 600;
  transition: background 0.16s ease, color 0.16s ease;
}

.tb-nav:hover {
  background: rgba(var(--ink-rgb), 0.05);
}

.tb-nav.is-active {
  background: rgba(var(--ink-rgb), 0.07);
  color: var(--ink-heading);
}

.tb-nav[hidden] {
  display: none;
}

/* The two full-width pages inside the shell. Exactly one is ever shown. */
.page[hidden] {
  display: none;
}

@media (max-width: 620px) {
  .topbar {
    gap: 8px;
    padding-left: 16px;
    padding-right: 16px;
  }
  .tb-nav {
    padding: 8px 10px;
    font-size: 0.9rem;
  }
}

.account-dot {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid var(--hairline);
  background: var(--card);
  color: var(--navy);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.account-dot:hover {
  border-color: var(--hairline-deep);
  box-shadow: var(--shadow-card);
}

.account-dot svg {
  width: 17px;
  height: 17px;
}

/* ==========================================================================
   MAIN LAYOUT
   ========================================================================== */

main {
  max-width: 720px;
  margin: 0 auto;
  padding: 0 20px;
}

/* ----- hero --------------------------------------------------------------- */

.hero {
  text-align: center;
  margin: 54px 0 30px;
}

.eyebrow {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 14px;
}

.hero-title {
  font-family: var(--serif);
  font-weight: 600;
  font-size: clamp(2.1rem, 6vw, 3rem);
  line-height: 1.15;
  color: var(--ink-heading);
  margin: 0;
}

/* ----- cards -------------------------------------------------------------- */

.card {
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 16px;
  box-shadow: var(--shadow-card);
}

/* ----- the ask card ------------------------------------------------------- */

.ask {
  max-width: 640px;
  margin: 0 auto;
  padding: 20px 22px 16px;
  transition: border-color 0.25s ease, box-shadow 0.25s ease;
}

.ask:focus-within {
  border-color: var(--hairline-deep);
  box-shadow: var(--shadow-card-hover);
}

.ask textarea {
  display: block;
  width: 100%;
  min-height: 58px;
  border: 0;
  outline: none;
  resize: none;
  background: transparent;
  font-family: var(--sans);
  font-size: 1.06rem;
  line-height: 1.6;
  color: var(--ink-heading);
  padding: 4px 2px 2px;
}

.ask textarea::placeholder {
  color: var(--muted);
}

.ask-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  border-top: 1px solid var(--hairline);
  margin-top: 12px;
  padding-top: 14px;
}

/* Keep "Seek guidance" hard-right even if the row wraps on a tiny screen. */
.ask-meta .primary {
  margin-left: auto;
}

/* Translation picker — a native <select> dressed to match the card: muted
   sans label color, hairline pill, custom chevron. WEB / KJV / ASV only
   (ESV stays link-out on the Scripture cards). */
.translation-select {
  appearance: none;
  -webkit-appearance: none;
  font-family: var(--sans);
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--muted);
  background-color: var(--card);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23a89f8d' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 12px;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  padding: 8px 32px 8px 15px;
  max-width: 100%;
  cursor: pointer;
  transition: border-color 0.18s ease, color 0.18s ease;
}

.translation-select:hover {
  border-color: var(--hairline-deep);
  color: var(--ink-body);
}

.translation-select option {
  color: var(--ink-body);
}

/* ----- buttons ------------------------------------------------------------ */

button.primary {
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--on-navy);
  background: var(--navy);
  border: 1px solid var(--navy);
  border-radius: 999px;
  padding: 11px 24px;
  cursor: pointer;
  transition: background 0.2s ease, transform 0.15s ease, opacity 0.2s ease;
}

button.primary:hover {
  background: var(--navy-soft);
}

button.primary:active {
  transform: translateY(1px);
}

button.primary:disabled {
  opacity: 0.55;
  cursor: default;
}

.link-btn {
  background: none;
  border: none;
  padding: 0;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--navy);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
  opacity: 0.8;
  transition: opacity 0.2s ease;
}

.link-btn:hover {
  opacity: 1;
}

/* ==========================================================================
   RESULTS
   ========================================================================== */

.results {
  max-width: 640px;
  margin: 0 auto;
}

.section-label {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 34px 4px 12px;
}

/* The warm guidance card. */
.word-card {
  padding: 24px 26px;
}

.word-card p {
  margin: 0;
  font-size: 1.04rem;
  line-height: 1.8;
  color: var(--ink-body);
}

/* Scripture cards — the reference leads, WEB tag beside it, the verse in
   serif italic, and a quiet link out to the ESV. */
.verse-card {
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 16px;
  box-shadow: var(--shadow-card);
  padding: 20px 24px 18px;
  margin-bottom: 14px;
}

.verse-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
}

.verse-ref {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1.18rem;
  color: var(--ink-heading);
  margin: 0;
}

.verse-translation {
  flex-shrink: 0;
  font-size: 0.64rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  padding: 4px 10px;
}

.verse-text {
  font-family: var(--scripture);
  font-style: italic;
  font-size: 1.02rem;
  line-height: 1.78;
  color: var(--ink-body);
  margin: 0 0 12px;
}

.verse-missing {
  font-size: 0.92rem;
  color: var(--muted);
  margin: 0 0 12px;
}

.verse-esv-link {
  display: inline-block;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--navy);
  text-decoration: none;
  opacity: 0.72;
  transition: opacity 0.2s ease;
}

.verse-esv-link:hover {
  opacity: 1;
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* The card's foot: the ESV link keeps its place on the left, the save action
   sits opposite it. Wraps rather than crushes on a narrow phone. */
.verse-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
}

/* Save a verse straight from an answer — the same list the reader's sidebar
   shows. Sized as a quiet action, not a call to action: the answer is the
   point of the card and this sits beside it. */
.verse-save {
  flex: 0 0 auto;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 0.8rem;
  color: var(--navy);
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  padding: 6px 14px;
  cursor: pointer;
  transition: border-color 0.18s ease, box-shadow 0.2s ease, color 0.2s ease;
}

.verse-save:hover:not(:disabled) {
  border-color: var(--hairline-deep);
  box-shadow: var(--shadow-card);
}

/* Settled. Same token the reader uses for a marked verse, so "kept" looks
   the same wherever it is seen. */
.verse-save.is-saved {
  background: var(--sage-tint);
  border-color: var(--sage);
  color: var(--sage);
  cursor: default;
}

.verse-save:disabled { opacity: 0.6; }

.verse-save-note {
  font-size: 0.82rem;
  color: var(--muted);
  margin: 10px 0 0;
}

.verse-save-note[hidden] { display: none; }

.attribution {
  font-size: 0.78rem;
  color: var(--muted);
  margin: 6px 4px 0;
}

/* Loading + error states around the engine call. */
.status {
  font-family: var(--scripture);
  font-style: italic;
  color: var(--muted);
  text-align: center;
  margin: 30px 0 0;
  animation: statusPulse 1.6s ease-in-out infinite alternate;
}

@keyframes statusPulse {
  from { opacity: 0.55; }
  to { opacity: 1; }
}

.error-card {
  background: var(--error-bg);
  border: 1px solid var(--error-line);
  border-radius: 14px;
  color: var(--error-ink);
  font-size: 0.95rem;
  padding: 16px 18px;
  margin-top: 30px;
}

/* A gentle notice (e.g. daily limit reached) — calm, not alarming. */
.notice-card {
  background: var(--card);
  border: 1px solid var(--hairline);
  border-left: 3px solid var(--navy);
  border-radius: 14px;
  color: var(--ink-body);
  font-size: 0.97rem;
  line-height: 1.7;
  padding: 18px 20px;
  margin-top: 30px;
}

/* Each new answer rises in gently. */
.fade-in {
  animation: riseIn 0.6s var(--ease-out) both;
}

/* ----- crisis ------------------------------------------------------------- */
/* Calm but unmistakable: white card, navy top accent, resource chips. The
   message text itself comes from the engine, exactly as returned. */

.crisis-card {
  background: var(--card);
  border: 1px solid var(--hairline);
  border-top: 3px solid var(--navy);
  border-radius: 16px;
  box-shadow: var(--shadow-card);
  padding: 26px 28px;
  margin-top: 34px;
}

.crisis-card h2 {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1.5rem;
  color: var(--ink-heading);
  margin: 0 0 12px;
}

.crisis-message {
  margin: 0;
  font-size: 1rem;
  line-height: 1.8;
  color: var(--ink-body);
}

.crisis-resources {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 16px;
}

.crisis-chip {
  display: inline-flex;
  align-items: center;
  font-size: 0.85rem;
  color: var(--ink-heading);
  background: var(--bg);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  padding: 8px 14px;
}

/* ----- Dead Sea Scrolls context (renderer preserved) ---------------------- */

.scroll-card {
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 16px;
  box-shadow: var(--shadow-card);
  padding: 20px 24px;
  margin-bottom: 14px;
}

.scroll-title {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1.15rem;
  color: var(--ink-heading);
  margin: 0 0 8px;
}

.scroll-text {
  font-size: 0.98rem;
  line-height: 1.75;
  margin: 0;
}

.scroll-connection {
  border-top: 1px solid var(--hairline);
  margin: 14px 0 0;
  padding-top: 12px;
  font-size: 0.95rem;
}

.connection-label {
  display: inline-block;
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  margin-right: 10px;
}

.read-alongside {
  font-size: 0.85rem;
  color: var(--muted);
  margin: 8px 4px 0;
}

/* ==========================================================================
   ACCOUNTS UI (sign-in required whenever Supabase accounts are enabled)
   ========================================================================== */

.account-bar {
  max-width: 640px;
  margin: 0 auto 6px;
  padding: 0 4px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  font-size: 0.85rem;
  color: var(--muted);
}

.auth-card {
  max-width: 430px;
  margin: 44px auto 0;
  padding: 34px 30px 26px;
  text-align: left;
}

.auth-mark {
  color: var(--cross-brown);
  margin-bottom: 18px;
}

.auth-mark svg {
  width: 22px;
  height: auto;
}

.auth-title {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1.6rem;
  color: var(--ink-heading);
  margin: 0 0 10px;
}

.auth-intro {
  font-size: 0.95rem;
  margin: 0 0 16px;
}

/* Small safety note under the sign-in form — crisis help never needs
   an account, and the wall must never hide that. */
.auth-safety {
  font-size: 0.82rem;
  color: var(--muted);
  border-top: 1px solid var(--hairline);
  margin: 20px 0 0;
  padding-top: 14px;
}

.auth-label {
  display: block;
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 12px 0 6px;
}

#auth-form input {
  width: 100%;
  font: inherit;
  font-size: 0.98rem;
  color: var(--ink-heading);
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 10px;
  padding: 10px 12px;
  transition: border-color 0.2s ease;
}

#auth-form input::placeholder {
  color: var(--muted);
}

#auth-form input:focus {
  outline: none;
  border-color: var(--hairline-deep);
}

.auth-message {
  min-height: 1.2em;
  font-size: 0.88rem;
  color: var(--ink-body);
  margin-top: 10px;
}

.auth-message.is-error {
  color: var(--error-ink);
}

.auth-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 14px;
}

/* ----- welcome screen (post-verification onboarding) ---------------------
   Reuses .auth-card, so the frame, the brown cross and the serif heading are
   already the app's. These rules only cover what the sign-in form does not
   have: a two-up name row, a select, and the quiet hint lines. */

#welcome-form input,
#welcome-form select,
#welcome-form textarea {
  width: 100%;
  font: inherit;
  font-size: 0.98rem;
  color: var(--ink-heading);
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 10px;
  padding: 10px 12px;
  transition: border-color 0.2s ease;
}

#welcome-form input::placeholder,
#welcome-form textarea::placeholder {
  color: var(--muted);
}

#welcome-form input:focus,
#welcome-form select:focus,
#welcome-form textarea:focus {
  outline: none;
  border-color: var(--hairline-deep);
}

#welcome-form textarea {
  resize: vertical;
  min-height: 72px;
  line-height: 1.55;
}

/* First and last name sit side by side, stacking on narrow screens. */
.welcome-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

.welcome-field {
  min-width: 0;
}

/* The label's own margin already spaces the row; drop the doubled top gap
   on the two fields inside it. */
.welcome-field .auth-label {
  margin-top: 0;
}

/* Native arrow removed for a chevron that matches the hairline palette. */
.welcome-select {
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%23a89f8d' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 11px;
  padding-right: 36px;
  cursor: pointer;
}

/* The 13+ rule and the "only used to improve the app" line. */
.welcome-hint {
  font-size: 0.8rem;
  color: var(--muted);
  margin: 7px 0 0;
}

.welcome-optional {
  margin-left: 6px;
  font-weight: 400;
  letter-spacing: 0.04em;
  text-transform: none;
  opacity: 0.75;
}

@media (max-width: 480px) {
  .welcome-row {
    grid-template-columns: 1fr;
    gap: 0;
  }
  .welcome-field + .welcome-field .auth-label {
    margin-top: 12px;
  }
}

/* ==========================================================================
   FOOTER
   ========================================================================== */

footer {
  max-width: 640px;
  margin: 70px auto 44px;
  padding: 22px 20px 0;
  border-top: 1px solid var(--hairline);
  text-align: center;
  font-size: 0.84rem;
  color: var(--muted);
}

footer p {
  margin: 0 0 8px;
}

footer strong {
  color: var(--ink-body);
}

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */

@media (max-width: 560px) {
  .topbar {
    padding: 16px 16px 10px;
  }
  .wordmark {
    font-size: 1.25rem;
  }
  .account-dot {
    width: 34px;
    height: 34px;
  }
  main {
    padding: 0 14px;
  }
  .hero {
    margin: 38px 0 24px;
  }
  .ask {
    padding: 16px 16px 12px;
  }
  .ask-meta {
    gap: 10px;
  }
  .translation-select {
    font-size: 0.76rem;
    padding: 7px 28px 7px 12px;
  }
  button.primary {
    padding: 10px 18px;
    font-size: 0.9rem;
  }
  .word-card {
    padding: 20px;
  }
  .verse-card {
    padding: 18px 18px 16px;
  }
  .crisis-card {
    padding: 22px 20px;
  }
  .auth-card {
    padding: 24px 20px 20px;
  }
  .splash-cross {
    width: 70px;
  }
  .splash-title {
    font-size: 1.75rem;
  }
  .watermark svg {
    width: 78vw;
  }
}

/* ==========================================================================
   REDUCED MOTION — honor the visitor's preference; everything settles
   instantly, and the watermark and the Ask-page photo hold still.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  .splash-cross,
  .splash-title,
  .splash-tagline,
  html.splash-pending.app-enter .cascade,
  html.splash-skip .app-shell,
  .fade-in,
  .status {
    animation-duration: 0.01ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
  }
  .watermark svg {
    animation: none;
  }
  /* Static image, no zoom — the photo itself still shows. */
  .ask-bg img {
    animation: none;
  }
  #splash {
    transition-duration: 0.01ms;
  }
}

/* ==========================================================================
   PREMIUM VIEW (Commit 2) — collapsible sidebar + 3-mode layout
   --------------------------------------------------------------------------
   Same locked palette as the free page. Single mode hosts the live #ask-slot
   (moved in by app.js); Conversation and Learning are static coming-soon
   screens. Desktop: the sidebar collapses to an icon rail. Mobile: it
   becomes an off-canvas drawer with a backdrop.
   ========================================================================== */

#premium-view {
  display: flex;
  min-height: 100vh;
  min-height: 100dvh;
}

/* ----- sidebar ------------------------------------------------------------ */

.p-sidebar {
  display: flex;
  flex-direction: column;
  flex: 0 0 268px;
  width: 268px;
  padding: 18px 14px 14px;
  background: var(--card);
  border-right: 1px solid var(--hairline);
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100dvh;
  transition: width 0.28s var(--ease-out), flex-basis 0.28s var(--ease-out);
  z-index: 2;
}

.p-side-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 4px 6px 0;
  margin-bottom: 16px;
}

.p-wordmark {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  text-decoration: none;
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1.22rem;
  color: var(--ink-heading);
  white-space: nowrap;
  overflow: hidden;
}

.p-wordmark-cross {
  width: 12px;
  height: auto;
  color: var(--cross-brown);
  flex-shrink: 0;
}

.p-icon-btn {
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  border-radius: 9px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--navy);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 0.18s ease, border-color 0.18s ease;
}

.p-icon-btn:hover {
  background: var(--bg);
  border-color: var(--hairline);
}

.p-icon-btn svg {
  width: 19px;
  height: 19px;
}

/* modes (no tier switch above them — the tier is set server-side) */
.p-modes {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 0 2px;
  margin-top: 18px;
}

.p-mode {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  border: 0;
  background: transparent;
  border-radius: 11px;
  padding: 10px 12px;
  cursor: pointer;
  color: var(--ink-body);
  font-family: var(--sans);
  font-size: 0.95rem;
  font-weight: 600;
  text-align: left;
  transition: background 0.16s ease;
}

.p-mode:hover {
  background: var(--bg);
}

.p-mode.is-active {
  background: rgba(var(--ink-rgb), 0.07);
  color: var(--ink-heading);
}

.p-mode-icon {
  width: 19px;
  height: 19px;
  flex-shrink: 0;
  color: var(--navy);
  opacity: 0.82;
}

.p-mode.is-active .p-mode-icon {
  opacity: 1;
}

.p-label {
  flex: 1;
  white-space: nowrap;
}

.p-mode-tag {
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--navy);
  background: rgba(var(--ink-rgb), 0.08);
  border-radius: 999px;
  padding: 3px 7px;
}

.p-mode-tag.muted {
  color: var(--muted);
  background: var(--bg);
  border: 1px solid var(--hairline);
}

/* context-aware lower section (placeholders only) */
.p-context {
  margin-top: 16px;
  padding: 0 6px;
}

.p-ctx-block {
  border-top: 1px solid var(--hairline);
  padding-top: 16px;
}

/* The Learning progress panel still lists the deleted mockup courses
   (Foundations / The Gospels / Prayer). Hidden until real progress
   tracking exists — the id rule outranks the is-hidden toggling in
   setPremiumMode(), so no JS changes. */
#ctx-learning { display: none; }

.p-ctx-label {
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 6px 12px;
}

.p-ghost-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 6px;
}

.p-ghost-dot {
  width: 22px;
  height: 22px;
  border-radius: 7px;
  background: var(--bg);
  border: 1px solid var(--hairline);
  flex-shrink: 0;
}

.p-ghost-line {
  height: 9px;
  border-radius: 5px;
  background: linear-gradient(90deg, var(--hairline-deep), var(--hairline));
}

.p-ghost-line.w70 { width: 70%; }
.p-ghost-line.w60 { width: 60%; }
.p-ghost-line.w50 { width: 50%; }

.p-ctx-foot {
  font-size: 0.72rem;
  font-style: italic;
  color: var(--muted);
  margin: 10px 6px 0;
}

.p-progress {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 2px 6px;
}

.p-progress-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.p-progress-name {
  font-size: 0.8rem;
  color: var(--ink-body);
  width: 82px;
  flex-shrink: 0;
}

.p-progress-track {
  flex: 1;
  height: 6px;
  border-radius: 999px;
  background: var(--bg);
  border: 1px solid var(--hairline);
  overflow: hidden;
}

.p-progress-fill {
  display: block;
  height: 100%;
  background: var(--navy);
  border-radius: 999px;
}

/* account placeholder — pinned bottom */
.p-account {
  margin-top: auto;
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  border: 0;
  border-top: 1px solid var(--hairline);
  background: transparent;
  padding: 14px 8px 4px;
  cursor: pointer;
  text-align: left;
  color: var(--ink-body);
  transition: color 0.18s ease;
}

.p-account:hover {
  color: var(--ink-heading);
}

.p-avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 1px solid var(--hairline);
  background: var(--bg);
  color: var(--navy);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.p-avatar svg { width: 16px; height: 16px; }

.p-account-text {
  display: flex;
  flex-direction: column;
  line-height: 1.25;
  overflow: hidden;
}

.p-account-name {
  font-size: 0.86rem;
  font-weight: 600;
  white-space: nowrap;
}

.p-account-sub {
  font-size: 0.72rem;
  color: var(--muted);
  white-space: nowrap;
}

/* ----- main area ---------------------------------------------------------- */

.p-main {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.p-main-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 24px;
  border-bottom: 1px solid var(--hairline);
  position: sticky;
  top: 0;
  background: rgba(var(--bg-rgb), 0.86);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  z-index: 3;
}

.p-hamburger { display: none; }

.p-main-title {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1.15rem;
  color: var(--ink-heading);
}

.p-scroll { flex: 1 1 auto; }

.p-panel[hidden] { display: none; }

.p-panel-inner {
  max-width: 680px;
  margin: 0 auto;
  padding: 42px 24px 90px;
}

.p-panel-title {
  font-family: var(--serif);
  font-weight: 600;
  font-size: clamp(1.9rem, 4.5vw, 2.6rem);
  line-height: 1.15;
  color: var(--ink-heading);
  margin: 6px 0 0;
}

.p-panel-lede {
  color: var(--ink-body);
  font-size: 1.02rem;
  line-height: 1.7;
  margin: 12px 0 0;
  max-width: 54ch;
}

/* Single mode: the moved #ask-slot sits just beneath the header. */
#premium-single-mount { margin-top: 24px; }

/* ----- coming-soon panels (Conversation, Learning) ----------------------- */

.p-coming-badge {
  display: inline-block;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--cross-brown);
  background: rgba(var(--brown-rgb), 0.08);
  border: 1px solid rgba(var(--brown-rgb), 0.18);
  border-radius: 999px;
  padding: 5px 12px;
}

.p-coming .p-panel-title { margin-top: 12px; }

.p-preview-counter {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 22px;
  padding: 9px 14px;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  background: var(--card);
  font-size: 0.85rem;
  color: var(--muted);
}

.p-dots {
  display: inline-flex;
  gap: 5px;
}

.p-dots i {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--hairline);
}

.p-dots i.on { background: var(--navy); }

/* Decorative composer — visibly inactive, sends nothing, calls nothing. */
.p-mock-composer {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 22px;
  padding: 16px 18px;
  border: 1px solid var(--hairline);
  border-radius: 16px;
  background: var(--card);
  box-shadow: var(--shadow-card);
  opacity: 0.72;
  pointer-events: none;
  user-select: none;
}

.p-mock-text {
  flex: 1;
  color: var(--muted);
  font-size: 1rem;
}

.p-mock-send {
  width: 38px;
  height: 38px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--navy);
  color: var(--on-navy);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  opacity: 0.5;
}

.p-mock-send svg { width: 18px; height: 18px; }

.p-mock-lock {
  position: absolute;
  top: -11px;
  left: 18px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
  background: var(--bg);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  padding: 3px 10px;
}

.p-mock-lock svg { width: 13px; height: 13px; }

.p-coming-note {
  margin-top: 26px;
  font-size: 0.92rem;
  color: var(--muted);
}

.link-inline {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  font-weight: 600;
  color: var(--navy);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* Learning: level selector + course cards (live — wired by initLearning) */
/* ----- learning header ---------------------------------------------------- */

.learn-head {
  display: flex;
  align-items: center;
  gap: 14px;
}

.learn-cross {
  width: 22px;
  height: 29px;
  flex-shrink: 0;
  color: var(--cross-brown);
}

/* ----- shelves ------------------------------------------------------------
   Three rows, one per level, all on screen at once — Starter, Growing, Deep,
   top to bottom. No tabs and no filtering: every course is always visible,
   and each rail scrolls sideways on its own. */

.shelf {
  margin-top: 34px;
}

.shelf-head {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.shelf-name {
  font-family: var(--serif);
  font-size: 1.3rem;
  font-weight: 600;
  color: var(--ink-heading);
  margin: 0;
}

.shelf-desc {
  font-size: 0.86rem;
  color: var(--muted);
  margin: 0;
}

.shelf-rail {
  display: flex;
  gap: 12px;
  margin-top: 14px;
  /* Padding so the hover lift and focus ring aren't clipped by the scroller. */
  padding: 4px 4px 10px;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}

.shelf-rail > * {
  scroll-snap-align: start;
}

.shelf-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  flex: 0 0 232px;
  width: 232px;
  min-height: 178px;
  padding: 16px;
  border: 1px solid var(--hairline);
  border-radius: 14px;
  background: var(--card);
  box-shadow: var(--shadow-card);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.18s ease, box-shadow 0.2s ease,
    transform 0.15s ease;
}

.shelf-card:hover {
  border-color: var(--hairline-deep);
  box-shadow: var(--shadow-card-hover);
}

.shelf-card:active { transform: translateY(1px); }

.shelf-card-icon {
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  border-radius: 10px;
  background: var(--bg);
  border: 1px solid var(--hairline);
  color: var(--navy);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.shelf-card-icon svg { width: 17px; height: 17px; }

.shelf-card-title {
  font-weight: 600;
  color: var(--ink-heading);
  font-size: 0.96rem;
  line-height: 1.3;
}

.shelf-card-meta {
  font-size: 0.78rem;
  color: var(--muted);
}

/* Pinned to the bottom of the card so prices line up across a row whatever
   the title wraps to. */
.shelf-card-price {
  margin-top: auto;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 0.9rem;
  color: var(--navy);
}

/* End-of-row placeholder. A plain div, not a button: nothing to click. */
.shelf-more {
  align-items: center;
  justify-content: center;
  border-style: dashed;
  background: transparent;
  box-shadow: none;
  cursor: default;
}

.shelf-more-text {
  font-size: 0.86rem;
  color: var(--muted);
}

@media (max-width: 620px) {
  .shelf-card {
    flex-basis: 202px;
    width: 202px;
  }
}

/* ----- course detail page -------------------------------------------------
   Subview 2, between the shelves and the reader. Everything on it comes from
   GET /api/course-preview, which is titles-only — no unit content reaches
   here, and nothing below would render it if it did. */

.course-detail {
  max-width: 760px;
  margin: 0 auto;
  padding: 42px 24px 90px;
}

.detail-level {
  font-family: var(--sans);
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 6px;
}

#detail-title { outline: none; }

.detail-facts {
  font-size: 0.88rem;
  color: var(--muted);
  margin: 10px 0 0;
}

.detail-blurb {
  font-size: 1rem;
  line-height: 1.7;
  color: var(--ink-body);
  margin: 20px 0 0;
}

.detail-block {
  margin-top: 34px;
}

.detail-block[hidden] { display: none; }

.detail-h2 {
  font-family: var(--serif);
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--ink-heading);
  margin: 0 0 12px;
}

.detail-learn {
  margin: 0;
  padding-left: 20px;
  color: var(--ink-body);
  line-height: 1.65;
}

.detail-learn li { margin-bottom: 6px; }

/* The outline: module headings with their lesson titles beneath. */
.detail-module {
  padding: 14px 16px;
  border: 1px solid var(--hairline);
  border-radius: 12px;
  background: var(--card);
  margin-bottom: 10px;
}

.detail-module-name {
  font-weight: 600;
  color: var(--ink-heading);
  font-size: 0.95rem;
  margin: 0 0 8px;
}

.detail-unit {
  font-size: 0.88rem;
  color: var(--muted);
  margin: 0 0 4px;
  padding-left: 14px;
  position: relative;
}

.detail-unit::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--hairline-deep);
}

/* Intro and Wrap-Up sit outside the modules, so they get no card. */
.detail-outline > .detail-unit {
  padding-left: 30px;
  margin-bottom: 8px;
}

.detail-outline > .detail-unit::before { left: 16px; }

.detail-cta {
  margin-top: 38px;
  padding-top: 26px;
  border-top: 1px solid var(--hairline);
}

.detail-cta-note {
  font-size: 0.84rem;
  color: var(--muted);
  margin: 12px 0 0;
}

@media (max-width: 620px) {
  .course-detail { padding: 28px 16px 72px; }
}

/* ----- course reader ------------------------------------------------------ */
/* The reader is the second subview of #mode-learning. It sits OUTSIDE
   .p-panel-inner so long-form reading gets a wider measure than the 680px
   list column. All colors/typography come from the locked tokens. */

.course-reader {
  max-width: 1000px;
  margin: 0 auto;
  padding: 42px 24px 90px;
}

.course-back {
  display: inline-block;
  margin-bottom: 18px;
  font-size: 0.9rem;
}

/* Focused programmatically when the reader opens (tabindex="-1"). */
#course-title { outline: none; }

.course-layout {
  display: grid;
  grid-template-columns: 240px 1fr;
  gap: 28px;
  align-items: start;
  margin-top: 26px;
}

/* Contents rail — sticks while the page scrolls, scrolls itself when tall. */
.course-toc {
  position: sticky;
  top: 20px;
  max-height: calc(100vh - 40px);
  overflow-y: auto;
  padding-right: 4px;
}

.course-toc-group {
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 18px 0 6px;
}

.course-toc-group:first-child { margin-top: 0; }

.course-toc-item {
  display: block;
  width: 100%;
  border: 0;
  background: none;
  text-align: left;
  font-family: var(--sans);
  font-size: 0.88rem;
  line-height: 1.4;
  color: var(--ink-body);
  padding: 6px 10px;
  border-radius: 8px;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}

.course-toc-item:hover { background: rgba(var(--ink-rgb), 0.05); }

.course-toc-item.is-active {
  background: rgba(var(--ink-rgb), 0.07);
  color: var(--navy);
  font-weight: 600;
}

.course-toc-num {
  color: var(--muted);
  font-weight: 600;
  font-size: 0.78rem;
  margin-right: 6px;
}

.course-toc-item.is-active .course-toc-num { color: inherit; }

/* Reading pane — the familiar white card, sized for long-form text. */
.course-pane {
  min-width: 0;
  scroll-margin-top: 18px;
}

.course-unit {
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 16px;
  box-shadow: var(--shadow-card);
  padding: 34px 38px 38px;
}

.course-unit > :first-child { margin-top: 0; }

.course-unit h1,
.course-unit h2,
.course-unit h3 {
  font-family: var(--serif);
  font-weight: 600;
  color: var(--ink-heading);
  line-height: 1.2;
  margin: 1.6em 0 0.5em;
}

.course-unit h1 { font-size: 1.7rem; }
.course-unit h2 { font-size: 1.45rem; }
.course-unit h3 { font-size: 1.18rem; }

/* The unit's own name, inserted by app.js above the server HTML. */
.course-unit .course-unit-title { font-size: 1.75rem; }

.course-unit p {
  margin: 0.85em 0;
  line-height: 1.75;
}

.course-unit ul,
.course-unit ol {
  margin: 0.85em 0;
  padding-left: 1.5em;
}

.course-unit li {
  margin: 0.4em 0;
  line-height: 1.65;
}

.course-unit hr {
  border: 0;
  border-top: 1px solid var(--hairline);
  margin: 2em 0;
}

/* Blockquotes are Scripture — same voice as .verse-text. */
.course-unit blockquote {
  margin: 1.4em 0;
  padding: 2px 0 2px 18px;
  border-left: 2px solid var(--hairline-deep);
  font-family: var(--scripture);
  font-style: italic;
  font-size: 1.05rem;
  line-height: 1.78;
  color: var(--ink-body);
}

/* [VIDEO SLOT] / [PROGRESS CHECKPOINT] placeholders from the server —
   clearly unfinished on purpose, so nothing reads as broken. */
.course-slot {
  display: block;
  margin: 1.4em 0;
  padding: 13px 16px;
  border: 1px dashed var(--hairline-deep);
  border-radius: 12px;
  background: var(--bg);
}

.course-slot-label {
  display: block;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

.course-slot-note {
  display: block;
  margin-top: 3px;
  font-size: 0.85rem;
  color: var(--muted);
}

/* ----- quizzes ------------------------------------------------------------
   The page holds no answer key, so every state here is painted by app.js:

     .is-picked   chosen, NOT yet graded — free to change, and the only
                  state here that implies no verdict at all
     .is-spent    ruled out — struck through, inert, the others stay live
     .is-correct  settled on this choice — sage tint and a check
     .is-dimmed   settled, never tried — recedes, unmarked

   There is no red and no X. The strikethrough does the work.

   .is-picked deliberately borrows the navy the app uses for a control the
   reader is operating, not the sage it uses for something settled. Sage
   means finished, and a pick is not finished. */

.quiz {
  margin: 1.6em 0 0;
}

.quiz-q {
  margin: 1.9em 0;
}

.quiz-q:first-child {
  margin-top: 1.2em;
}

.course-unit .quiz-prompt {
  margin: 0 0 0.9em;
  line-height: 1.7;
}

.quiz-options {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.quiz-opt {
  display: flex;
  align-items: baseline;
  gap: 12px;
  width: 100%;
  padding: 12px 15px;
  text-align: left;
  font-family: var(--sans);
  font-size: 0.97rem;
  line-height: 1.6;
  color: var(--ink-body);
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  cursor: pointer;
  transition: border-color 0.18s var(--ease-out),
    background 0.18s var(--ease-out), opacity 0.18s var(--ease-out);
}

.quiz-opt:hover:not(:disabled) {
  border-color: var(--hairline-deep);
  background: var(--bg);
}

.quiz-opt:focus-visible {
  outline: 2px solid var(--cross-brown);
  outline-offset: 2px;
}

.quiz-opt:disabled {
  cursor: default;
}

.quiz-opt-letter {
  flex: none;
  width: 1.15em;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--cross-brown);
}

.quiz-opt-text {
  flex: 1;
}

/* Ruled out. */
.quiz-opt.is-spent {
  background: transparent;
  color: var(--muted);
  opacity: 0.72;
}

.quiz-opt.is-spent .quiz-opt-text {
  text-decoration: line-through;
}

.quiz-opt.is-spent .quiz-opt-letter {
  color: var(--muted);
}

/* Chosen, still ungraded. */
.quiz-opt.is-picked {
  border-color: var(--navy);
  background: var(--bg);
}

.quiz-opt.is-picked .quiz-opt-letter {
  color: var(--navy);
}

.quiz-opt.is-picked::after {
  content: "●";
  margin-left: auto;
  padding-left: 10px;
  font-size: 0.55rem;
  line-height: 2.1;
  color: var(--navy);
}

/* Settled — this was the choice. */
.quiz-opt.is-correct {
  border-color: var(--sage);
  background: var(--sage-tint);
}

.quiz-opt.is-correct .quiz-opt-letter {
  color: var(--sage);
}

.quiz-opt.is-correct::after {
  content: "✓";
  margin-left: auto;
  padding-left: 10px;
  font-size: 0.95rem;
  color: var(--sage);
}

/* Settled, never tried. */
.quiz-opt.is-dimmed {
  background: transparent;
  opacity: 0.45;
}

.quiz-opt.is-checking {
  opacity: 0.6;
}

/* The explanation slot. Empty until explanations are written into the
   manuscripts — hidden while empty, never a placeholder. */
.quiz-explain {
  margin: 10px 0 0;
  padding-left: 15px;
  border-left: 2px solid var(--hairline-deep);
  font-size: 0.94rem;
  line-height: 1.7;
  color: var(--ink-body);
}

/* Submit, and the line that says what is still waiting. */
.quiz-actions {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  margin: 1.7em 0 0;
}

.quiz-submit.is-checking {
  opacity: 0.6;
}

.quiz-hint {
  margin: 0;
  font-family: var(--sans);
  font-size: 0.85rem;
  letter-spacing: 0.02em;
  color: var(--muted);
}

.quiz-tally {
  margin: 1.8em 0 0;
  padding-top: 14px;
  border-top: 1px solid var(--hairline);
  font-family: var(--sans);
  font-size: 0.85rem;
  letter-spacing: 0.02em;
  color: var(--muted);
}

.quiz-explain[hidden],
.quiz-hint[hidden],
.quiz-submit[hidden],
.quiz-tally[hidden] {
  display: none;
}

/* Access / load messages shown alone in the pane (e.g. the server's 403). */
.course-gate {
  margin: 0;
  font-family: var(--scripture);
  font-style: italic;
  font-size: 1.02rem;
  line-height: 1.75;
  color: var(--ink-body);
  max-width: 46ch;
}

/* Prev / Next through the units. */
.course-stepnav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 18px;
}

.course-step {
  font-family: var(--sans);
  font-weight: 600;
  font-size: 0.88rem;
  color: var(--navy);
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  padding: 9px 18px;
  cursor: pointer;
  transition: border-color 0.18s ease, box-shadow 0.2s ease,
    transform 0.15s ease, opacity 0.2s ease;
}

.course-step:hover:not(:disabled) {
  border-color: var(--hairline-deep);
  box-shadow: var(--shadow-card);
}

.course-step:active:not(:disabled) { transform: translateY(1px); }

.course-step:disabled {
  opacity: 0.45;
  cursor: default;
}

.course-pos {
  font-size: 0.8rem;
  color: var(--muted);
}

/* display:flex would defeat the hidden attribute this relies on. */
.course-stepnav[hidden] { display: none; }

/* Solo messages (loading / access / error) span the full width — no empty
   240px rail column beside them. */
.course-reader.no-toc .course-layout { grid-template-columns: 1fr; }

/* Group-less items after the modules (the Wrap-Up) breathe a little. */
.course-toc-solo { margin-top: 14px; }

@media (max-width: 760px) {
  .course-reader { padding: 28px 16px 72px; }
  .course-layout {
    grid-template-columns: 1fr;
    gap: 18px;
  }
  /* The rail becomes a compact scrollable card above the reading pane. */
  .course-toc {
    position: static;
    max-height: 220px;
    border: 1px solid var(--hairline);
    border-radius: 12px;
    background: var(--card);
    padding: 12px;
  }
  .course-unit { padding: 22px 18px 26px; }
}

/* Backdrop for the mobile drawer (hidden on desktop). */
#nav-backdrop { display: none; }

/* ----- desktop: collapse to an icon rail --------------------------------- */

@media (min-width: 761px) {
  #premium-view.nav-collapsed .p-sidebar {
    flex-basis: 74px;
    width: 74px;
  }
  #premium-view.nav-collapsed .p-wordmark,
  #premium-view.nav-collapsed .p-label,
  #premium-view.nav-collapsed .p-mode-tag,
  #premium-view.nav-collapsed .p-context,
  #premium-view.nav-collapsed .p-account-text {
    display: none;
  }
  #premium-view.nav-collapsed .p-side-head {
    justify-content: center;
  }
  #premium-view.nav-collapsed .p-mode {
    justify-content: center;
    padding-left: 0;
    padding-right: 0;
  }
  #premium-view.nav-collapsed .p-account {
    justify-content: center;
    padding-left: 0;
    padding-right: 0;
  }
}

/* ----- mobile: sidebar becomes an off-canvas drawer ---------------------- */

@media (max-width: 760px) {
  .p-sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    height: 100dvh;
    flex-basis: auto;
    width: min(84vw, 300px);
    transform: translateX(0);
    transition: transform 0.28s var(--ease-out);
    box-shadow: 0 24px 60px rgba(var(--ink-rgb), 0.24);
    z-index: 50;
  }
  /* On phones, "collapsed" means the drawer is closed (slid off-canvas) —
     NOT the desktop icon rail, so labels are kept intact. */
  #premium-view.nav-collapsed .p-sidebar {
    transform: translateX(-100%);
  }
  #nav-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(var(--ink-rgb), 0.34);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.28s ease;
    z-index: 45;
  }
  #premium-view:not(.nav-collapsed) #nav-backdrop {
    opacity: 1;
    pointer-events: auto;
  }
  .p-hamburger { display: inline-flex; }
  .p-main-head { padding: 14px 16px; }
  .p-panel-inner { padding: 28px 16px 72px; }
}

/* ==========================================================================
   ACCOUNT PANEL
   --------------------------------------------------------------------------
   One centred card over a soft scrim, opened from either layout. Same
   eggshell/hairline/navy language as the rest of the app — calm, not a
   dashboard. Sits above the premium drawer (z-index 45) but below nothing
   else; the splash is gone by the time this can open.
   ========================================================================== */

.acct {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.acct[hidden] {
  display: none;
}

.acct-scrim {
  position: absolute;
  inset: 0;
  background: rgba(var(--ink-rgb), 0.34);
  opacity: 0;
  transition: opacity 0.28s var(--ease-out);
}

.acct.is-open .acct-scrim {
  opacity: 1;
}

.acct-card {
  position: relative;
  width: 100%;
  max-width: 460px;
  max-height: calc(100vh - 48px);
  overflow-y: auto;
  padding: 26px 28px 22px;
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 0.3s var(--ease-out), transform 0.3s var(--ease-out);
}

.acct.is-open .acct-card {
  opacity: 1;
  transform: translateY(0);
}

.acct-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 18px;
}

.acct-title {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1.45rem;
  color: var(--ink-heading);
  margin: 0;
  outline: none;
}

.acct-close {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid var(--hairline);
  background: var(--card);
  color: var(--ink-body);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: border-color 0.2s ease, color 0.2s ease;
}

.acct-close:hover {
  border-color: var(--hairline-deep);
  color: var(--ink-heading);
}

.acct-close svg {
  width: 15px;
  height: 15px;
}

/* ----- the value rows ----------------------------------------------------- */

.acct-rows {
  margin: 0;
}

.acct-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 11px 0;
  border-bottom: 1px solid var(--hairline);
}

.acct-row dt {
  font-size: 0.85rem;
  color: var(--muted);
  flex-shrink: 0;
}

.acct-row dd {
  margin: 0;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--ink-heading);
  text-align: right;
  overflow-wrap: anywhere;
}

/* The usage list follows the identity rows with no double hairline. */
.acct-usage {
  margin-top: 0;
}

.acct-note {
  font-size: 0.8rem;
  color: var(--muted);
  line-height: 1.55;
  margin: 16px 0 18px;
}

/* Cancellation / grace-period warning — same ink the sign-in card already
   uses for an error, not a new color. */
.acct-note.is-warning {
  color: var(--error-ink);
}

/* ----- "View all plans" --------------------------------------------------- */

/* "View all plans" — a link out to /plans, not an in-panel list. */
.acct-plans-wrap {
  border-top: 1px solid var(--hairline);
  padding-top: 16px;
}

.acct-plans-wrap .link-btn {
  display: inline-block;
}

.acct-foot {
  border-top: 1px solid var(--hairline);
  margin-top: 18px;
  padding-top: 14px;
}

@media (max-width: 480px) {
  .acct {
    padding: 14px;
  }
  .acct-card {
    padding: 22px 20px 18px;
  }
  .acct-row {
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
  }
  .acct-row dd {
    text-align: left;
  }
}

/* ==========================================================================
   PLANS PAGE (/plans)
   --------------------------------------------------------------------------
   A public pricing page in the app's own language: eggshell ground, white
   cards, hairline borders, navy for the one real action. FREE AND STANDARD
   only — two cards side by side, stacking on a phone. Premium and Boost are
   real tiers but are not shippable and are not shown. Nothing on the page is
   buyable yet.
   ========================================================================== */

.plans-back {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--navy);
  text-decoration: none;
  opacity: 0.75;
  transition: opacity 0.2s ease;
}

.plans-back:hover {
  opacity: 1;
}

.plans-main {
  /* Back to two cards, so back to the width two cards want. 1180 was for
     four; at that width a pair of cards stretches into slabs. */
  max-width: 900px;
  margin: 0 auto;
  padding: 0 20px 40px;
}

.plans-hero {
  text-align: center;
  margin: 26px 0 34px;
}

.plans-title {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 2.5rem;
  line-height: 1.15;
  color: var(--ink-heading);
  margin: 6px 0 0;
}

/* Two equal columns that become one below 720px. */
.plans-grid {
  display: grid;
  /* TWO CARDS AGAIN — Premium and Boost are no longer on this page. One
     column on a phone, two once there is room. The four-column rule that
     lived here went with the cards it was for; leaving it would have set
     four tracks for two cards and put them in the left half of the page. */
  grid-template-columns: 1fr;
  gap: 20px;
  align-items: stretch;
}

.plan-card {
  display: flex;
  flex-direction: column;
  padding: 28px 26px 26px;
}

.plan-name {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1.5rem;
  color: var(--ink-heading);
  margin: 0;
}

.plan-price {
  display: flex;
  align-items: baseline;
  gap: 4px;
  margin: 10px 0 0;
  padding-bottom: 20px;
  border-bottom: 1px solid var(--hairline);
}

.plan-amount {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 2.3rem;
  line-height: 1;
  color: var(--ink-heading);
}

.plan-period {
  font-size: 0.9rem;
  color: var(--muted);
}

.plan-lead {
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--ink-heading);
  margin: 20px 0 0;
}

.plan-features {
  list-style: none;
  margin: 18px 0 26px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* A small brown check, echoing the cross motif. */
.plan-features li {
  position: relative;
  padding-left: 26px;
  font-size: 0.92rem;
  line-height: 1.5;
}

.plan-features li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 0.45em;
  width: 11px;
  height: 6px;
  border-left: 2px solid var(--cross-brown);
  border-bottom: 2px solid var(--cross-brown);
  transform: rotate(-45deg);
}

/* The card action sits flush at the bottom, so both cards line up however
   many features each one lists. */
.plan-cta {
  margin-top: auto;
  display: block;
  width: 100%;
  text-align: center;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 0.9rem;
  padding: 12px 18px;
  border-radius: 999px;
  border: 1px solid var(--navy);
  background: var(--navy);
  color: var(--on-navy);
  text-decoration: none;
  cursor: pointer;
  transition: background 0.2s ease, transform 0.15s ease;
}

.plan-cta:hover:not(:disabled) {
  background: var(--navy-soft);
}

.plan-cta:active:not(:disabled) {
  transform: translateY(1px);
}

/* "Coming soon" — there is no Stripe, so this must not look clickable. */
.plan-cta:disabled {
  background: var(--bg);
  border-color: var(--hairline-deep);
  color: var(--muted);
  cursor: default;
}

/* The Free card's action is real but secondary. */
.plan-cta-quiet {
  background: var(--card);
  border-color: var(--hairline-deep);
  color: var(--navy);
}

.plan-cta-quiet:hover {
  background: var(--bg);
}

/* Two across once there is room for two. */
@media (min-width: 700px) {
  .plans-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 720px) {
  .plans-title {
    font-size: 2rem;
  }
  .plans-main {
    padding: 0 16px 32px;
  }
  .plan-card {
    padding: 24px 20px 22px;
  }
}

/* Honor reduced-motion for the premium transitions too. */
@media (prefers-reduced-motion: reduce) {
  .p-sidebar,
  #nav-backdrop,
  .p-mode,
  .acct,
  .acct-card {
    transition: none !important;
  }
}

/* ==========================================================================
   DESKTOP WIDTHS
   --------------------------------------------------------------------------
   The only place this layout GROWS. Every other breakpoint in this file is a
   max-width: the page was authored at a fixed 720px and from there only ever
   shrank, which is why a laptop was served the same column as a phone.

   main's 720px cap is LIFTED here rather than deleted outright. Deleting it
   would also free .course-detail (760px) and .course-reader (1000px) between
   720px and 1024px — a change to tablets nobody asked for. Above 1024px main
   stops deciding widths and each surface carries its own.
   ========================================================================== */

@media (min-width: 1024px) {
  main {
    max-width: none;
  }

  /* Ask is prose and stays prose. .account-bar, .ask and .results already cap
     themselves at 640px and centre; .hero was the one thing inside main with
     no width of its own, so it would have gone full-bleed the moment the cap
     came off. */
  .hero {
    max-width: 640px;
    margin-left: auto;
    margin-right: auto;
  }

  /* Shelves: a percentage so the rails still scale on smaller laptops, under
     a ceiling set by what a row actually holds rather than by how much screen
     exists. At 1800px a shelf carrying one course left a single card adrift in
     an empty row, with the fixed 440px watermark cross stranded in the open
     space beside it; at 900px the cards sit back over the cross and the row
     reads as a row. Centring comes from .p-panel-inner's margin: 0 auto. */
  #learning-list {
    width: 90%;
    max-width: 900px;
  }

  /* ----- shelf contents, scaled for the wider column ----------------------
     The card and its type were sized for a 680px panel; at desktop width the
     row read as small print in a large room. Card and contents grow together
     so the proportions hold. Left alignment needs no rule here — .shelf-card
     is already align-items: flex-start with text-align: left, and .shelf-head
     is a flex column. */
  .shelf-name {
    font-size: 1.625rem;
  }

  .shelf-desc {
    font-size: 1.075rem;
  }

  /* A FIXED box, not a floor: every card in every shelf is exactly 200px tall,
     so the rows match each other and not merely themselves.

     WHEN THE CONTENT DOES NOT FIT, PADDING GIVES WAY FIRST. The box size and
     the type size are the fixed points — 285x200, and a 19.2px title over a
     15.6px count and an 18px price. The gutter is the adjustable one, and it
     has already been spent once: 19px left a two-line title clearing by
     1.76px, which is inside the range real font metrics drift from nominal
     line boxes, and 12px lifts that to 15.76px. Reach for the gutter before
     the box or the type, and know the remaining travel is small.

     Titles are the other half of this. Two lines is the ceiling — roughly 54
     characters across the 261px column — and a third line breaks out of the
     card by ~9px with no clamp and no ellipsis to stop it. That rule lives
     where course authors will meet it: COURSE-FORMAT.md section 6, item 11. */
  .shelf-card {
    flex: 0 0 285px;
    width: 285px;
    height: 200px;
    padding: 12px;
    gap: 10px;
  }

  /* These two carry one line each and had no line-height of their own, so they
     inherited body's 1.65 — a measure meant for paragraphs — and spent 55.44px
     drawing 33.6px of text. At 1.2 they render as the labels they are. With
     the 12px gutter the two-line stack comes to 160.24px against the 176px the
     fixed box leaves, so the card holds its second line with room to spare
     rather than by a fraction of a pixel. */
  .shelf-card-meta,
  .shelf-card-price {
    line-height: 1.2;
  }

  .shelf-card-icon {
    width: 40px;
    height: 40px;
  }

  /* The glyph tracks its box — 20/40 keeps the 17/34 ratio the card was drawn
     at, so the icon does not become a large frame around a small mark. */
  .shelf-card-icon svg {
    width: 20px;
    height: 20px;
  }

  .shelf-card-title {
    font-size: 1.2rem;
  }

  .shelf-card-meta {
    font-size: 0.975rem;
  }

  .shelf-card-price {
    font-size: 1.125rem;
  }

  /* The placeholder tile shares a row with real cards, so its label tracks the
     card title instead of staying at the size it had in the narrow column. */
  .shelf-more-text {
    font-size: 1.2rem;
  }

  /* The header IS the topbar (header.topbar), so it sits outside main and had
     its own 1060px cap, which matched nothing once the shelves set their own
     width. It tracks the shelf box instead, and the two must be changed
     together — a ceiling here that disagrees with #learning-list above puts
     the wordmark hundreds of pixels off the shelf title beneath it.

     The shelves are 90% of MAIN's content box and main carries a 20px gutter
     each side, so the identical width measured against the topbar's
     full-width parent is `calc(90% - 36px)`, under the same 900px ceiling.
     The gutter also drops 28px -> 24px to match .p-panel-inner: with both
     gutters equal the two boxes coincide exactly, and the wordmark's left
     edge lands on the shelf title's. */
  .topbar {
    width: calc(90% - 36px);
    max-width: 900px;
    padding-left: 24px;
    padding-right: 24px;
  }

  /* The reader's own max-width finally does something. Until now it was
     capped by main two levels above it and had never once rendered. */
  .course-reader {
    max-width: 1240px;
  }

  .course-layout {
    grid-template-columns: 280px 1fr;
  }

  /* THE TEXT MEASURE DOES NOT GROW WITH THE SCREEN, and the card does not
     drift away from the contents rail. The 76px is .course-unit's own
     left+right padding, so the 65ch lands on the TEXT rather than on the card;
     the card sits flush against the gap after the rail, and every pixel the
     reader gains beyond it becomes right margin.

     The 18px base is what widens the column without lengthening the lines:
     `ch` is measured in the element's OWN font, so 65ch at 18px is ~585px
     where at 16px it was ~520px — a wider column carrying the same number of
     characters. */
  .course-unit {
    font-size: 18px;
    max-width: calc(65ch + 76px);
    margin-left: 0;
    margin-right: auto;
  }

  /* The unit's type scale is authored in rem, which is root-relative and so
     would not follow the 18px base: h3 (1.18rem = 18.9px) would sit level with
     the body text and stop reading as a heading, and Scripture blockquotes
     (1.05rem = 16.8px) would render SMALLER than the prose around them,
     inverting the emphasis. Same ratios as authored, re-based on the element
     so the whole scale moves together. */
  .course-unit h1 { font-size: 1.7em; }
  .course-unit h2 { font-size: 1.45em; }
  .course-unit h3 { font-size: 1.18em; }
  .course-unit .course-unit-title { font-size: 1.75em; }
  .course-unit blockquote { font-size: 1.05em; }
}

/* ==========================================================================
   THE BIBLE READER — #page-bible
   --------------------------------------------------------------------------
   NO NEW TOKENS. Every colour, font and radius below is one already in the
   palette at the top of this file. The verse tint is --sage-tint, the token
   added for a settled quiz answer, reused here for a highlighted verse.

   The layout is the course reader's: a rail and a reading column, the same
   1024px breakpoint, and the same rule about measure — above 1024px the
   prose caps at 65ch and every pixel beyond that becomes margin. A verse
   must not run 180 characters because the monitor is wide.
   ========================================================================== */

.bible-reader {
  max-width: 1240px;
  margin: 0 auto;
  padding: 28px 20px 90px;
}

/* ----- the bar ------------------------------------------------------------ */
/* Sticky: on a long chapter the way to another one should not be a scroll
   back to the top. */

.bible-bar {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 0;
  margin-bottom: 8px;
  background: var(--bg);
  border-bottom: 1px solid var(--hairline);
}

.bible-ref {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1.3rem;
  color: var(--ink-heading);
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  padding: 7px 16px;
  cursor: pointer;
  transition: border-color 0.18s ease, box-shadow 0.2s ease;
}

.bible-ref:hover {
  border-color: var(--hairline-deep);
  box-shadow: var(--shadow-card);
}

.bible-ref-caret {
  width: 16px;
  height: 16px;
  color: var(--muted);
}

/* Three translations as one segmented control — WEB is the default. */
.bible-trans {
  display: inline-flex;
  margin-left: auto;
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  overflow: hidden;
}

.bible-trans-btn {
  border: 0;
  background: none;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  color: var(--muted);
  padding: 8px 13px;
  cursor: pointer;
  transition: background 0.18s ease, color 0.18s ease;
}

.bible-trans-btn:hover { color: var(--ink-body); }

.bible-trans-btn.is-active {
  background: var(--navy);
  color: var(--on-navy);
}

.bible-marks-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  flex: 0 0 auto;
  color: var(--navy);
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  cursor: pointer;
}

.bible-marks-btn svg { width: 18px; height: 18px; }

/* ----- layout ------------------------------------------------------------- */
/* Phone first: one column, the rail is a drawer opened from the bar. */

.bible-layout {
  display: block;
  margin-top: 18px;
}

.bible-pane { min-width: 0; }

.bible-title {
  font-family: var(--serif);
  font-weight: 600;
  font-size: clamp(1.7rem, 4.5vw, 2.2rem);
  line-height: 1.15;
  color: var(--ink-heading);
  margin: 0 0 16px;
  outline: none;
}

/* ----- the chapter -------------------------------------------------------- */

.bible-chapter {
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 16px;
  box-shadow: var(--shadow-card);
  padding: 26px 22px;
  /* The type is set HERE, on the container, so every verse in the flow
     shares one rhythm rather than each carrying its own. */
  font-family: var(--scripture);
  font-size: 1.02rem;
  line-height: 1.75;
  color: var(--ink-body);
}

/* THE READING SURFACE IS FLOW, NOT ROWS.
   Verses used to be block buttons, one per row, and the verse numbers stacked
   into a left rail the eye tracked down like a ledger. That is a study
   layout — built for looking a reference up. The vertical rhythm ran
   tight-tight-GAP, so the loudest thing on the page was the boundary between
   records rather than the sentence.

   Now the chapter is one paragraph. Verses run together, the number rides
   inside the sentence as a superscript, and NOTHING about a verse boundary
   creates a gap. */
.bible-flow {
  margin: 0;
  /* Ragged right, never justified: justification opens rivers of white space
     at this measure, and the eye needs the line-end shape to find its way
     back. */
  text-align: left;
  hyphens: none;
}

.bible-verse {
  display: inline;
  cursor: pointer;
  border-radius: 3px;
  transition: background 0.16s ease;
}

/* An inline mark spans line breaks, so each fragment has to carry the
   padding and the rounded ends rather than only the first and last. */
.bible-verse.is-highlighted,
.bible-verse.is-selected,
.bible-verse:hover {
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
  padding: 0.1em 0.12em;
  margin: 0 -0.12em;
}

.bible-verse:hover { background: rgba(var(--ink-rgb), 0.05); }

/* The five washes. */
.bible-verse.is-sage { background: var(--hl-sage); }
.bible-verse.is-clay { background: var(--hl-clay); }
.bible-verse.is-sand { background: var(--hl-sand); }
.bible-verse.is-sky { background: var(--hl-sky); }
.bible-verse.is-lavender { background: var(--hl-lavender); }

/* SELECTED IS NOT HIGHLIGHTED, and must not look like it. A selection is a
   thing in progress — it disappears the moment you tap elsewhere — so it is
   drawn as a rule under the words rather than as a wash behind them. A
   reader can see at a glance which verses are marked and which are merely
   being pointed at, even when both are true of the same verse. */
.bible-verse.is-selected {
  background: rgba(var(--ink-rgb), 0.06);
  box-shadow: inset 0 -2px 0 0 var(--navy);
}

.bible-verse:focus-visible {
  outline: 2px solid rgba(var(--ink-rgb), 0.45);
  outline-offset: 2px;
}

/* THIS IS WHERE THE COLOUR WAS BEING LOST.
   These two rules are what is left of the single-colour version, when every
   highlight was sage and one token could say so. They painted
   `background: var(--sage-tint)` on .is-highlighted — the same specificity
   as .bible-verse.is-clay and friends (two classes each), and LATER in the
   file, so they won every time. The colour was chosen correctly, sent
   correctly, stored correctly and the right class was on the element; a
   leftover rule then painted over all of it.

   Their backgrounds are gone. The colour rules above are the only thing that
   paints a highlight now, and because they sit AFTER .bible-verse:hover they
   also survive hovering — which is what the second rule was really for.
   The shared box-decoration/padding for .is-highlighted lives further up and
   is untouched. */

/* Where a bookmark jump landed. The app's existing focus ring, held for a
   moment — not a new colour, and not a state the verse keeps. */
.bible-verse.is-found {
  outline: 2px solid rgba(var(--ink-rgb), 0.45);
  outline-offset: 2px;
}

/* The number is a mark inside the sentence, not a column. Small, quiet, and
   it must not open up the leading — `line-height: 0` keeps a superscript
   from pushing its own line taller than the ones around it. */
.bible-vnum {
  font-family: var(--sans);
  font-weight: 700;
  font-size: 0.58em;
  line-height: 0;
  color: var(--muted);
  vertical-align: super;
  margin-right: 0.18em;
  /* Never part of a text selection or a copy — the words are the content. */
  user-select: none;
}

.bible-empty {
  font-size: 0.95rem;
  color: var(--muted);
  margin: 0;
}

.bible-slot:empty { display: none; }
.bible-slot { margin-top: 12px; }

.bible-stepnav { margin-top: 20px; }

/* ----- the bookmark rail -------------------------------------------------- */
/* Same shape as the Conversations sidebar: a label, rows, a quiet foot. */

.bible-side {
  display: none;
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 16px;
  padding: 16px 14px;
  margin-bottom: 18px;
}

/* THE DRAWER MUST BE WHERE THE FINGER IS. Below 1024px the rail sits above
   the reading column in the document, so simply revealing it put the panel
   off-screen whenever the reader had scrolled — tapping the bookmark button
   part-way down a chapter looked like nothing happened. Opened, it becomes a
   panel pinned under the bar instead. */
.bible-side.is-open {
  display: block;
  position: fixed;
  top: 64px;
  left: 12px;
  right: 12px;
  z-index: 40;
  max-height: 68vh;
  overflow-y: auto;
  box-shadow: var(--shadow-card-hover);
}

.bible-side-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 4px;
}

.bible-side-head .p-ctx-label { margin: 0; }

/* Plain figures in the muted colour — a count, not a warning. */
.bible-count {
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}

/* The last few. Still no red — the palette has no negative colour, so the
   nearly-full state is the brown that already carries emphasis here. */
.bible-count.is-near { color: var(--cross-brown); }

.bible-bm-list { margin-top: 8px; }

.bible-bm-row {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  width: 100%;
  margin-bottom: 2px;
}

.bible-bm-jump {
  flex: 1 1 auto;
  min-width: 0;
  text-align: left;
  border: 0;
  background: none;
  border-radius: 8px;
  padding: 7px 8px;
  cursor: pointer;
  transition: background 0.15s ease;
}

.bible-bm-jump:hover { background: rgba(var(--ink-rgb), 0.05); }

.bible-bm-ref {
  display: block;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 0.84rem;
  color: var(--navy);
}

/* Which wording this one is. The same verse kept in two translations is two
   entries, and they would otherwise carry the same label. */
.bible-bm-trans {
  margin-left: 6px;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--muted);
}

.bible-bm-snippet {
  display: block;
  font-family: var(--scripture);
  font-style: italic;
  font-size: 0.82rem;
  line-height: 1.45;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bible-bm-remove {
  flex: 0 0 auto;
  border: 0;
  background: none;
  color: var(--muted);
  font-size: 1rem;
  line-height: 1;
  padding: 7px 6px;
  border-radius: 8px;
  cursor: pointer;
  transition: color 0.15s ease, background 0.15s ease;
}

.bible-bm-remove:hover {
  color: var(--ink-body);
  background: rgba(var(--ink-rgb), 0.05);
}

/* ----- the save prompt ---------------------------------------------------- */
/* Shown under a verse the moment it is highlighted. Dismissible, and No is
   the quiet default: ignoring it leaves the verse highlighted and unsaved. */

.bible-save {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin: 2px 0 8px;
  padding: 10px 12px;
  background: var(--sage-tint);
  border: 1px solid var(--hairline);
  border-radius: 12px;
}

.bible-save-text {
  font-size: 0.88rem;
  color: var(--ink-body);
  margin: 0;
}

.bible-save-actions {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
}

.bible-save-count {
  font-size: 0.76rem;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}

.bible-save-btn {
  font-family: var(--sans);
  font-weight: 600;
  font-size: 0.8rem;
  color: var(--navy);
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  padding: 6px 14px;
  cursor: pointer;
  transition: border-color 0.18s ease, box-shadow 0.2s ease;
}

.bible-save-btn:hover {
  border-color: var(--hairline-deep);
  box-shadow: var(--shadow-card);
}

.bible-save-btn.is-quiet { color: var(--muted); }

/* At the cap, and after a failure. Plain sentence, no warning colour. */
.bible-save-note {
  flex: 1 1 100%;
  font-size: 0.84rem;
  color: var(--ink-body);
  margin: 0;
}

/* ----- the picker --------------------------------------------------------- */

.bible-picker {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.bible-picker[hidden] { display: none; }

.bible-picker-scrim {
  position: absolute;
  inset: 0;
  background: rgba(var(--ink-rgb), 0.32);
}

.bible-picker-panel {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 560px;
  max-height: 88vh;
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 18px 18px 0 0;
  box-shadow: var(--shadow-card-hover);
  overflow: hidden;
}

.bible-picker-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 16px 10px;
  border-bottom: 1px solid var(--hairline);
}

.bible-picker-title {
  flex: 1 1 auto;
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1.15rem;
  color: var(--ink-heading);
  margin: 0;
}

.bible-picker-back {
  font-size: 0.85rem;
  flex: 0 0 auto;
}

.bible-search-wrap { padding: 12px 16px 4px; }

.bible-search {
  width: 100%;
  font-family: var(--sans);
  font-size: 0.95rem;
  color: var(--ink-body);
  background: var(--bg);
  border: 1px solid var(--hairline);
  border-radius: 10px;
  padding: 10px 12px;
}

.bible-search::placeholder { color: var(--muted); }

.bible-picker-body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 10px 16px 20px;
}

.bible-picker-group {
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 14px 0 6px;
}

.bible-picker-group:first-child { margin-top: 4px; }

.bible-book-list { display: block; }

.bible-book {
  display: block;
  width: 100%;
  text-align: left;
  font-family: var(--sans);
  font-size: 0.95rem;
  color: var(--ink-body);
  border: 0;
  background: none;
  border-radius: 8px;
  padding: 9px 10px;
  cursor: pointer;
  transition: background 0.15s ease;
}

.bible-book:hover { background: rgba(var(--ink-rgb), 0.05); }

/* Chapters as numbers, sized so a thumb hits one cleanly. */
.bible-chap-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(48px, 1fr));
  gap: 8px;
  margin-top: 6px;
}

.bible-chapnum {
  font-family: var(--sans);
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--ink-body);
  background: var(--bg);
  border: 1px solid var(--hairline);
  border-radius: 10px;
  padding: 12px 0;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
}

.bible-chapnum:hover {
  background: var(--card);
  border-color: var(--hairline-deep);
}

@media (max-width: 480px) {
  .bible-reader { padding: 20px 14px 80px; }
  .bible-chapter { padding: 20px 14px; }
  .bible-ref { font-size: 1.15rem; padding: 6px 13px; }
  .bible-trans-btn { padding: 8px 10px; font-size: 0.68rem; }
}

/* ==========================================================================
   THE BIBLE READER AT DESKTOP WIDTH — the same 1024px breakpoint the rest of
   the app turns on, and the same rule the course reader follows: the text
   MEASURE DOES NOT GROW WITH THE SCREEN. Above this width the reading column
   caps at 65ch and everything beyond it becomes right margin.
   ========================================================================== */

@media (min-width: 1024px) {
  /* THE READING COLUMN CENTRES IN THE VIEWPORT.
     It used to be a grid cell beside a 280px rail, left-aligned inside the
     1fr that was left over — so it centred in the SPACE THE SIDEBAR LEFT and
     sat 97px right of the middle of the screen. The rail no longer takes
     part in the flow of this page; the column is centred, and the rail is
     placed around it further down. */
  .bible-layout {
    display: block;
    margin-top: 22px;
  }

  /* THE MEASURE, CALIBRATED BY MEASUREMENT rather than by unit arithmetic.
     `ch` is the width of the digit "0". Georgia's lowercase prose is far
     narrower than its figures, so the old cap of 65ch rendered about 90
     characters a line — a cap that was applied exactly and meant nothing.
     This number was set by walking the rendered text with a Range, counting
     the characters that actually land on each line, and adjusting until the
     median sat inside 60-65. Re-measure if the face or the size changes;
     the value is a consequence of both and does not survive either. */
  .bible-pane {
    max-width: 552px;
    margin-left: auto;
    margin-right: auto;
  }

  /* The bar names the text under it, so it shares that text's edges rather
     than spanning a width the reading column no longer uses. */
  .bible-bar {
    max-width: 552px;
    margin-left: auto;
    margin-right: auto;
  }

  /* 18px is what widens the column without lengthening the lines: the same
     characters, drawn larger, which is the point of the extra room. */
  .bible-chapter {
    font-size: 18px;
    padding: 30px;
  }

  /* Set back to the UI face: it is a note about the page, not Scripture. */
  .bible-empty { font-family: var(--sans); }

  /* On a phone the picker is a sheet rising from the bottom edge; with room
     to spare it becomes a centred dialog. */
  .bible-picker { align-items: center; }

  .bible-picker-panel {
    max-height: 76vh;
    border-radius: 18px;
  }
}

/* ==========================================================================
   THE BOOKMARK RAIL BESIDE THE COLUMN — only once there is genuinely room.
   --------------------------------------------------------------------------
   The rail is 280px and wants a gutter each side. Below this width there is
   no room for it beside a centred reading column WITHOUT pushing the column
   off centre, which is the thing being fixed — so under 1240px it stays the
   drawer it is on a phone, opened from the bar.

   It is positioned FROM THE CENTRE, not from the left edge, so it stays
   beside the text on a 2560px monitor instead of stranding itself against
   the window frame. 596px = half the column (276) + a 40px gutter + the
   rail's own 280px.
   ========================================================================== */
@media (min-width: 1240px) {
  .bible-side,
  .bible-side.is-open {
    display: block;
    position: fixed;
    left: calc(50% - 596px);
    right: auto;
    top: 104px;
    width: 280px;
    max-height: calc(100vh - 150px);
    overflow-y: auto;
    z-index: 20;
    box-shadow: none;
    margin-bottom: 0;
  }

  .bible-marks-btn { display: none; }
}

/* ==========================================================================
   THE ACTION SHEET — what happens to a selection
   --------------------------------------------------------------------------
   It rises from the BOTTOM EDGE, on every width. Both of the reader's other
   controls — the reference bar and the translation picker — sit at the top of
   the screen, which is the hardest place for a thumb to reach one-handed;
   the control reached most often should be the one nearest the hand.

   No new tokens: the panel is the same card, hairline, radius and shadow as
   every other raised surface in the app.
   ========================================================================== */

.bible-sheet {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.bible-sheet[hidden] { display: none; }

.bible-sheet-scrim {
  position: absolute;
  inset: 0;
  /* Lighter than the picker's: the text underneath is still the point, and
     the second tap of a range has to land on a verse behind this. */
  background: rgba(var(--ink-rgb), 0.18);
}

.bible-sheet-panel {
  position: relative;
  width: 100%;
  max-width: 560px;
  max-height: 82vh;
  overflow-y: auto;
  background: var(--card);
  border: 1px solid var(--hairline);
  border-bottom: 0;
  border-radius: 18px 18px 0 0;
  box-shadow: var(--shadow-card-hover);
  padding: 16px 18px calc(18px + env(safe-area-inset-bottom, 0px));
}

.bible-sheet-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 12px;
}

.bible-sheet-ref {
  flex: 1 1 auto;
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1.15rem;
  color: var(--ink-heading);
  margin: 0;
}

.bible-sheet-snippet {
  font-family: var(--scripture);
  font-style: italic;
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--muted);
  margin: 0 0 12px;
}

.bible-sheet-label {
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 14px 0 8px;
}

.bible-sheet-count {
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  margin: 10px 0 0;
  text-align: right;
}

/* ----- colour swatches ---------------------------------------------------- */

.bible-swatches {
  display: flex;
  gap: 10px;
}

.bible-swatch {
  width: 38px;
  height: 38px;
  border-radius: 999px;
  border: 1px solid var(--hairline-deep);
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.2s ease;
}

.bible-swatch:hover { transform: translateY(-1px); }

/* The swatch IS the wash, so it shows exactly what the verse will look
   like — not a paler cousin of it. */
.bible-swatch.is-sage { background: var(--hl-sage); border-color: var(--sage); }
.bible-swatch.is-clay { background: var(--hl-clay); border-color: var(--clay); }
.bible-swatch.is-sand { background: var(--hl-sand); border-color: var(--sand); }
.bible-swatch.is-sky { background: var(--hl-sky); border-color: var(--sky); }
.bible-swatch.is-lavender { background: var(--hl-lavender); border-color: var(--lavender); }

/* The chosen one, marked by a ring rather than by a tick: the swatch IS the
   colour, and a glyph on top of it obscures the thing being chosen. */
.bible-swatch.is-active {
  box-shadow: 0 0 0 2px var(--card), 0 0 0 4px var(--navy);
}

/* ----- collections in the sheet ------------------------------------------- */

.bible-collection-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: 34vh;
  overflow-y: auto;
}

.bible-collection {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 8px;
  border-radius: 8px;
  cursor: pointer;
  font-size: 0.92rem;
  color: var(--ink-body);
  transition: background 0.15s ease;
}

.bible-collection:hover { background: rgba(var(--ink-rgb), 0.04); }

/* "All saved" is not a choice — it is where everything already is. Shown
   ticked and disabled so the rule is visible rather than merely true. */
.bible-collection.is-fixed {
  cursor: default;
  color: var(--muted);
}

.bible-collection.is-fixed:hover { background: none; }

.bible-collection input { accent-color: var(--navy); }

.bible-collection-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bible-collection-count {
  flex: 0 0 auto;
  font-size: 0.76rem;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  margin-left: 8px;
}

.bible-newcol {
  display: flex;
  gap: 8px;
  margin-top: 10px;
}

.bible-newcol-input {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--sans);
  font-size: 0.92rem;
  color: var(--ink-body);
  background: var(--bg);
  border: 1px solid var(--hairline);
  border-radius: 10px;
  padding: 9px 12px;
}

.bible-newcol-input::placeholder { color: var(--muted); }

.bible-sheet-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 16px;
}

/* ----- collections in the rail -------------------------------------------- */

.bible-collections {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 10px 0 4px;
}

.bible-filter {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--sans);
  font-size: 0.8rem;
  color: var(--ink-body);
  background: var(--bg);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  padding: 5px 11px;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
}

.bible-filter:hover { border-color: var(--hairline-deep); }

.bible-filter.is-active {
  background: var(--navy);
  border-color: var(--navy);
  color: var(--on-navy);
}

.bible-filter.is-active .bible-collection-count { color: rgba(var(--on-navy-rgb), 0.7); }

.bible-filter-x {
  margin-left: 2px;
  font-size: 0.95rem;
  line-height: 1;
  color: var(--muted);
  opacity: 0.75;
}

.bible-filter-x:hover { opacity: 1; color: var(--ink-body); }

.bible-filter.is-active .bible-filter-x { color: rgba(var(--on-navy-rgb), 0.75); }

@media (min-width: 1024px) {
  /* With room to spare the sheet stops hugging the bottom edge and floats
     clear of it, but it stays a BOTTOM sheet — the reasoning about thumbs
     holds on a laptop trackpad too, and one component is easier to keep
     right than two. */
  .bible-sheet { align-items: flex-end; padding-bottom: 28px; }

  .bible-sheet-panel {
    border-bottom: 1px solid var(--hairline);
    border-radius: 18px;
  }
}

/* ----- appearance control (account panel) --------------------------------- */

.acct-theme { margin-top: 18px; }

.acct-theme-label {
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 8px;
}

.acct-theme-row {
  display: inline-flex;
  background: var(--bg);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  overflow: hidden;
}

.acct-theme-btn {
  border: 0;
  background: none;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 0.8rem;
  color: var(--muted);
  padding: 8px 16px;
  cursor: pointer;
  transition: background 0.18s ease, color 0.18s ease;
}

.acct-theme-btn:hover { color: var(--ink-body); }

.acct-theme-btn.is-active {
  background: var(--navy);
  color: var(--on-navy);
}

/* A note under the plan grid, for facts about tiers this page does not
   sell. Quiet by design: it states a limit, it does not make an offer. */
.plans-foot {
  max-width: 640px;
  margin: 22px auto 0;
  text-align: center;
  font-size: 0.88rem;
  color: var(--muted);
}

/* ----- billing toggle (/plans) -------------------------------------------- */
/* Annual is the default because it is the better price, and the saving is
   stated once, here. There is no countdown and no struck-through figure:
   the discount is a standing fact about the plan, not an event. */

.billing-toggle {
  display: inline-flex;
  margin-top: 22px;
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  padding: 4px;
  gap: 4px;
}

.billing-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 0.88rem;
  color: var(--muted);
  background: none;
  border: 0;
  border-radius: 999px;
  padding: 9px 18px;
  cursor: pointer;
  transition: background 0.18s ease, color 0.18s ease;
}

.billing-btn:hover { color: var(--ink-body); }

.billing-btn.is-active {
  background: var(--navy);
  color: var(--on-navy);
}

/* The one marker. Quiet on purpose — it is information, not a klaxon. */
.billing-save {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--sage);
  background: var(--sage-tint);
  border-radius: 999px;
  padding: 3px 8px;
}

.billing-btn.is-active .billing-save {
  color: var(--navy);
  background: var(--card);
}

/* The annual total under the per-month headline. */
.plan-sub {
  font-size: 0.82rem;
  color: var(--muted);
  margin: 4px 0 0;
  min-height: 1.2em;
}

/* ==========================================================================
   THE HINT BAR — a selection, before anything has been decided about it
   --------------------------------------------------------------------------
   IT HAS NO SCRIM, and that is the entire reason it exists. The action sheet
   covers the viewport; opening it on the first tap put a scrim over every
   remaining verse, so on a phone the second tap of a range landed on the
   scrim and a range could not be built at all.

   So it is slim, it sits on the bottom edge, and every verse behind it stays
   reachable. Same card, hairline and radius as every other raised surface —
   no new tokens.
   ========================================================================== */

.bible-hint {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 60;
  display: flex;
  justify-content: center;
  padding: 0 12px calc(12px + env(safe-area-inset-bottom, 0px));
  /* The bar itself is the only thing that takes a tap. Nothing around it
     blocks the text — the container must not become an invisible scrim. */
  pointer-events: none;
}

.bible-hint[hidden] { display: none; }

.bible-hint-inner {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  max-width: 560px;
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 14px;
  box-shadow: var(--shadow-card-hover);
  padding: 10px 12px 10px 16px;
}

.bible-hint-text {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  line-height: 1.35;
}

.bible-hint-ref {
  display: block;
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1rem;
  color: var(--ink-heading);
}

.bible-hint-say {
  display: block;
  font-size: 0.8rem;
  color: var(--muted);
}

/* Over the limit: the same brown the app already uses for emphasis. Still
   no red — nothing on a verse is marked in red. */
.bible-hint-say.is-over { color: var(--cross-brown); }

.bible-hint-actions {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

/* While a mouse drag is in progress the browser's own text selection would
   fight it, so it is suspended — and ONLY then. Below the drag threshold
   this class is never added and selecting text to copy behaves as it did. */
.bible-chapter.is-dragging {
  user-select: none;
  -webkit-user-select: none;
  cursor: text;
}

/* The reading column ends above the bar rather than behind it. */
.bible-pane { padding-bottom: 84px; }

/* ----- making a collection from the rail ---------------------------------- */
/* The save sheet is not the only door. Someone tidying verses kept from
   answers has no chapter open, and should not have to find one. */

.bible-railcol { margin: 4px 0 10px; }

.bible-railcol-open {
  font-family: var(--sans);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--navy);
  background: none;
  border: 0;
  padding: 4px 2px;
  cursor: pointer;
  opacity: 0.8;
  transition: opacity 0.15s ease;
}

.bible-railcol-open:hover { opacity: 1; }

.bible-railcol .bible-newcol { margin-top: 0; }

/* ==========================================================================
   ASK RATING — "Was this helpful?"
   --------------------------------------------------------------------------
   Two quiet controls under a non-crisis answer. Hairline and muted at rest;
   the chosen one settles into sage — the same token a kept verse and a solved
   quiz use, so "chosen" reads the same everywhere it appears. There is NO red
   on the down control: nothing in this app is marked in red.
   ========================================================================== */
.ask-rate {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 22px;
}

.ask-rate-label {
  font-family: var(--sans);
  font-size: 0.82rem;
  color: var(--muted);
  margin-right: 2px;
}

.ask-rate-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  color: var(--muted);
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  cursor: pointer;
  transition: border-color 0.18s ease, color 0.18s ease, background-color 0.18s ease;
}

.ask-rate-btn svg {
  width: 17px;
  height: 17px;
  display: block;
}

.ask-rate-btn:hover {
  border-color: var(--hairline-deep);
  color: var(--ink-body);
}

/* Chosen — the same sage a kept verse and a settled quiz answer use. Both
   controls settle the same way; the down thumb is never red. */
.ask-rate-btn.is-selected {
  color: var(--sage);
  background: var(--sage-tint);
  border-color: var(--sage);
}

/* ==========================================================================
   THE STREAMED ANSWER — verses arrive one, two, three
   --------------------------------------------------------------------------
   The message itself needs no styling: it types into the same .word-card the
   buffered answer used. The verse cards start held and are released by
   app.js at a small stagger, so they read as arriving rather than as a list
   dropping in. The same reveal serves the fallback path, which is the point:
   the two paths must be indistinguishable.
   ========================================================================== */
.verse-card.verse-reveal-pending {
  opacity: 0;
  transform: translateY(7px);
}

.verse-card.verse-reveal-in {
  transition: opacity 0.45s var(--ease-out), transform 0.45s var(--ease-out);
  opacity: 1;
  transform: none;
}
