/* Bible Strands — four themes over one set of semantic tokens. Nothing below
   this block names a colour directly; a theme is a variable block, not a
   rewrite. Switch with data-theme on <html>. */

:root, :root[data-theme="navy"] {
  /* Navy — the ground of the logo art, with its cream lettering and gold.
     The default: the app opens in the same colours as the front page and the
     artwork that greets you, so the three read as one place. Bluer and warmer
     than Lamplight, which is closer to charcoal. */
  --bg:#111822; --surface:#172030; --surface-2:#1f2a3b; --surface-3:#2a3649;
  --line:#2c3a4f; --line-soft:#223043; --scrollbar:#2e3c51;

  --text:#e9dfc8; --text-dim:#a9b0bb; --text-faint:#76808f;
  --read:#e6dcc6; --read-2:#dcd3bf; --read-3:#d0c8b6;

  --accent:#b39ddb; --accent-soft:#6d5a96; --accent-deep:#8f76c4;
  --gold:#d8a657; --gold-soft:#8a6d36; --gold-deep:#a8702a; --gold-dim:#b89a5c; --gold-bright:#fff2d4; --on-gold:#141b25;
  --accent-dim:#a08cc8; --accent-bright:#efe8ff; --on-accent:#141b25;
  --info:#83aee3; --info-dim:#8aa0c2;
  --good:#a9bb6a; --good-dim:#93a070; --good-line:#3f5230;
  --danger:#d88787; --danger-line:#5a3232;

  --wj:#e8776f; --wj-2:#e2706b; --wj-bright:#ee7f77; --wj-dim:#cf918c; --gospel:#d68ad3; --gospel-dim:#b98bb7;

  --tile-bg:#1a2536; --tile-hi:#223047; --tile-back:#172131;
  --tile-root:#211f1b; --tile-root-line:#3d3526;
  --tile-place:#16222a; --tile-place-line:#274049;
  --tile-note:#22231d; --tile-note-line:#403e2b;
  --tile-dict:#172a2c; --tile-dict-line:#2c4d4f; --dict-accent:#6fc7c0;

  --thread-link:#415267; --thread-leap:#a384d0;
  --thread-echo:#5f9393; --thread-place:#4c6857;

  --map-sea:#0c1622; --map-land:#1a2535; --map-coast:#41597a;
  --map-water:#3a6789; --map-lake:#1c3650; --map-border:#2e3e53;
  --map-label:#5584a6; --map-grid:#1a2533;
  --canon-arc:#314055; --canon-arc-cross:#75649a;

  --shadow-tile: 0 6px 22px rgba(0,0,0,.42);
  --shadow-tile-hi: 0 12px 30px rgba(0,0,0,.55);
  --shadow-panel: 0 18px 50px rgba(0,0,0,.6);
  --tile-face: linear-gradient(180deg, rgba(255,255,255,.04), rgba(255,255,255,0) 42%);
  --tile-edge: rgba(255,255,255,.07);
  --canvas-dot: rgba(233,223,200,.05);
  --hover-wash: rgba(255,255,255,.06);
  --accent-wash: rgba(179,157,219,.14);
}

:root[data-theme="lamplight"] {
  /* Lamplight — ink and candle, for reading at night. */
  --bg:#0f1216; --surface:#161b21; --surface-2:#1e252d; --surface-3:#2a323c;
  --line:#2b333d; --line-soft:#222a33; --scrollbar:#2c343d;

  --text:#e6e3dc; --text-dim:#9aa3ad; --text-faint:#6b757f;
  --read:#ded9d0; --read-2:#d7d3ca; --read-3:#cfcbc2;

  --accent:#b39ddb; --accent-soft:#6d5a96; --accent-deep:#8f76c4;
  --gold:#d8a657; --gold-soft:#8a6d36; --gold-deep:#a8702a; --gold-dim:#b09256; --gold-bright:#fff2d4; --on-gold:#12161a;
  --accent-dim:#9c89c2; --accent-bright:#efe8ff; --on-accent:#12161a;
  --info:#7aa2d8; --info-dim:#8098b8;
  --good:#a3b565; --good-dim:#8f9b6b; --good-line:#3f5230;
  --danger:#cf7f7f; --danger-line:#5a3232;

  --wj:#e2706b; --wj-2:#dd6a65; --wj-bright:#e8776f; --wj-dim:#c98a86; --gospel:#d68ad3; --gospel-dim:#b98bb7;

  --tile-bg:#1a2028; --tile-hi:#222b35; --tile-back:#171d24;
  --tile-root:#1d1b16; --tile-root-line:#3a3222;
  --tile-place:#161d1c; --tile-place-line:#26383a;
  --tile-note:#20201a; --tile-note-line:#3d3b28;
  --tile-dict:#16242a; --tile-dict-line:#2b4448; --dict-accent:#68bdb6;

  --thread-link:#3a4652; --thread-leap:#9a7bc8;
  --thread-echo:#5c8a8a; --thread-place:#47614f;

  --map-sea:#0a141e; --map-land:#17202a; --map-coast:#3d5468;
  --map-water:#35607f; --map-lake:#1a3348; --map-border:#2b3a49;
  --map-label:#4d7a99; --map-grid:#18222c;
  --canon-arc:#2e3a46; --canon-arc-cross:#6f5f8c;

  --shadow-tile: 0 6px 22px rgba(0,0,0,.42);
  --shadow-tile-hi: 0 12px 30px rgba(0,0,0,.55);
  --shadow-panel: 0 18px 50px rgba(0,0,0,.6);
  --tile-face: linear-gradient(180deg, rgba(255,255,255,.035), rgba(255,255,255,0) 42%);
  --tile-edge: rgba(255,255,255,.07);
  --canvas-dot: rgba(255,255,255,.045);
  --hover-wash: rgba(255,255,255,.06);
  --accent-wash: rgba(179,157,219,.13);
}

:root[data-theme="parchment"] {
  /* Parchment — aged paper and ink, for daylight. */
  --bg:#e8ddc8; --surface:#f6efe1; --surface-2:#ece2cd; --surface-3:#e0d3b9;
  --line:#cbbb9c; --line-soft:#ded2b8; --scrollbar:#c6b79b;

  --text:#2d2721; --text-dim:#6a5d4b; --text-faint:#938471;
  --read:#241f1a; --read-2:#2f2922; --read-3:#3b3429;

  --accent:#6a4c9c; --accent-soft:#a996cc; --accent-deep:#523a7f;
  --gold:#9a6512; --gold-soft:#c0a065; --gold-deep:#7c4f0d; --gold-dim:#8a6c38; --gold-bright:#5c3c08; --on-gold:#fdf8ee;
  --accent-dim:#6f5f92; --accent-bright:#3a2562; --on-accent:#fdf8ee;
  --info:#2f5f96; --info-dim:#4a739f;
  --good:#5b7226; --good-dim:#6d8240; --good-line:#b9c79a;
  --danger:#9d3a35; --danger-line:#d8b3b0;

  --wj:#b3322c; --wj-2:#a92e28; --wj-bright:#c03a33; --wj-dim:#8d443f; --gospel:#9a3f97; --gospel-dim:#86598a;

  --tile-bg:#fbf6ea; --tile-hi:#fffdf6; --tile-back:#f4ecdb;
  --tile-root:#f6eed9; --tile-root-line:#d8c49a;
  --tile-place:#eef2e4; --tile-place-line:#bccaa8;
  --tile-note:#fbf3d6; --tile-note-line:#ddcb93;
  --tile-dict:#ebf5f3; --tile-dict-line:#b7d9d4; --dict-accent:#2f7d78;

  --thread-link:#a4977f; --thread-leap:#7b5bb0;
  --thread-echo:#3f7d7d; --thread-place:#5b7d5f;

  --map-sea:#cddbe4; --map-land:#efe6d2; --map-coast:#8ba3b5;
  --map-water:#5f92b5; --map-lake:#bcd4e4; --map-border:#c3b79e;
  --map-label:#5a7f99; --map-grid:#ddd2bb;
  --canon-arc:#c3b59a; --canon-arc-cross:#a08cc0;

  --shadow-tile: 0 2px 4px rgba(90,70,40,.10), 0 8px 20px rgba(90,70,40,.13);
  --shadow-tile-hi: 0 4px 8px rgba(90,70,40,.14), 0 16px 34px rgba(90,70,40,.20);
  --shadow-panel: 0 16px 44px rgba(80,62,38,.24);
  --tile-face: linear-gradient(180deg, rgba(255,255,255,.75), rgba(255,255,255,0) 46%);
  --tile-edge: rgba(255,255,255,.9);
  --canvas-dot: rgba(120,98,60,.13);
  --hover-wash: rgba(120,98,60,.09);
  --accent-wash: rgba(106,76,156,.12);
}

:root {
  --radius: 10px;
  --rail-w: 420px;
  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, "Times New Roman", serif;
  --sans: ui-sans-serif, system-ui, "Segoe UI", Inter, Roboto, sans-serif;
  --hebrew: "SBL Hebrew", "Ezra SIL", "Times New Roman", "Segoe UI Historic", serif;
  --greek: "SBL Greek", "Palatino Linotype", Georgia, serif;
}

:root[data-theme="linen"] {
  /* Linen — cool daylight, quieter than parchment. */
  --bg:#e7eaee; --surface:#f7f9fb; --surface-2:#eceff3; --surface-3:#dfe4ea;
  --line:#c9d1da; --line-soft:#dde3ea; --scrollbar:#c3ccd6;

  --text:#1e242b; --text-dim:#5b6673; --text-faint:#8b96a3;
  --read:#191f25; --read-2:#232a32; --read-3:#2f3742;

  --accent:#5f4796; --accent-soft:#a595c9; --accent-deep:#4a3579;
  --gold:#8a5a12; --gold-soft:#b89a62; --gold-deep:#6f4708; --gold-dim:#7d6436; --gold-bright:#503505; --on-gold:#ffffff;
  --accent-dim:#685b8c; --accent-bright:#33215a; --on-accent:#ffffff;
  --info:#2c5f9e; --info-dim:#4b76a4;
  --good:#4e7030; --good-dim:#638347; --good-line:#b3c7a2;
  --danger:#9c3a3a; --danger-line:#d9b4b4;

  --wj:#b0302e; --wj-2:#a52b29; --wj-bright:#bd3936; --wj-dim:#8a4241; --gospel:#9a3f97; --gospel-dim:#86598a;

  --tile-bg:#ffffff; --tile-hi:#ffffff; --tile-back:#f3f6f9;
  --tile-root:#fdf7e9; --tile-root-line:#ddc99f;
  --tile-place:#eef5ee; --tile-place-line:#bcd2bd;
  --tile-note:#fdf8e3; --tile-note-line:#ddd0a0;
  --tile-dict:#eef6f5; --tile-dict-line:#bcdcd8; --dict-accent:#2a7470;

  --thread-link:#9aa6b4; --thread-leap:#7359ad;
  --thread-echo:#38787c; --thread-place:#557d5c;

  --map-sea:#d4e2ec; --map-land:#eef1f4; --map-coast:#89a2b4;
  --map-water:#5a8fb4; --map-lake:#c2d9e8; --map-border:#c2ccd6;
  --map-label:#587e99; --map-grid:#dde4ec;
  --canon-arc:#bcc6d2; --canon-arc-cross:#9a8cc0;

  --shadow-tile: 0 1px 3px rgba(30,45,65,.10), 0 8px 20px rgba(30,45,65,.10);
  --shadow-tile-hi: 0 4px 8px rgba(30,45,65,.13), 0 16px 34px rgba(30,45,65,.16);
  --shadow-panel: 0 16px 44px rgba(28,42,60,.20);
  --tile-face: linear-gradient(180deg, rgba(255,255,255,.9), rgba(255,255,255,0) 44%);
  --tile-edge: rgba(255,255,255,1);
  --canvas-dot: rgba(60,80,105,.12);
  --hover-wash: rgba(40,60,85,.07);
  --accent-wash: rgba(95,71,150,.12);
}



* { box-sizing: border-box; }

html, body {
  margin: 0; height: 100%;
  background: var(--bg); color: var(--text);
  font-family: var(--sans); font-size: 15px; line-height: 1.5;
  overflow: hidden;
}

body { display: flex; flex-direction: column; }

button, input, select, textarea { font: inherit; color: inherit; }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: var(--scrollbar); border-radius: 6px; }
::-webkit-scrollbar-track { background: transparent; }

.dim   { color: var(--text-dim); }
.faint { color: var(--text-faint); }
.hint  { color: var(--text-faint); font-size: 12.5px; }

/* ───────────────────────────────────────────────────────────── top bar ── */

.topbar {
  display: flex; align-items: center; gap: 20px;
  padding: 0 16px; height: 54px; flex: 0 0 54px;
  background: var(--surface); border-bottom: 1px solid var(--line);
}

.brand { display: flex; align-items: center; gap: 10px; }
.brand h1 { font: 600 16px/1 var(--serif); margin: 0; letter-spacing: .3px; }
.mark {
  width: 10px; height: 18px; border-radius: 50% 50% 46% 46% / 62% 62% 38% 38%;
  background: linear-gradient(180deg, var(--gold), var(--gold-deep));
  box-shadow: 0 0 12px rgba(216,166,87,.45);
}

.tabs { display: flex; gap: 2px; }
.tab {
  background: none; border: 0; padding: 7px 14px; border-radius: 7px;
  color: var(--text-dim); cursor: pointer; font-size: 13.5px;
}
.tab:hover { background: var(--surface-2); color: var(--text); }
.tab.is-active { background: var(--surface-2); color: var(--accent); }

.topbar-right { margin-left: auto; display: flex; align-items: center; gap: 12px; }

.search-wrap { position: relative; }
#search {
  width: 340px; padding: 8px 12px; border-radius: 8px;
  background: var(--bg); border: 1px solid var(--line); outline: none;
}
#search:focus { border-color: var(--accent-soft); }

.results {
  position: absolute; top: 40px; right: 0; width: 520px; max-height: 60vh;
  overflow: auto; background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: 0 18px 50px rgba(0,0,0,.6); z-index: 60;
}
.result {
  padding: 9px 13px; cursor: pointer; border-bottom: 1px solid var(--line-soft);
  display: grid; grid-template-columns: 130px 1fr; gap: 10px; align-items: baseline;
}
.result:last-child { border-bottom: 0; }
.result:hover, .result.sel { background: var(--surface-2); }
.result .r-ref { color: var(--accent); font-size: 12.5px; white-space: nowrap; }
.result .r-txt { font-family: var(--serif); font-size: 13.5px; color: var(--text-dim); }
.result .r-txt b { color: var(--text); font-weight: 600; }
.results .group-label {
  padding: 6px 13px; font-size: 11px; letter-spacing: .09em; text-transform: uppercase;
  color: var(--text-faint); background: var(--bg); position: sticky; top: 0;
}

/* global reading-version switch */
.version-pick { display: flex; gap: 2px; background: var(--bg); border: 1px solid var(--line); border-radius: 8px; padding: 2px; }
.version-pick button {
  background: none; border: 0; padding: 4px 10px; border-radius: 6px;
  color: var(--text-dim); cursor: pointer; font-size: 12.5px; white-space: nowrap;
}
.version-pick button:hover { color: var(--text); background: var(--surface-2); }
.version-pick button.on { background: var(--surface-2); color: var(--accent); }

/* "the model is reasoning" indicator */
.ai-status { color: var(--text-faint); font-size: 12.5px; font-style: italic; }
.ai-status::after {
  content: '·'; margin-left: 4px; animation: pulse 1.2s ease-in-out infinite; color: var(--accent);
}
@keyframes pulse { 0%, 100% { opacity: .25; } 50% { opacity: 1; } }


/* ───────────────────────────────────────────────────────────── layout ── */

.view { display: none; flex: 1; min-height: 0; }
.view.is-active { display: flex; }

#view-daily, #view-saved { flex-direction: column; overflow: auto; }

.canvas-wrap { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.rail {
  width: var(--rail-w); flex: 0 0 var(--rail-w);
  border-left: 1px solid var(--line); background: var(--surface);
  overflow: auto; padding: 16px;
}
.rail-empty { color: var(--text-faint); font-size: 13.5px; padding: 28px 6px; text-align: center; }

/* ───────────────────────────────────────────────────────── thread bar ── */

.thread-bar {
  display: flex; align-items: center; gap: 8px; padding: 8px 12px;
  border-bottom: 1px solid var(--line); background: var(--surface); flex: 0 0 auto;
}
.thread-bar select {
  background: var(--bg); border: 1px solid var(--line); color: var(--text);
  border-radius: 7px; padding: 5px 8px; max-width: 230px; outline: none;
}
.sep { width: 1px; height: 20px; background: var(--line); }

.btn {
  background: var(--surface-2); border: 1px solid var(--line); color: var(--text);
  padding: 5px 11px; border-radius: 7px; cursor: pointer; font-size: 13px;
}
.btn:hover { background: var(--surface-3); border-color: var(--accent-soft); }
.btn.ghost { background: transparent; }
.btn.ghost:hover { background: var(--surface-2); }
.btn.danger:hover { border-color: var(--danger); color: var(--danger); }
.btn.is-on { background: var(--accent-soft); border-color: var(--accent); color: var(--on-accent); }
.btn:disabled { opacity: .4; cursor: default; }

/* ───────────────────────────────────────────────────────────── canvas ── */

.canvas {
  position: relative; flex: 1; overflow: hidden; cursor: grab;
  background:
    radial-gradient(circle at 1px 1px, rgba(255,255,255,.045) 1px, transparent 0) 0 0 / 28px 28px,
    var(--bg);
}
.canvas.grabbing { cursor: grabbing; }
.canvas.linking  { cursor: crosshair; }

/* The edge layer and the tile layer are given the SAME transform, so they must
   scale about the same point. transform-origin defaults to 50% 50%, which made
   the SVG scale about its centre while the tiles scaled about their top-left —
   the lines drifted off the tiles as soon as you zoomed. Both are 0 0. */
.edges {
  position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none; overflow: visible;
  transform-origin: 0 0;
}
.world { position: absolute; top: 0; left: 0; transform-origin: 0 0; will-change: transform; }

.empty {
  position: absolute; inset: 0; display: grid; place-content: center;
  text-align: center; pointer-events: none; color: var(--text-faint);
}
/* display:grid above outranks the [hidden] attribute's display:none, so the
   placeholder has to be hidden explicitly or it floats over a full canvas. */
.empty[hidden] { display: none; }
.empty p { margin: 4px 0; }

/* tiles */

.tile {
  position: absolute; width: 268px; background: var(--tile-bg);
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 10px 12px 11px; cursor: pointer; user-select: none;
  box-shadow: 0 6px 22px rgba(0,0,0,.42);
  transition: border-color .12s, box-shadow .12s, transform .12s;
}
.tile:hover { border-color: var(--accent-soft); transform: translateY(-1px); }
.tile.sel {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent), 0 10px 30px rgba(0,0,0,.55);
}
.tile.dragging { cursor: grabbing; z-index: 30; }
.tile.link-src { border-color: var(--info); box-shadow: 0 0 0 1px var(--info); }

.tile .t-head {
  display: flex; align-items: baseline; gap: 8px; margin-bottom: 5px;
}
.tile .t-ref { color: var(--accent); font-size: 12.5px; font-weight: 600; letter-spacing: .02em; }
.tile .t-badge {
  margin-left: auto; font-size: 10.5px; color: var(--text-faint);
  border: 1px solid var(--line); border-radius: 20px; padding: 1px 7px; white-space: nowrap;
}
/* The verse scrolls rather than being clipped. Some verses are long and a
   tile that cuts off mid-word with no way to read the rest is worse than a
   scrollbar. */
.tile .t-text {
  font-family: var(--serif); font-size: 14px; line-height: 1.45; color: var(--read-2);
  flex: 1 1 auto; min-height: 0; overflow-y: auto; padding-right: 4px;
}
.tile .t-why {
  margin-top: 7px; font-size: 11.5px; color: var(--text-faint);
  border-top: 1px dashed var(--line-soft); padding-top: 6px;
}

/* Verse tiles turn over, like the daily cards. */
.tile.flippable {
  height: 178px; padding: 0; perspective: 1400px; background: transparent;
  border: 0; box-shadow: none;
}
.tile-inner {
  position: relative; width: 100%; height: 100%;
  transition: transform .5s cubic-bezier(.4,.1,.2,1); transform-style: preserve-3d;
}
.tile.flipped .tile-inner { transform: rotateY(180deg); }

.tile-face {
  position: absolute; inset: 0; backface-visibility: hidden;
  background: var(--tile-bg); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 10px 12px 11px; overflow: hidden; display: flex; flex-direction: column;
  box-shadow: 0 6px 22px rgba(0,0,0,.42);
}
.tile.flippable:hover .tile-face { border-color: var(--accent-soft); }
.tile.flippable.sel .tile-face { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent), 0 10px 30px rgba(0,0,0,.55); }
.tile.flippable.link-src .tile-face { border-color: var(--info); box-shadow: 0 0 0 1px var(--info); }
.tile-back { transform: rotateY(180deg); background: var(--tile-back); }

.t-flip {
  margin-left: auto; background: none; border: 0; color: var(--text-faint);
  cursor: pointer; font-size: 13px; line-height: 1; padding: 2px 3px; border-radius: 4px;
}
.t-flip:hover { color: var(--accent); background: var(--surface-2); }

.t-back-body {
  flex: 1; overflow: auto; font-size: 12.8px; line-height: 1.58;
  color: var(--read-3); white-space: pre-wrap; padding-right: 4px;
}
.t-back-body strong { color: var(--accent); }

.tile.kind-root { width: 218px; background: var(--tile-root); border-color: var(--tile-root-line); }
.tile.kind-root .t-heb {
  font-family: var(--hebrew); font-size: 26px; direction: rtl; color: var(--accent);
  line-height: 1.3; margin: 2px 0;
}
.tile.kind-root .t-grk { font-family: var(--greek); font-size: 22px; color: var(--accent); }
.tile.kind-root .t-def { font-size: 12px; color: var(--text-dim); }

.tile.kind-place { width: 210px; background: var(--tile-place); border-color: var(--tile-place-line); }
.tile.kind-place .t-ref { color: var(--good); }

.tile.kind-note { width: 230px; background: var(--tile-note); border-color: var(--tile-note-line); }
.tile.kind-note textarea {
  width: 100%; background: transparent; border: 0; outline: none; resize: vertical;
  font-family: var(--serif); font-size: 13.5px; color: var(--text); min-height: 62px;
}

/* edges */

/* One colour per kind of connection, used consistently everywhere:
   link · leap · root · echo · place · your own */
.edge { fill: none; stroke: var(--thread-link); stroke-width: 1.4; }
.edge.link  { stroke: var(--thread-link); }
.edge.leap  { stroke: var(--thread-leap); stroke-width: 1.7; stroke-dasharray: 9 4; }
.edge.root  { stroke: var(--accent-soft); stroke-dasharray: 4 3; }
.edge.echo  { stroke: var(--thread-echo); stroke-dasharray: 1 4; stroke-linecap: round; }
.edge.user  { stroke: var(--info); stroke-width: 1.8; }
.edge.place { stroke: var(--thread-place); stroke-dasharray: 2 4; }
.edge.cited { stroke: var(--dict-accent); stroke-dasharray: 6 3 1 3; }
.edge.hot   { stroke: var(--accent); stroke-width: 2.2; }

/* the same vocabulary on tiles */
.tile .t-why[data-kind="leap"] { color: var(--thread-leap); }
.tile .t-why[data-kind="echo"] { color: var(--thread-echo); }
.tile .t-why[data-kind="root"] { color: var(--accent-soft); }
.edge-label {
  fill: var(--text-faint); font: 10.5px var(--sans); text-anchor: middle;
  paint-order: stroke; stroke: var(--bg); stroke-width: 3px;
}

/* ─────────────────────────────────────────────────────────────── rail ── */

.rail h3 { margin: 0 0 2px; font: 600 15px/1.3 var(--serif); color: var(--accent); }
.rail .r-sub { font-size: 12px; color: var(--text-faint); margin-bottom: 12px; }

.rail-scripture {
  font-family: var(--serif); font-size: 16.5px; line-height: 1.62;
  color: var(--read); margin: 0 0 12px;
}

.seg { display: flex; gap: 3px; margin: 10px 0; flex-wrap: wrap; }
.seg button {
  background: var(--bg); border: 1px solid var(--line); color: var(--text-dim);
  padding: 4px 10px; border-radius: 6px; cursor: pointer; font-size: 12.5px;
}
.seg button.on { background: var(--surface-2); color: var(--accent); border-color: var(--accent-soft); }

.rail-section { border-top: 1px solid var(--line-soft); margin-top: 14px; padding-top: 12px; }
.rail-section > h4 {
  margin: 0 0 8px; font-size: 11px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--text-faint); font-weight: 600;
}

/* interlinear */

.interlinear { display: flex; flex-wrap: wrap; gap: 6px; direction: rtl; }
.interlinear.ltr { direction: ltr; }
.iw {
  min-width: 56px; text-align: center; padding: 5px 7px; border-radius: 7px;
  border: 1px solid transparent; cursor: pointer;
}
.iw:hover { background: var(--surface-2); border-color: var(--accent-soft); }
.iw .w-orig { font-family: var(--hebrew); font-size: 21px; color: var(--text); line-height: 1.5; }
.interlinear.ltr .w-orig { font-family: var(--greek); font-size: 18px; }
.iw .w-tr  { font-size: 10.5px; color: var(--accent); direction: ltr; }
.iw .w-lit { font-size: 11.5px; color: var(--text-dim); direction: ltr; }
.iw .w-str { font-size: 9.5px; color: var(--text-faint); direction: ltr; }

/* literal line: the verse as the original orders it */
.literal-line {
  font-size: 14px; line-height: 1.7; color: var(--read-3);
  background: var(--bg); border: 1px solid var(--line-soft);
  border-radius: 8px; padding: 10px 12px; font-family: var(--serif);
}
.literal-line .lw { cursor: pointer; border-bottom: 1px dotted var(--line); }
.literal-line .lw:hover { color: var(--accent); border-color: var(--accent); }
.literal-line .sep { color: var(--text-faint); }

.link-row {
  display: grid; grid-template-columns: 112px 1fr auto; gap: 9px;
  padding: 7px 6px; border-radius: 7px; cursor: pointer; align-items: baseline;
}
.link-row:hover { background: var(--surface-2); }
.link-row .l-ref { color: var(--accent); font-size: 12.5px; }
.link-row .l-txt {
  font-family: var(--serif); font-size: 13px; color: var(--text-dim);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.link-row .l-votes { font-size: 10.5px; color: var(--text-faint); }

.chips { display: flex; flex-wrap: wrap; gap: 5px; }
.chip {
  font-size: 11.5px; padding: 3px 9px; border-radius: 20px;
  border: 1px solid var(--line); color: var(--text-dim); cursor: pointer; background: var(--bg);
}
.chip:hover { border-color: var(--accent-soft); color: var(--accent); }
.chip.on { background: var(--accent-soft); color: var(--on-accent); border-color: var(--accent); }

textarea.note {
  width: 100%; min-height: 84px; background: var(--bg); color: var(--text);
  border: 1px solid var(--line); border-radius: 8px; padding: 9px 11px;
  resize: vertical; outline: none; font-family: var(--serif); font-size: 14px;
}
textarea.note:focus { border-color: var(--accent-soft); }

/* AI block */

.ask-row { display: flex; gap: 6px; }
.ask-row input {
  flex: 1; background: var(--bg); border: 1px solid var(--line);
  border-radius: 7px; padding: 7px 10px; outline: none;
}
.ask-row input:focus { border-color: var(--accent-soft); }

.ai-out {
  margin-top: 10px; font-size: 13.5px; line-height: 1.62; color: var(--read-2);
  white-space: pre-wrap; word-wrap: break-word;
}
.ai-out .vref {
  color: var(--accent); cursor: pointer; border-bottom: 1px dotted var(--accent-soft);
}
.ai-out .vref:hover { background: var(--accent-wash); }
.ai-out strong { color: var(--text); }
.ai-busy::after {
  content: '▍'; animation: blink 1s steps(2) infinite; color: var(--accent);
}
@keyframes blink { 50% { opacity: 0; } }

/* ──────────────────────────────────────────────────────── daily cards ── */

.daily-head {
  display: flex; align-items: flex-end; gap: 20px; padding: 22px 26px 12px; flex: 0 0 auto;
}
.daily-head h2 { margin: 0; font: 600 21px var(--serif); }
/* A small copy of the canvas legend under the heading (daily.js _key). */
.daily-key {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px;
  margin-top: 6px; font-size: 12px; color: var(--text-dim);
}
.dk-item { display: inline-flex; align-items: center; gap: 6px; cursor: help; }
.dk-stripe { width: 3px; height: 14px; border-radius: 2px; }
.dk-stripe.is-ot { background: var(--good); }
.dk-stripe.is-gospels { background: var(--gospel); }
.dk-stripe.is-nt { background: var(--info); }
.dk-sep { width: 1px; height: 14px; background: var(--line); }
.dk-words { font-family: var(--serif); font-style: italic; font-size: 13px; }
.daily-nav { margin-left: auto; display: flex; gap: 6px; align-items: center; }
.daily-nav input[type=date] {
  background: var(--surface); border: 1px solid var(--line); color: var(--text);
  border-radius: 7px; padding: 5px 9px; outline: none; color-scheme: dark;
}

.daily-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(310px, 1fr));
  gap: 16px; padding: 8px 26px 40px;
}
/* The run of days kept, and the Revisit cards coming back (daily.js _returning). */
.daily-streak { display: flex; align-items: center; gap: 10px; margin-top: 6px; font-size: 12px; color: var(--text-faint); cursor: help; }
@media (max-width: 700px) {
  .daily-head { flex-wrap: wrap; }
  .daily-head > div:first-child { flex: 1 1 100%; }
}
.ds-dots { display: inline-flex; gap: 4px; }
.ds-dot { width: 8px; height: 8px; border-radius: 50%; box-shadow: inset 0 0 0 1.5px var(--line); cursor: help; }
.ds-dot.on { background: var(--good); box-shadow: none; }
.ds-dot.today { outline: 1px solid var(--text-faint); outline-offset: 2px; }
.daily-back { border-top: 1px solid var(--line); margin: 0 26px; padding-top: 14px; }
.daily-back h3 { margin: 0; font: 600 16px var(--serif); }
.daily-back p { margin: 4px 0 0; font-size: 13px; }
.daily-back .daily-grid { padding: 12px 0 40px; }

.card { perspective: 1600px; height: 260px; cursor: pointer; }
.card-inner {
  position: relative; width: 100%; height: 100%;
  transition: transform .55s cubic-bezier(.4,.1,.2,1); transform-style: preserve-3d;
}
.card.flipped .card-inner { transform: rotateY(180deg); }

.card-face {
  position: absolute; inset: 0; backface-visibility: hidden;
  border: 1px solid var(--line); border-radius: 12px; padding: 16px 17px;
  background: var(--tile-bg); display: flex; flex-direction: column; overflow: hidden;
}
.card:hover .card-face { border-color: var(--accent-soft); }
.card-back { transform: rotateY(180deg); background: var(--tile-back); }

.card-ref { color: var(--accent); font-size: 13px; font-weight: 600; margin-bottom: 8px; }
.card-text {
  font-family: var(--serif); font-size: 15.5px; line-height: 1.55; color: var(--read);
  flex: 1 1 auto; min-height: 0; overflow-y: auto; padding-right: 4px;
}
.card-foot {
  margin-top: 10px; display: flex; align-items: center; gap: 8px;
  font-size: 11px; color: var(--text-faint); flex: 0 0 auto;
}
.card-foot .spacer { margin-left: auto; }

.card-back .card-body {
  flex: 1; overflow: auto; font-size: 12.8px; line-height: 1.58; color: var(--read-3);
  white-space: pre-wrap; padding-right: 4px;
}
.card-back .card-body strong { color: var(--accent); }

/* Where the verse sits, down the left edge, as on a canvas tile. (A reviewed
   card used to take a green edge here; green is the Old Testament's, so the
   tick by the reference says reviewed instead.) */
.card.is-gospels .card-face { border-left: 3px solid var(--gospel); }
.card.is-nt      .card-face { border-left: 3px solid var(--info); }
.card.is-ot      .card-face { border-left: 3px solid var(--good); }
.card.is-gospels .card-ref { color: var(--gospel); }
.card.is-nt      .card-ref { color: var(--info); }
.card.is-ot      .card-ref { color: var(--good-dim); }
/* A reviewed card says so on both sides, by the reference, as canvas tiles do. */
.card.reviewed .card-ref-row > span:first-child::after {
  content: '✓'; margin-left: 7px; display: inline-grid; place-items: center;
  width: 17px; height: 17px; border-radius: 50%; vertical-align: 1px;
  background: var(--good); color: var(--bg); font-size: 10.5px; font-weight: 700;
}
.card.reviewed .card-front { background: color-mix(in srgb, var(--good) 7%, var(--tile-bg)); }
.card-ref-row > span:first-child { margin-right: auto; }
.card-ref-row .t-flip + .t-flip { margin-left: 2px; }   /* ▤ and ⤢ side by side */
.mini {
  background: transparent; border: 1px solid var(--line); color: var(--text-dim);
  border-radius: 6px; padding: 2px 8px; font-size: 11px; cursor: pointer;
}
.mini:hover { border-color: var(--accent-soft); color: var(--accent); }
.mini.on { background: var(--good); color: var(--on-accent); border-color: var(--good); }

/* ───────────────────────────────────────────────────────────────  map ── */

.map-wrap { flex: 1; display: flex; flex-direction: column; min-width: 0; }
.map-tools {
  display: flex; align-items: center; gap: 12px; padding: 9px 14px;
  border-bottom: 1px solid var(--line); background: var(--surface);
}
.map-tools input[type=search] {
  background: var(--bg); border: 1px solid var(--line); border-radius: 7px;
  padding: 6px 10px; width: 240px; outline: none;
}
.chk { display: flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--text-dim); }

.map { flex: 1; overflow: hidden; background: var(--map-sea); cursor: grab; position: relative; }
.map.grabbing { cursor: grabbing; }
.map svg { width: 100%; height: 100%; display: block; }

.place-dot { fill: var(--good); opacity: .8; cursor: pointer; transition: r .12s, fill .12s; }
.place-dot:hover { fill: var(--accent); opacity: 1; }
.place-dot.sel { fill: var(--accent); opacity: 1; }
.place-label {
  fill: var(--text-dim); font: 10px var(--sans); pointer-events: none;
  paint-order: stroke; stroke: var(--map-sea); stroke-width: 3px;
}
.map-graticule { stroke: var(--map-grid); stroke-width: .5; fill: none; }
/* Sea is the page background; land is filled over it, so the two read apart
   at a glance. The 10m coastline is stroked on top for the real edge. */
.map-land  { fill: var(--map-land); stroke: none; }
.map-coast { fill: none; stroke: var(--map-coast); stroke-width: .9; stroke-linejoin: round; }
.map-border {
  fill: none; stroke: var(--map-border); stroke-width: .7; stroke-dasharray: 3 3; opacity: .75;
}
.sea-label {
  fill: var(--map-label); font: italic 11px var(--serif); text-anchor: middle;
  pointer-events: none; letter-spacing: .06em;
}

/* ────────────────────────────────────────────────────────────── saved ── */

.saved-head {
  display: flex; align-items: center; gap: 16px; padding: 22px 26px 12px; flex-wrap: wrap;
}
.saved-head h2 { margin: 0; font: 600 21px var(--serif); }
.saved-head input {
  background: var(--surface); border: 1px solid var(--line); border-radius: 8px;
  padding: 7px 11px; width: 320px; outline: none;
}
.saved-head input:focus { border-color: var(--accent-soft); }

.saved-list { padding: 6px 26px 40px; display: flex; flex-direction: column; gap: 10px; }
.saved-item {
  border: 1px solid var(--line); border-radius: 10px; padding: 13px 15px;
  background: var(--surface); cursor: pointer;
}
.saved-item:hover { border-color: var(--accent-soft); }
.saved-item .s-top { display: flex; align-items: baseline; gap: 10px; margin-bottom: 5px; }
.saved-item .s-ref { color: var(--accent); font-size: 13px; font-weight: 600; }
.saved-item .s-when { margin-left: auto; font-size: 11px; color: var(--text-faint); }
.saved-item .s-text { font-family: var(--serif); font-size: 14.5px; color: var(--read-2); }
.saved-item .s-note {
  margin-top: 8px; padding-left: 11px; border-left: 2px solid var(--accent-soft);
  font-size: 13px; color: var(--text-dim); white-space: pre-wrap;
}
.pill {
  font-size: 10.5px; padding: 1px 8px; border-radius: 20px;
  border: 1px solid var(--line); color: var(--text-faint);
}
.pill.keep  { color: var(--good);  border-color: var(--good-line); }
.pill.revisit { color: var(--accent);   border-color: var(--accent-soft); }
.pill.unclear { color: var(--danger);   border-color: var(--danger-line); }

/* ────────────────────────────────────────────────────────────── misc ── */

.toast {
  position: fixed; bottom: 22px; left: 50%; transform: translateX(-50%);
  background: var(--surface-2); border: 1px solid var(--accent-soft); color: var(--text);
  padding: 9px 16px; border-radius: 8px; font-size: 13px; z-index: 200;
  box-shadow: 0 10px 34px rgba(0,0,0,.6);
}

a { color: var(--info); }
.ext {
  font-size: 12px; color: var(--info); text-decoration: none;
  border: 1px solid var(--line); border-radius: 6px; padding: 3px 9px;
}
.ext:hover { border-color: var(--info); background: color-mix(in srgb, var(--info) 12%, transparent); }

@media (max-width: 1100px) {
  :root { --rail-w: 340px; }
  #search { width: 220px; }
}
@media (max-width: 820px) {
  .topbar { flex-wrap: wrap; height: auto; padding: 8px 12px; gap: 10px; }
  .rail { position: absolute; right: 0; top: 0; bottom: 0; z-index: 80; }
  .view.is-active { position: relative; }
  /* Here the panel covers the view, and it used to cover its own ✕ too.
     Above it, and saying plainly what it does. (.view .rail-close: the
     desktop rule for the button comes later in this file.) */
  .view .rail-close {
    z-index: 85; top: 10px; right: 12px; width: auto; height: auto;
    padding: 7px 14px; font-size: 0; border-radius: 16px;
    background: var(--surface-3); color: var(--text); border-color: var(--line);
  }
  .view .rail-close::after { content: '← Back'; font-size: 13px; font-weight: 600; }
  /* Room for it above the panel's heading. (.view .rail: the phone rule
     further down sets the panel's padding and must not undo this.) */
  .view .rail { padding-top: 52px; }
}

/* ────────────────────────────────────────────────────────────── canon ── */

.canon-wrap { flex: 1; display: flex; flex-direction: column; min-width: 0; }
.canon-tools {
  display: flex; align-items: center; gap: 14px; padding: 9px 14px;
  border-bottom: 1px solid var(--line); background: var(--surface); flex-wrap: wrap;
}
.canon-tools input[type=range] { width: 130px; accent-color: var(--accent); }

.canon { flex: 1; overflow: hidden; background: var(--map-sea); cursor: grab; position: relative; }
.canon.grabbing { cursor: grabbing; }
.canon svg { width: 100%; height: 100%; display: block; }
.canon-loading { position: absolute; inset: 0; display: grid; place-content: center; }

.canon-heading {
  fill: var(--accent); font: 600 13px var(--serif); letter-spacing: .06em;
}

/* arcs between books: thickness is the weight of the thread */
.canon-arc { fill: none; stroke: var(--canon-arc); opacity: .55; }
.canon-arc.crosses { stroke: var(--canon-arc-cross); opacity: .7; }
.canon-arc.on { stroke: var(--accent); opacity: 1; }

.canon-beyond { fill: none; opacity: .5; stroke-width: 1.3; }
.canon-beyond.on { opacity: 1; stroke-width: 2; }

.canon-book { cursor: pointer; }
.canon-box {
  fill: var(--tile-bg); stroke: var(--line); stroke-width: 1;
}
.canon-book:hover .canon-box { stroke: var(--accent-soft); fill: var(--tile-hi); }
.canon-book.on .canon-box { stroke: var(--accent); stroke-width: 1.6; fill: var(--tile-hi); }
.canon-box.beyond { fill: var(--tile-root); stroke: var(--tile-root-line); stroke-dasharray: 3 2; }
.canon-label { fill: var(--text); font: 11px var(--sans); pointer-events: none; }
.canon-mark { fill: var(--accent); opacity: .8; }

.kind-tag {
  display: inline-block; margin-top: 4px; margin-right: 5px;
  font-size: 10px; letter-spacing: .04em; text-transform: uppercase;
  border: 1px solid var(--line); border-radius: 20px; padding: 1px 7px;
  color: var(--text-faint);
}
.beyond-row { grid-template-columns: 118px 1fr auto; align-items: start; }
.beyond-row .l-txt { -webkit-line-clamp: 4; }

/* ───────────────────────────────────────────────── words of Jesus ── */

/* Red letter, as modern Bibles print it. Tuned to stay readable on the dark
   surface rather than using a pure red. */
.wj { color: var(--wj); }
.card-text .wj, .t-text .wj { color: var(--wj-2); }
.rail-scripture .wj { color: var(--wj-bright); }
/* God's words (scripts/gods-words.mjs), beside the red letters. Off in the
   theme menu. */
.gw { color: var(--gold); }
.rail-scripture .gw { color: var(--gold); }
:root[data-gold="off"] .gw { color: inherit; }
:root[data-red="off"] .wj { color: inherit; }
.swatch.sw-gold { background: var(--gold); }
.swatch.sw-red { background: var(--wj); }
/* The legend's samples of each lettering, in the reading face. */
.legend-words {
  font-family: var(--serif); font-size: 12.5px; font-style: italic; line-height: 1.3;
}
/* Two parts, not the three (box, line, name) of a thread row, or the name
   falls into the 34px line column and stacks one word to a line. */
.legend-row.is-words { grid-template-columns: 92px 1fr; }

/* ───────────────────────────────────────────────────────── reader ── */

.reader {
  position: fixed; inset: 0; z-index: 150;
  background: color-mix(in srgb, var(--bg) 72%, transparent); backdrop-filter: blur(3px);
  display: grid; place-items: center; padding: 30px;
}
.reader[hidden] { display: none; }

.reader-panel {
  width: min(820px, 100%); max-height: 86vh; display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--line); border-radius: 14px;
  box-shadow: 0 30px 90px rgba(0,0,0,.7); overflow: hidden;
}
.reader-head {
  display: flex; align-items: flex-start; gap: 16px; padding: 15px 18px 12px;
  border-bottom: 1px solid var(--line); flex: 0 0 auto;
}
.reader-head h3 { margin: 0; font: 600 17px var(--serif); color: var(--accent); }
.reader-nav { margin-left: auto; display: flex; align-items: center; gap: 5px; }
.reader-nav select {
  background: var(--bg); border: 1px solid var(--line); color: var(--text);
  border-radius: 7px; padding: 5px 8px; outline: none; max-width: 170px;
}

.reader-body {
  overflow: auto; padding: 18px 22px 26px;
  font-family: var(--serif); font-size: 16.5px; line-height: 1.72; color: var(--read);
}
.reader-v { display: block; padding: 3px 6px; border-radius: 6px; cursor: pointer; }
.reader-v:hover { background: var(--surface-2); }
.reader-v.here { background: var(--accent-wash); box-shadow: inset 2px 0 0 var(--accent); }
.reader-v .vn {
  font-family: var(--sans); font-size: 11px; color: var(--accent-soft);
  vertical-align: super; margin-right: 5px; user-select: none;
}

/* starter threads in the dropdown */
.thread-bar optgroup { color: var(--text-faint); font-style: normal; }
.t-spacer { margin-left: auto; }
#thread-merge { max-width: 160px; color: var(--text-dim); }
#thread-merge:disabled { opacity: .45; }

/* ──────────────────────────────────────────────── collapsible rail ── */

.rail-toggle {
  align-self: stretch; width: 16px; flex: 0 0 16px;
  background: var(--surface); border: 0; border-left: 1px solid var(--line);
  color: var(--text-faint); cursor: pointer; font-size: 11px; padding: 0;
}
.rail-toggle:hover { background: var(--surface-2); color: var(--accent); }
.view.rail-hidden .rail { display: none; }
.view.rail-hidden .rail-toggle { transform: rotate(180deg); }

/* ───────────────────────────────────────────────────── map eras ── */

.map-river { fill: none; stroke: var(--map-water); stroke-width: 1.1; stroke-linejoin: round; opacity: .85; }
.map-lake  { fill: var(--map-lake); stroke: var(--map-water); stroke-width: .8; }
.map-tools select {
  background: var(--bg); border: 1px solid var(--line); color: var(--text);
  border-radius: 7px; padding: 4px 8px; outline: none; margin-left: 6px;
}
.era-name { fill: var(--accent); }
.name-then {
  font-size: 12.5px; color: var(--accent);
}
.name-row {
  display: grid; grid-template-columns: 132px 1fr; gap: 10px;
  padding: 4px 6px; border-radius: 6px; align-items: baseline;
}
.name-row.is-now { background: var(--accent-wash); }
.name-row .era { font-size: 11px; color: var(--text-faint); }
.name-row .nm  { font-family: var(--serif); font-size: 14px; }

.ask-q {
  font-size: 13px; color: var(--accent); margin-bottom: 6px;
  padding-left: 9px; border-left: 2px solid var(--accent-soft);
}
.ask-log { margin-top: 12px; }
.ask-log h4 {
  margin: 0 0 6px; font-size: 11px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--text-faint); font-weight: 600;
}
.ask-item {
  border: 1px solid var(--line-soft); border-radius: 8px;
  padding: 7px 10px; margin-bottom: 6px; background: var(--bg);
}
.ask-item summary {
  cursor: pointer; font-size: 13px; color: var(--text-dim); list-style: none;
}
.ask-item summary::-webkit-details-marker { display: none; }
.ask-item summary::before { content: '▸ '; color: var(--accent-soft); }
.ask-item[open] summary::before { content: '▾ '; }
.ask-item summary:hover { color: var(--text); }
.ask-item .ai-out { margin-top: 8px; font-size: 13px; }

/* the context block on a flipped tile */
.t-ctx-head {
  font-family: var(--sans); font-size: 9.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--text-faint); margin-bottom: 3px;
}
.t-flip { font-size: 14px; padding: 2px 5px; }
.tile-back { cursor: pointer; }

/* a tile turns over on a click, as the daily cards do */
.tile-front, .tile-back { cursor: pointer; }
.t-foot {
  margin-top: auto; display: flex; align-items: flex-end; gap: 8px;
  padding-top: 6px;
}
.t-foot .t-why { margin-top: 0; border-top: 0; padding-top: 0; flex: 1; }
.t-turn {
  font-size: 10px; color: var(--text-faint); white-space: nowrap;
  margin-left: auto; opacity: .7;
}
.tile:hover .t-turn { color: var(--accent-soft); opacity: 1; }

/* Close button for the right-hand panel. It sits OUTSIDE the <aside>, because
   the panel replaces its own children whenever the selection changes and would
   otherwise wipe the button away. */
.view { position: relative; }
.rail-close {
  position: absolute; top: 9px; right: 13px; z-index: 6;
  width: 22px; height: 22px; padding: 0; line-height: 1;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: 6px;
  color: var(--text-faint); cursor: pointer; font-size: 12px;
}
.rail-close:hover { color: var(--danger); border-color: var(--danger); }
.view.rail-hidden .rail-close { display: none; }

/* A flipped tile grows to the proportions of a Daily Ten card, so the four
   sections have room to read. It grows symmetrically — the negative margins
   are half the size increase — which keeps the tile's centre fixed, and the
   edges are drawn to centres, so the threads stay attached while it opens. */
.tile.flippable { transition: width .28s ease, height .28s ease, margin .28s ease; }
.tile.flippable.flipped {
  width: 330px;  margin-left: -31px;
  height: 376px; margin-top: -99px;
  z-index: 20;
}
.tile.flippable.flipped .tile-face { padding: 13px 15px; }
/* A long verse: taller, about the same centre (canvas.js tileHeight). */
.tile.flippable.tall:not(.flipped) {
  height: var(--tile-h); margin-top: calc((178px - var(--tile-h)) / 2);
}
/* Reviewed in the Daily Ten, on any day: a tick by the reference. */
.tile.reviewed .tile-front .t-ref::after,
.tile.reviewed .tile-back .t-ref::after {
  content: '✓'; margin-left: 6px; display: inline-grid; place-items: center;
  width: 15px; height: 15px; border-radius: 50%; vertical-align: 1px;
  background: var(--good); color: var(--bg); font-size: 9.5px; font-weight: 700;
}

/* ───────────────────────────────────────────────── thread dropdown ── */

/* A real menu rather than a <select>, so each saved thread can carry its own
   delete. A native option cannot hold a button. */
.thread-pick { position: relative; }
.thread-current {
  display: flex; align-items: center; gap: 8px; min-width: 200px; max-width: 260px;
  background: var(--bg); border: 1px solid var(--line); color: var(--text);
  border-radius: 7px; padding: 5px 9px; cursor: pointer; font-size: 13px;
}
.thread-current:hover { border-color: var(--accent-soft); }
#thread-current-name { flex: 1; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.thread-current .caret { color: var(--text-faint); font-size: 10px; }

.thread-menu {
  position: absolute; top: 34px; left: 0; z-index: 70;
  width: 320px; max-height: 60vh; overflow: auto;
  background: var(--surface); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 18px 50px rgba(0,0,0,.6); padding: 5px;
}
.thread-menu[hidden] { display: none; }
.tm-head {
  padding: 7px 9px 4px; font-size: 10.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--text-faint);
}
/* The parts of the Bible inside "Start an adventure". */
.tm-subhead {
  padding: 6px 9px 2px; font-size: 11px; font-weight: 600; color: var(--accent); cursor: help;
}
/* Each group in its part's color, as on the cards: heading and a stripe down
   every row. Both Testaments: the Old's green running into the New's blue. */
.tm-subhead.adv-ot { color: var(--good); }
.tm-subhead.adv-gos { color: var(--gospel); }
.tm-subhead.adv-nt { color: var(--info); }
.tm-subhead.adv-all {
  background: linear-gradient(90deg, var(--good), var(--info));
  -webkit-background-clip: text; background-clip: text; color: transparent;
  width: max-content;
}
.adv-row { position: relative; }
.adv-row::before {
  content: ''; position: absolute; left: 2px; top: 5px; bottom: 5px; width: 3px;
  border-radius: 2px; background: var(--adv);
}
.adv-row.adv-ot { --adv: var(--good); }
.adv-row.adv-gos { --adv: var(--gospel); }
.adv-row.adv-nt { --adv: var(--info); }
.adv-row.adv-all { --adv: linear-gradient(var(--good), var(--info)); }
.tm-row {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 9px; border-radius: 7px; cursor: pointer;
}
.tm-row:hover { background: var(--surface-2); }
.tm-row.on { background: var(--surface-2); }
.tm-row.on .tm-name { color: var(--accent); }
.tm-name { flex: 1; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tm-count { font-size: 11px; color: var(--text-faint); }
.tm-blurb { font-size: 11.5px; color: var(--text-faint); padding: 0 9px 7px; margin-top: -4px; }
.tm-del {
  flex: 0 0 auto; width: 20px; height: 20px; padding: 0; line-height: 1;
  background: transparent; border: 1px solid transparent; border-radius: 5px;
  color: var(--text-faint); cursor: pointer; font-size: 11px; opacity: 0;
}
.tm-row:hover .tm-del { opacity: 1; }
.tm-del:hover { color: var(--danger); border-color: var(--danger); background: color-mix(in srgb, var(--danger) 12%, transparent); }
.tm-empty { padding: 10px 9px; font-size: 12.5px; color: var(--text-faint); }

/* ────────────────────────────────────────────────────────── legend ── */

.legend {
  position: absolute; left: 12px; bottom: 12px; z-index: 40;
  background: color-mix(in srgb, var(--surface) 93%, transparent); border: 1px solid var(--line);
  border-radius: 9px; backdrop-filter: blur(3px); overflow: hidden;
  min-width: 156px;
}
.legend-toggle {
  display: flex; align-items: center; gap: 8px; width: 100%;
  background: none; border: 0; cursor: pointer;
  padding: 7px 10px; color: var(--text-dim); font-size: 11.5px;
  letter-spacing: .08em; text-transform: uppercase;
}
.legend-toggle:hover { color: var(--text); }
.legend-title { flex: 1; text-align: left; }
.legend-caret { font-size: 9px; color: var(--text-faint); transition: transform .18s; }
.legend.collapsed .legend-caret { transform: rotate(-90deg); }
.legend.collapsed .legend-body { display: none; }

.legend-body { padding: 2px 10px 9px; }
.legend-row {
  display: grid; grid-template-columns: auto 34px 1fr; gap: 9px;
  align-items: center; padding: 3px 0; cursor: default;
}
.legend-row svg { display: block; overflow: visible; }
.legend-name { font-size: 12px; color: var(--text); }
.legend-what { font-size: 10.5px; color: var(--text-faint); }
.legend-row:hover .legend-what { color: var(--text-dim); }

/* The four headings, shown while the note is still being written. */
.t-skel { margin-top: 7px; opacity: .38; }
.t-skel strong { color: var(--accent); }
.t-skel::after {
  content: ''; display: block; height: 7px; margin-top: 4px; border-radius: 3px;
  background: linear-gradient(90deg, var(--line) 0%, var(--line-soft) 60%, transparent 100%);
}

/* The verse the tile is about, marked out from its neighbours. */

/* ─────────────────────────────────────────────── places on the map ── */

/* Colour says where in Scripture a place appears; size says how often it is
   named. The Gospels take precedence so Jesus' ground reads at a glance. */
.place-dot   { opacity: .82; transition: fill .12s, opacity .12s; pointer-events: none; }
.place-dot.is-gospels { fill: var(--gospel); }   /* the Gospels' own orchid, not red-letter red */
.place-dot.is-both    { fill: color-mix(in srgb, var(--good) 50%, var(--info)); }   /* between olive and lapis: gold is for God's words now */
.place-dot.is-nt      { fill: var(--info); }   /* lapis */
.place-dot.is-ot      { fill: var(--good); }   /* olive */
.place-dot.sel        { fill: var(--accent-bright); opacity: 1; }

/* An invisible, generous click target over each dot. */
.place-hit { fill: transparent; cursor: pointer; }
.place-hit:hover + .place-label,
.place-hit:hover { outline: none; }
.place-hit:hover ~ .place-dot { opacity: 1; }

.place-label.is-gospels { fill: var(--gospel-dim); }
.place-label.is-both    { fill: color-mix(in srgb, var(--good-dim) 50%, var(--info-dim)); }
.place-label.is-nt      { fill: var(--info-dim); }
.place-label.is-ot      { fill: var(--good-dim); }
.place-label.era-name   { fill: var(--accent); }

/* The key is also the filter: each row toggles that kind of place. */
.map-legend {
  position: absolute; left: 12px; bottom: 12px; z-index: 30;
  background: color-mix(in srgb, var(--surface) 92%, transparent); border: 1px solid var(--line);
  border-radius: 9px; padding: 7px 9px; backdrop-filter: blur(3px);
  font-size: 11.5px; color: var(--text-dim); min-width: 172px;
}
.ml-row {
  display: flex; align-items: center; gap: 8px;
  padding: 4px 6px; border-radius: 6px; cursor: pointer; user-select: none;
}
.ml-row:hover { background: var(--hover-wash); color: var(--text); }
.ml-row.off { opacity: .38; }
.ml-row.off .ml-dot { background: transparent; box-shadow: inset 0 0 0 1.5px currentColor; }
.ml-name { flex: 1; }
.ml-count { font-size: 10.5px; color: var(--text-faint); font-variant-numeric: tabular-nums; }
.ml-dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; }
.ml-dot.is-gospels { background: var(--gospel); }
.ml-dot.is-both    { background: color-mix(in srgb, var(--good) 50%, var(--info)); }
.ml-dot.is-nt      { background: var(--info); }
.ml-dot.is-ot      { background: var(--good); }
.ml-note { margin-top: 5px; font-size: 10.5px; color: var(--text-faint); }

/* Why a kind of thread matters — revealed when you hover its legend row. */
.legend-row { cursor: help; border-radius: 6px; }
.legend-row:hover { background: var(--surface-2); }
/* The explanation floats beside the legend and never affects its size.
   pointer-events:none so it can never take the hover from the row. */
.legend-tip {
  position: absolute; z-index: 45; width: 236px;
  background: color-mix(in srgb, var(--surface) 97%, transparent); border: 1px solid var(--accent-soft);
  border-radius: 8px; padding: 9px 11px;
  font-size: 11.5px; line-height: 1.5; color: var(--text-dim);
  box-shadow: 0 10px 30px rgba(0,0,0,.55);
  pointer-events: none;
}
.legend-tip[hidden] { display: none; }

/* A dictionary entry on the canvas. */
.tile.kind-dict { width: 250px; background: var(--tile-dict); border-color: var(--tile-dict-line); }
.tile.kind-dict .t-ref { color: var(--dict-accent); }
.tile.kind-dict .t-text { font-size: 12.5px; }

/* A dictionary tile turns over as well, so its colour belongs to the two
   faces; the tile itself is only the frame they rotate inside. */
.tile.kind-dict.flippable { background: transparent; border: 0; box-shadow: none; }
.tile.kind-dict .tile-front { background: var(--tile-dict); border-color: var(--tile-dict-line); }
.tile.kind-dict .tile-back  { background: var(--tile-back);  border-color: var(--tile-dict-line); }

/* The entry in full, on the back. */
.t-def-body {
  margin: 0 0 9px; font-family: var(--serif); font-size: 12.8px;
  line-height: 1.6; color: var(--read-2); white-space: normal;
}
.t-sense { color: var(--dict-accent); font-weight: 600; }

/* Somewhere to go next: cited verses, and the entries beside this one. */
.t-chips { display: flex; flex-wrap: wrap; gap: 5px; margin: 2px 0 9px; }
.t-chip {
  font: inherit; font-size: 11.5px; line-height: 1;
  padding: 4px 8px; border-radius: 999px; cursor: pointer;
  background: var(--surface-2); color: var(--read-2);
  border: 1px solid var(--line-soft);
}
.t-chip:hover { border-color: var(--accent); color: var(--accent); }
.t-chip.here { opacity: .55; }
.t-chip.here:hover { border-color: var(--line-soft); color: var(--read-2); }
.dict-body {
  font-family: var(--serif); font-size: 14px; line-height: 1.6; color: var(--read-2);
}
.dict-body .vref { color: var(--accent); cursor: pointer; border-bottom: 1px dotted var(--accent-soft); }

/* ───────────────────────────────────────────── tiles that feel like tiles ── */

/* Card stock rather than a flat rectangle: a light top edge, a faint sheen
   across the face, and two shadows — a tight one for contact and a wide one
   for lift. In the light themes this reads as paper on a desk. */
.tile-face, .tile:not(.flippable) {
  background-image: var(--tile-face);
  border-top-color: var(--tile-edge);
  box-shadow: var(--shadow-tile);
}
.tile:hover .tile-face,
.tile:not(.flippable):hover { box-shadow: var(--shadow-tile-hi); }
.tile.flippable:hover { transform: translateY(-1px); }


/* The legend's second section: what a card's left stripe means. These read
   the same tokens as .tile.is-* above, so a theme that restyles the tiles
   restyles the key with them and the two cannot drift apart. */
.legend-sub {
  margin: 14px 0 2px; font-size: 11px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text-faint);
  border-top: 1px solid var(--line-soft); padding-top: 10px;
}
/* The part rows are buttons into the canon map, so they need the button
   reset -- but they must keep the same grid as the thread rows above or the
   two sections stop lining up. */
.legend-row.is-part {
  font: inherit; color: inherit; background: none; border: 0;
  width: 100%; text-align: left; cursor: pointer;
}
.legend-row.is-part:hover .legend-name { color: var(--accent); }
.legend-row.is-part:focus-visible { outline: 1px solid var(--accent); border-radius: 4px; }
/* These rows have no checkbox, so the stripe is placed into the swatch column
   explicitly; the text then auto-places beside it and the names stay in one
   line with the thread rows above. */
.legend-stripe {
  grid-column: 2; justify-self: center;
  width: 4px; height: 22px; border-radius: 2px;
}
.legend-stripe.is-gospels { background: var(--gospel); }
.legend-stripe.is-nt      { background: var(--info); }
.legend-stripe.is-ot      { background: var(--good); }

/* Books on the canon map carry the same spine as a verse tile from them. */
.canon-stripe { pointer-events: none; }
.canon-stripe.is-gospels { fill: var(--gospel); }
.canon-stripe.is-nt      { fill: var(--info); }
.canon-stripe.is-ot      { fill: var(--good); }

/* Arriving from the legend: everything outside the chosen part steps back,
   rather than disappearing, so you can still see where it sits. */
#canon-svg.part-gospels .canon-book:not(.is-gospels),
#canon-svg.part-nt      .canon-book:not(.is-nt),
#canon-svg.part-ot      .canon-book:not(.is-ot) { opacity: .32; }
#canon-svg[class*="part-"] .canon-arc { opacity: .12; }
/* Colour says which part of Scripture a verse is from — the same four the map
   uses, so the key carries across. A spine down the left edge, and the
   reference in the same colour. */
.tile.is-gospels .tile-face, .tile.is-gospels { border-left: 3px solid var(--gospel); }
.tile.is-nt      .tile-face, .tile.is-nt      { border-left: 3px solid var(--info); }
.tile.is-ot      .tile-face, .tile.is-ot      { border-left: 3px solid var(--good); }
.tile.is-gospels .t-ref { color: var(--gospel); }
.tile.is-nt      .t-ref { color: var(--info); }
.tile.is-ot      .t-ref { color: var(--good-dim); }

/* the same idea for the non-verse kinds */
.tile.kind-root  .tile-face, .tile.kind-root  { border-left: 3px solid var(--accent-soft); }
.tile.kind-place .tile-face, .tile.kind-place { border-left: 3px solid var(--thread-place); }
.tile.kind-dict  .tile-face, .tile.kind-dict  { border-left: 3px solid var(--dict-accent); }

/* ────────────────────────────────────────────── canvas backdrops ── */

.canvas { background-repeat: repeat; background-position: 0 0; }

:root[data-backdrop="plain"] .canvas { background-image: none; }

:root[data-backdrop="dots"] .canvas {
  background-image: radial-gradient(circle at 1px 1px, var(--canvas-dot) 1px, transparent 0);
  background-size: 28px 28px;
}

:root[data-backdrop="grid"] .canvas {
  background-image:
    linear-gradient(var(--canvas-dot) 1px, transparent 1px),
    linear-gradient(90deg, var(--canvas-dot) 1px, transparent 1px);
  background-size: 32px 32px, 32px 32px;
}

/* A woven grain, built from crossed gradients rather than an image. */
:root[data-backdrop="paper"] .canvas {
  background-image:
    repeating-linear-gradient(90deg, var(--canvas-dot) 0 1px, transparent 1px 4px),
    repeating-linear-gradient(0deg,  var(--canvas-dot) 0 1px, transparent 1px 4px);
  background-size: auto, auto;
  opacity: 1;
}

/* Mottled, like a page that has been handled. */
:root[data-backdrop="vellum"] .canvas {
  background-image:
    radial-gradient(ellipse at 20% 30%, var(--canvas-dot) 0, transparent 45%),
    radial-gradient(ellipse at 75% 65%, var(--canvas-dot) 0, transparent 40%),
    radial-gradient(ellipse at 45% 85%, var(--canvas-dot) 0, transparent 38%);
  background-size: 620px 520px, 700px 600px, 560px 480px;
}

:root[data-backdrop="photo"] .canvas {
  background-size: cover; background-position: center; background-repeat: no-repeat;
}
/* Keeps tiles readable over a photograph without washing the picture out. */
:root[data-backdrop="photo"] .canvas::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: color-mix(in srgb, var(--bg) 62%, transparent);
}

/* The logo, whole, behind the board. The layer is sized to the largest square
   that fits (container units), so the art is never cropped, and its edges are
   faded so the art's own navy ground melts into the theme's. */
.canvas { container-type: size; }
:root[data-backdrop="logo"] .canvas { background-image: none; }
:root[data-backdrop="logo"] .canvas::before {
  content: ''; position: absolute; pointer-events: none;
  width: min(96cqw, 96cqh); aspect-ratio: 1;
  left: 50%; top: 50%; transform: translate(-50%, -50%);
  background: url("/logo.jpg") center / contain no-repeat;
  opacity: .32;
  -webkit-mask-image:
    linear-gradient(to right, transparent, #000 12%, #000 88%, transparent),
    linear-gradient(to bottom, transparent, #000 8%, #000 94%, transparent);
  -webkit-mask-composite: source-in;
  mask-image:
    linear-gradient(to right, transparent, #000 12%, #000 88%, transparent),
    linear-gradient(to bottom, transparent, #000 8%, #000 94%, transparent);
  mask-composite: intersect;
}
/* On the light themes the art's dark ground would read as a stain; fainter. */
:root[data-theme="parchment"][data-backdrop="logo"] .canvas::before,
:root[data-theme="linen"][data-backdrop="logo"] .canvas::before { opacity: .14; }

/* ─────────────────────────────────────────────── theme picker ── */

.theme-pick { position: relative; }
.theme-btn {
  background: var(--bg); border: 1px solid var(--line); color: var(--text-dim);
  border-radius: 8px; width: 32px; height: 30px; cursor: pointer; font-size: 14px;
}
.theme-btn:hover { border-color: var(--accent-soft); color: var(--accent); }

.theme-menu {
  position: absolute; top: 38px; right: 0; z-index: 80; width: 268px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 10px; box-shadow: var(--shadow-panel); padding: 5px;
  max-height: 72vh; overflow: auto;
}
.theme-menu[hidden] { display: none; }
.theme-menu .tm-head {
  padding: 7px 9px 4px; font-size: 10.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--text-faint);
}
.theme-menu .tm-row {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 9px; border-radius: 7px; cursor: pointer;
}
.theme-menu .tm-row:hover { background: var(--hover-wash); }
.theme-menu .tm-row.on { background: var(--surface-2); }
.theme-menu .tm-row.on .tm-name { color: var(--accent); }
.theme-menu .tm-name { font-size: 13px; }
.theme-menu .tm-note { font-size: 11px; color: var(--text-faint); }

.swatch {
  flex: 0 0 auto; width: 26px; height: 26px; border-radius: 6px;
  border: 1px solid var(--line);
}
.sw-navy      { background: linear-gradient(135deg, #172030 50%, #d8a657 50%); }
.sw-lamplight { background: linear-gradient(135deg, #0f1216 50%, #d8a657 50%); }
.sw-parchment { background: linear-gradient(135deg, #e8ddc8 50%, #9a6512 50%); }
.sw-linen     { background: linear-gradient(135deg, #e7eaee 50%, #8a5a12 50%); }
.bk-dots   { background: radial-gradient(circle at 5px 5px, var(--text-faint) 1.5px, var(--bg) 0) 0 0 / 9px 9px; }
.bk-plain  { background: var(--bg); }
.bk-paper  { background: repeating-linear-gradient(90deg, var(--text-faint) 0 1px, var(--bg) 1px 4px); }
.bk-grid   { background:
               linear-gradient(var(--text-faint) 1px, transparent 1px) 0 0 / 9px 9px,
               linear-gradient(90deg, var(--text-faint) 1px, var(--bg) 1px) 0 0 / 9px 9px; }
.bk-vellum { background: radial-gradient(ellipse at 35% 40%, var(--text-faint) 0, var(--bg) 70%); }
.bk-photo  { background: linear-gradient(135deg, var(--info) 0, var(--good) 100%); }

/* A quiet link out to the sources. Attribution is a condition of several of
   the licences this corpus is built on, so it belongs in the chrome, not
   buried in a menu. */
.credits-link {
  font-size: 11.5px; color: var(--text-faint); text-decoration: none;
  padding: 3px 7px; border-radius: 5px; white-space: nowrap;
}
.credits-link:hover { color: var(--accent); background: var(--surface-2); }

/* One line at the top of the legend, tying the app's two nouns together: you
   build a strand; it is woven out of threads. */
.legend-lede {
  font-size: 11px; line-height: 1.5; color: var(--text-faint);
  margin: 0 0 9px; padding-bottom: 8px;
  border-bottom: 1px solid var(--line-soft);
}

/* ──────────────────────────────────────────────────────────── phones ── */

/* The stylesheet stopped at 820px, which left a phone with a 340px rail
   absolutely positioned over a 375px viewport — about 35px of canvas, a
   toolbar pushed off-screen and a search box wider than the window. These
   rules carry the layout the rest of the way down.

   Everything here is layout only. Touch behaviour lives in the views. */

@media (max-width: 700px) {
  /* The bar becomes two rows: identity and tabs, then search across the
     full width, where a phone keyboard can actually use it. */
  .topbar {
    flex-wrap: wrap; height: auto; padding: 8px 12px calc(8px + env(safe-area-inset-bottom, 0px));
    gap: 8px 10px;
  }
  .brand h1 { font-size: 15px; }

  /* Tabs move to the bottom of the screen, where a thumb reaches them and
     where they cost the view no height at the top. Three rows of chrome on
     an 812px screen was a fifth of the phone spent before anything was read. */
  .tabs {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 90;
    background: var(--surface); border-top: 1px solid var(--line);
    justify-content: space-around; gap: 0;
    padding: 5px 4px calc(5px + env(safe-area-inset-bottom, 0px));
  }
  .tab { padding: 8px 6px; font-size: 12px; flex: 1 1 0; text-align: center; }
  .tab.is-active { background: none; }        /* a pill looks wrong down here */
  /* The bar floats over the views, so give the scrolling ones room to end. */
  #view-daily, #view-saved { padding-bottom: 58px; }
  .canvas-wrap, .map-wrap, .canon-wrap { padding-bottom: 46px; }
  .rail { padding-bottom: 58px; }

  /* The controls ride alongside the masthead; only the search field, which
     wants the whole width for a phone keyboard, takes a row of its own. */
  .topbar-right {
    order: 2; margin-left: auto; gap: 8px;
    flex-wrap: wrap; justify-content: flex-end; flex: 1 1 auto; min-width: 0;
  }
  .search-wrap { order: 4; flex: 1 1 100%; }
  #search { width: 100%; }
  .results { width: 100%; right: auto; left: 0; max-height: 52vh; }
  /* A 130px reference column leaves nothing for the text at this width. */
  .result { grid-template-columns: 1fr; gap: 2px; }

  /* The panel covers the view rather than competing with it for room, and
     stops short of the edge so the canvas behind is still visibly there. */
  :root { --rail-w: min(92vw, 400px); }
  .rail { box-shadow: -14px 0 40px rgba(0,0,0,.4); padding: 14px; }

  /* Toolbars scroll sideways instead of overflowing off-screen. */
  .thread-bar, .canon-tools, .map-tools {
    overflow-x: auto; flex-wrap: nowrap; -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .thread-bar::-webkit-scrollbar,
  .canon-tools::-webkit-scrollbar,
  .map-tools::-webkit-scrollbar { display: none; }
  .thread-bar > *, .canon-tools > *, .map-tools > * { flex: 0 0 auto; }
  /* The running hint is the first thing worth losing on a small screen. */
  .thread-bar .hint, .canon-tools .hint, .map-tools .hint { display: none; }

  /* Reference material, not working surface: out of the way until asked. */
  .legend { max-width: 62vw; font-size: 11px; }
  .legend-tip { display: none; }

  .daily-grid { grid-template-columns: 1fr; }
  .reader-panel { width: 100%; max-width: none; border-radius: 0; }
}

/* Anything that still needs to give at true phone width. */
@media (max-width: 420px) {
  .brand h1 { font-size: 14px; }
  .credits-link { display: none; }       /* reachable from /credits directly */
  .tile.flippable.flipped {
    width: min(86vw, 330px); margin-left: calc((min(86vw, 330px) - 268px) / -2);
  }
}

/* ───────────────────────────────────────────────────────────── dialogs ── */

/* Replaces prompt() and confirm(), which render as system error dialogs
   inside an installed app and are blocked outright in some embedded
   contexts. Same two questions, asked in the app's own voice. */
.dlg-back {
  position: fixed; inset: 0; z-index: 200; display: grid; place-items: center;
  background: rgba(0,0,0,.45); padding: 20px;
  animation: dlg-in .12s ease-out;
}
@keyframes dlg-in { from { opacity: 0; } to { opacity: 1; } }

.dlg {
  width: min(420px, 100%); background: var(--surface); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: 0 24px 70px rgba(0,0,0,.55); padding: 20px;
}
.dlg-msg { margin: 0 0 14px; font-size: 14.5px; line-height: 1.55; color: var(--read-1); }
.dlg-input {
  width: 100%; padding: 9px 11px; border-radius: 8px; margin-bottom: 14px;
  background: var(--bg); border: 1px solid var(--line); outline: none;
}
.dlg-input:focus { border-color: var(--accent-soft); }
.dlg-row { display: flex; gap: 8px; justify-content: flex-end; }
/* Thumb-sized targets: this is the one piece of chrome a phone must hit. */
.dlg-row .btn { min-height: 40px; padding: 9px 16px; }
.dlg-row .btn:disabled { opacity: .45; cursor: default; }

/* "Report this note" (api.js reportLink): quiet, under the note. */
.note-report {
  background: none; border: 0; padding: 4px 0; margin-top: 6px; cursor: pointer;
  font-size: 11px; color: var(--text-faint); text-decoration: underline dotted;
  align-self: flex-start; flex: 0 0 auto;   /* just the words, not the card's width */
}
.note-report:hover { color: var(--danger); }
.report-reasons { display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px; }
.report-reason {
  text-align: left; padding: 8px 11px; border-radius: 8px; cursor: pointer;
  background: var(--bg); border: 1px solid var(--line); color: var(--text); font-size: 13.5px;
}
.report-reason:hover { border-color: var(--accent-soft); }
.report-reason.on { border-color: var(--accent); background: var(--surface-2); }
.report-comment { min-height: 64px; resize: vertical; font: inherit; color: var(--text); }

@media (prefers-reduced-motion: reduce) {
  .dlg-back { animation: none; }
}

/* ───────────────────────────────────────────────────────── touch input ── */

/* Without this the browser claims every drag for scrolling the page and the
   canvas never sees the gesture. Scrollable text inside a tile is exempted,
   or a verse too long for its tile becomes unreadable on a phone. */
.canvas, .map, .canon { touch-action: none; }
.t-text, .t-back-body, .rail, .results { touch-action: pan-y; }

/* Touch targets. A 20px close button is a desktop affordance; a finger needs
   something it can actually land on. */
@media (pointer: coarse) {
  .rail-close, .rail-toggle { min-width: 40px; min-height: 40px; }
  .btn, .mini, .tab { min-height: 36px; }
  .t-chip { min-height: 30px; padding: 6px 11px; }
  /* Holding a tile opens the remove prompt; the browser's own long-press
     menu and text selection would fight it for the gesture. */
  .tile { -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }
  .t-text, .t-back-body { -webkit-user-select: text; user-select: text; }
}

/* ────────────────────────────── beyond the canon: can you read it? ── */

/* Whether a work is readable is a different question from whether it is
   canonical, and it is the one people ask first. Four states, because the
   honest answers really are four: it is here, it is free but not loaded, it
   survives under copyright, or it is gone. */
.canon-box.beyond.text-corpus     { stroke: var(--good);         fill: color-mix(in srgb, var(--good) 20%, transparent); }
.canon-box.beyond.text-available  { stroke: var(--accent);       fill: color-mix(in srgb, var(--accent) 16%, transparent); }
.canon-box.beyond.text-restricted { stroke: var(--text-faint);   fill: color-mix(in srgb, var(--text-faint) 12%, transparent); }
.canon-box.beyond.text-lost       { stroke: var(--text-faint);   fill: none; stroke-dasharray: 3 3; }

.canon-legend {
  position: absolute; left: 12px; bottom: 12px; z-index: 5;
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 10px 12px; max-width: 260px; backdrop-filter: blur(3px);
}
.canon-legend[hidden] { display: none; }
.cl-head {
  font-size: 11px; text-transform: uppercase; letter-spacing: .07em;
  color: var(--accent); margin-bottom: 8px;
}
.cl-row { display: flex; gap: 9px; align-items: flex-start; margin-bottom: 7px; }
.cl-row:last-child { margin-bottom: 0; }
.cl-dot {
  width: 11px; height: 11px; border-radius: 3px; flex: 0 0 auto; margin-top: 2px;
  border: 1px solid var(--text-faint);
}
.cl-dot.text-corpus     { border-color: var(--good);       background: color-mix(in srgb, var(--good) 30%, transparent); }
.cl-dot.text-available  { border-color: var(--accent);     background: color-mix(in srgb, var(--accent) 26%, transparent); }
.cl-dot.text-restricted { border-color: var(--text-faint); background: color-mix(in srgb, var(--text-faint) 20%, transparent); }
.cl-dot.text-lost       { border-style: dashed; background: none; }
.cl-name  { font-size: 12px; color: var(--read-1); }
.cl-count { font-size: 12px; color: var(--text-faint); }
.cl-what  { font-size: 11px; color: var(--text-faint); line-height: 1.45; }

/* The same answer, stated in full where the work is opened. */
.text-state {
  margin: 12px 0 4px; padding: 9px 11px; border-radius: 8px;
  border: 1px solid var(--line-soft); background: var(--surface-2);
  border-left-width: 3px;
}
.text-state.text-corpus     { border-left-color: var(--good); }
.text-state.text-available  { border-left-color: var(--accent); }
.text-state.text-restricted { border-left-color: var(--text-faint); }
.text-state.text-lost       { border-left-color: var(--text-faint); border-left-style: dashed; }
.ts-name { font-size: 12px; font-weight: 600; color: var(--read-1); margin-bottom: 3px; }
.ts-note { font-size: 12px; line-height: 1.55; color: var(--text-faint); }

@media (max-width: 700px) { .canon-legend { max-width: 60vw; font-size: 11px; } }

/* ───────────────────────────────────── a card at reading size ── */

/* The back of a tile is 330px wide. That is right for a glance and wrong for
   four paragraphs, so ⤢ opens the same card with room to read it. Same shell
   as the reader, so the app has one idea of what an overlay looks like. */
.card-view {
  position: fixed; inset: 0; z-index: 160;
  background: color-mix(in srgb, var(--bg) 72%, transparent); backdrop-filter: blur(3px);
  display: grid; place-items: center; padding: 30px;
}
.card-view[hidden] { display: none; }

.card-panel {
  width: min(680px, 100%); max-height: 86vh; display: flex; flex-direction: column;
  background: var(--tile-back); border: 1px solid var(--line); border-radius: 14px;
  box-shadow: 0 30px 90px rgba(0,0,0,.7); overflow: hidden;
}
.card-head {
  display: flex; align-items: flex-start; gap: 16px; padding: 15px 20px 12px;
  border-bottom: 1px solid var(--line); flex: 0 0 auto;
}
.card-head h3 { margin: 0; font: 600 18px var(--serif); color: var(--accent); }
.card-head .btn { margin-left: auto; }

.card-body {
  overflow: auto; padding: 20px 24px 28px;
  font-family: var(--serif); color: var(--read-2);
}

/* The verse leads, because the note is about it. */
.card-verse {
  margin: 0 0 20px; font-size: 18px; line-height: 1.68; color: var(--read-1);
  padding-bottom: 18px; border-bottom: 1px solid var(--line-soft);
}
.card-note { font-size: 15.5px; line-height: 1.75; white-space: pre-wrap; }
.card-note strong { color: var(--accent); }
.card-def { margin: 0 0 14px; font-size: 15.5px; line-height: 1.7; }

.card-h {
  font-size: 11px; text-transform: uppercase; letter-spacing: .08em;
  color: var(--accent); margin: 24px 0 10px; font-family: var(--sans);
  border-top: 1px solid var(--line-soft); padding-top: 16px;
}
.card-refs { margin: 0; font-size: 14px; line-height: 1.9; }

/* A reference anywhere in the card puts that verse on the canvas. */
.card-body .vref { color: var(--accent); cursor: pointer; border-bottom: 1px dotted var(--accent-soft); }
.card-body .vref:hover { background: var(--accent-wash); }

@media (max-width: 700px) {
  .card-view { padding: 0; }
  .card-panel { width: 100%; max-height: 100%; height: 100%; border-radius: 0; border: 0; }
  .card-body { padding: 16px 16px 60px; }
  .card-verse { font-size: 17px; }
}

/* A pinned tile stays turned over until the pin is released, so two cards can
   be read side by side without a stray click closing one of them. */
.t-pin { font-size: 12px; }
.t-pin.on { color: var(--accent); }
.tile.pinned .tile-face { border-color: var(--accent-soft); }
.tile.pinned.flipped .tile-back {
  box-shadow: inset 0 0 0 1px var(--accent-soft);
}

/* A key you can switch off. The map's key already works this way; the canvas
   needs it more, because a busy board draws every kind of thread at once. */
.legend-row {
  cursor: pointer; border-radius: 5px; padding: 3px 4px; margin: 0 -4px;
  /* Clicking a control should not select its label — the old version left a
     blue smear across the word you were trying to switch off. */
  user-select: none; -webkit-user-select: none;
}
.legend-box { accent-color: var(--accent); margin: 0 2px 0 0; flex: 0 0 auto; cursor: pointer; }
.legend-row:hover { background: var(--surface-2); }
.legend-row.off { opacity: .38; }
.legend-row.off .legend-name { text-decoration: line-through; }

/* The way out of a card and into the chapter it came from. */
.card-read { margin-top: 26px; width: 100%; justify-content: center; }

/* ─────────────────────────────────────────────────────────── about ── */

/* Prose, in a column narrow enough to read. This is the one view that is
   trying to explain rather than to show. */
#view-about { flex-direction: column; overflow: auto; }
.about {
  max-width: 46rem; margin: 0 auto; padding: 44px 24px 90px;
  font-family: var(--serif); color: var(--read-2); font-size: 15.5px; line-height: 1.72;
}
.about p { margin: 0 0 16px; }
.about strong { color: var(--read-1); font-weight: 600; }
.about em { color: var(--read-1); }

.about-h1 { font: 600 30px var(--serif); color: var(--accent); margin: 0 0 8px; }
.about-lede { font-size: 17px; line-height: 1.68; color: var(--read-1); margin-bottom: 34px; }
.about-h2 {
  font-family: var(--sans); font-size: 12px; text-transform: uppercase;
  letter-spacing: .09em; color: var(--accent); margin: 38px 0 14px;
  border-bottom: 1px solid var(--line-soft); padding-bottom: 8px;
}

/* Term and gloss, for the kinds of thread and the views. */
.about-kinds { margin: 0 0 18px; }
.about-kinds dt {
  font-weight: 600; color: var(--read-1); font-size: 14.5px; margin-top: 12px;
}
.about-kinds dd { margin: 2px 0 0; font-size: 14.5px; color: var(--text-dim); }

.about-note {
  border-left: 2px solid var(--accent-soft); padding-left: 15px;
  color: var(--read-2); margin: 20px 0 0;
}

/* What is in the corpus, counted rather than remembered. */
.about-stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 14px; margin: 4px 0 22px;
}
.about-stat {
  background: var(--surface); border: 1px solid var(--line-soft);
  border-radius: 10px; padding: 13px 14px;
}
.as-n { font: 600 20px var(--serif); color: var(--accent); line-height: 1.2; }
.as-l { font-family: var(--sans); font-size: 11.5px; color: var(--text-faint); margin-top: 3px; line-height: 1.4; }

.about-link {
  display: inline-block; margin: 2px 0 8px; color: var(--accent);
  font-family: var(--sans); font-size: 13.5px;
}
.about-link:hover { text-decoration: underline; }
.about-foot {
  margin-top: 40px; padding-top: 18px; border-top: 1px solid var(--line-soft);
  font-size: 13px; color: var(--text-faint);
}

@media (max-width: 700px) {
  .about { padding: 26px 18px 80px; font-size: 15px; }
  .about-h1 { font-size: 25px; }
  .about-lede { font-size: 16px; }
}

/* ───────────────────────────────────────────── the artwork, on arrival ── */

/* Navy regardless of theme, because it is the logo's own ground and the art
   should sit in it rather than on it. */
.intro {
  position: fixed; inset: 0; z-index: 400;
  display: grid; place-items: center;
  background: radial-gradient(ellipse at 22% 0%, #25303f 0%, #141b25 60%) #141b25;
  transition: opacity .6s ease;
  cursor: pointer;
}
.intro img {
  width: min(420px, 72vmin); height: auto; border-radius: 20px;
  box-shadow: 0 30px 90px rgba(0, 0, 0, .5);
  animation: intro-in .9s cubic-bezier(.2, .7, .2, 1) both;
}
@keyframes intro-in {
  from { opacity: 0; transform: scale(.94); }
  to   { opacity: 1; transform: none; }
}
.intro.leaving { opacity: 0; pointer-events: none; }

@media (prefers-reduced-motion: reduce) {
  .intro img { animation: none; }
  .intro { transition: none; }
}

/* ─────────────────────────────────────────────── whose workspace this is ── */

/* The corner: "Sign in" for a visitor, "Signed in" in Steve's workspace. */
.who {
  font-size: 12px; text-decoration: none; white-space: nowrap;
  color: var(--text); border: 1px solid var(--line); border-radius: 999px; padding: 4px 11px;
}
.who:hover { border-color: var(--accent); color: var(--accent); }
.who.in { color: var(--accent); border-color: var(--accent-soft); }

/* Save and bring back a visitor's work, in the strand menu. */
.tm-act .tm-name { color: var(--accent); }

/* ────────────────────────────────────────────── follow its threads ── */

/* The main action on a verse. Gold, with the logo's braid beside it. */
.follow {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--gold) !important; color: var(--on-gold) !important;
  border-color: var(--gold) !important; font-weight: 600;
}
.follow:hover { filter: brightness(1.08); }
.follow-mark { width: 16px; height: 16px; border-radius: 4px; display: block; }

/* Until it has been used once: a slow glow, so a newcomer finds it. */
.follow.nudge { animation: follow-glow 2.2s ease-in-out infinite; }
@keyframes follow-glow {
  0%, 100% { box-shadow: 0 0 0 0 rgba(216,166,87,0); }
  50%      { box-shadow: 0 0 0 6px rgba(216,166,87,.28); }
}
@media (prefers-reduced-motion: reduce) { .follow.nudge { animation: none; } }

/* ───────────────────────────────────────────────────────────── how to ── */

#view-howto { flex-direction: column; overflow: auto; }
.howto-step {
  display: grid; grid-template-columns: 38px 1fr; gap: 16px;
  padding: 20px 0; border-top: 1px solid var(--line-soft);
}
.howto-num {
  width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center;
  font: 600 15px var(--sans); color: var(--on-accent); background: var(--accent);
}
.howto-title { font: 600 18px var(--serif); color: var(--read-1, var(--text)); margin: 4px 0 8px; }
.howto-text p { margin: 0 0 10px; }
.howto-alt { font-size: 14px; color: var(--text-dim); }
.howto-show { margin-top: 4px; }

/* "Show me": the control being described, lit up for a few seconds. */
.spotlight {
  position: relative; z-index: 60;
  animation: spotlight 1.4s ease-in-out 3;
  outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 8px;
}
@keyframes spotlight {
  0%, 100% { box-shadow: 0 0 0 0 rgba(216,166,87,0); }
  50%      { box-shadow: 0 0 0 10px rgba(216,166,87,.3); }
}
@media (prefers-reduced-motion: reduce) { .spotlight { animation: none; } }

/* ─────────────────────────────────────────── the map, played through ── */

/* While playing, every place is dimmed; the chapter's own places light up in
   gold, and the last few chapters' places linger as a fading trail. Only
   classes change from step to step — the map itself is never redrawn. */
#map-svg.playing .place-dot { opacity: .16; transition: opacity .35s, stroke-width .35s, fill .35s; }
#map-svg.playing .place-dot.trail { opacity: .55; }
#map-svg.playing .place-dot.now {
  opacity: 1; fill: var(--accent); stroke: var(--accent-bright); stroke-width: 2;
  filter: drop-shadow(0 0 5px rgba(216,166,87,.8));
}
.play-label {
  font: 600 12px var(--sans); fill: var(--accent-bright);
  paint-order: stroke; stroke: rgba(0,0,0,.65); stroke-width: 3px; pointer-events: none;
}

.map-player {
  position: absolute; left: 50%; bottom: 16px; transform: translateX(-50%);
  width: min(760px, calc(100% - 32px)); z-index: 6;
  background: color-mix(in srgb, var(--surface) 94%, transparent); backdrop-filter: blur(4px);
  border: 1px solid var(--line); border-radius: 12px; padding: 10px 12px 12px;
  box-shadow: var(--shadow-panel);
}
.map-player[hidden] { display: none; }
.mp-top { display: flex; align-items: center; gap: 10px; margin-bottom: 9px; }
.mp-btn {
  width: 36px; height: 36px; border-radius: 50%; flex: 0 0 auto; cursor: pointer;
  background: var(--accent); color: var(--on-accent); border: 0; font-size: 13px; font-weight: 700;
}
.mp-speed {
  background: var(--bg); color: var(--text); border: 1px solid var(--line);
  border-radius: 7px; padding: 4px 6px; font-size: 12px; flex: 0 0 auto;
}
.mp-text { flex: 1; min-width: 0; }
.mp-where { font: 600 14px var(--serif); color: var(--read, var(--text)); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mp-era { font-size: 11.5px; color: var(--text-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mp-close { background: none; border: 0; color: var(--text-faint); cursor: pointer; font-size: 15px; padding: 4px 6px; }
.mp-close:hover { color: var(--text); }

.mp-track { position: relative; height: 22px; border-radius: 6px; overflow: hidden; cursor: pointer; background: var(--surface-2); touch-action: none; }
.mp-band { position: absolute; top: 0; bottom: 0; display: flex; align-items: center; overflow: hidden; }
.mp-band-name { font-size: 9.5px; letter-spacing: .06em; text-transform: uppercase; color: rgba(255,255,255,.75); padding-left: 5px; white-space: nowrap; pointer-events: none; }
.mp-torah    { background: #5b4a2c; }
.mp-history  { background: #4a5a33; }
.mp-wisdom   { background: #3f5a5a; }
.mp-prophets { background: #4b4466; }
.mp-gospels  { background: #6b3a69; }
.mp-acts     { background: #7a5a2e; }
.mp-letters  { background: #3d4f6e; }
.mp-rev      { background: #5a3a5e; }
.mp-tick { position: absolute; top: 0; bottom: 0; width: 1px; background: rgba(0,0,0,.25); pointer-events: none; }
.mp-shade { position: absolute; top: 0; bottom: 0; background: rgba(0,0,0,.62); pointer-events: none; }
.mp-head {
  position: absolute; top: -2px; bottom: -2px; width: 3px; margin-left: -1px;
  background: var(--accent-bright); box-shadow: 0 0 6px rgba(255,242,212,.9); pointer-events: none;
}

@media (max-width: 700px) {
  .map-player { bottom: 58px; padding: 8px 10px 10px; }
  .mp-where { font-size: 13px; }
}

.map.is-playing .map-legend { display: none; }

/* ─────────────────────────────── the Apocrypha, always labelled as such ── */

/* Books 67-80. Readable, and never mistakable for the 66: a dashed border in
   the dictionary's violet on every card, a note wherever they are read, and
   "· Apocrypha" on every search result. */
.tile.is-ap .tile-face, .tile.is-ap:not(.flippable) {
  border-left: 3px dashed var(--dict-accent);
}
.tile.is-ap .t-ref::after {
  content: ' · Apocrypha'; font-weight: 400; color: var(--dict-accent); font-size: .85em;
}
.result.is-ap .r-ref { color: var(--dict-accent); }
.ap-note {
  font: 12.5px/1.55 var(--sans); color: var(--text-dim);
  border-left: 2px dashed var(--dict-accent); padding: 4px 0 4px 11px; margin: 0 0 12px;
}
.r-opt {
  display: flex; align-items: center; gap: 6px; padding: 8px 13px; cursor: pointer;
  font-size: 12.5px; color: var(--text); border-bottom: 1px solid var(--line-soft);
  position: sticky; top: 0; z-index: 1; background: var(--surface);
}
.r-opt input { accent-color: var(--accent); }

/* ─────────────────────────────────────────────────────────── lineage ── */

/* Kin: the copper strand of the logo. People and the family lines between
   them, on the canvas and in the Lineage tree. */
:root { --thread-kin: #c08b68; }
:root[data-theme="parchment"] { --thread-kin: #8b5a3a; }
:root[data-theme="linen"]     { --thread-kin: #8a5c42; }

#view-lineage .map-tools { flex-wrap: wrap; }
.lineage { flex: 1; overflow: hidden; position: relative; background: var(--bg); }
.lineage svg { width: 100%; height: 100%; display: block; cursor: grab; touch-action: none; }
.lineage svg.grabbing { cursor: grabbing; }

.lin-node { cursor: pointer; outline: none; }
.lin-node rect { fill: var(--surface); stroke: var(--line); stroke-width: 1.2; }
.lin-node:hover rect, .lin-node:focus-visible rect { stroke: var(--thread-kin); }
.lin-node.line rect { stroke: var(--gold-soft); }
.lin-node.focus rect {
  fill: color-mix(in srgb, var(--thread-kin) 18%, var(--surface));
  stroke: var(--thread-kin); stroke-width: 2.4;
}
.lin-node.focus.line rect { stroke: var(--gold); }
.lin-name { fill: var(--text); font-size: 13px; font-weight: 600; }
.lin-node.line .lin-name { fill: var(--gold); }
.lin-sub  { fill: var(--text-faint); font-size: 10.5px; }

.lin-edge { fill: none; stroke: var(--text-faint); stroke-width: 1.3; opacity: .7; }
.lin-edge.line { stroke: var(--gold); stroke-width: 2.4; opacity: 1; }
.lin-edge.partner { stroke: var(--thread-kin); stroke-dasharray: 5 4; opacity: 1; }
.lin-edge.sibling { stroke-dasharray: 1 4; stroke-linecap: round; }
.lin-edge.uncertain { stroke-dasharray: 3 5; opacity: .45; }
.lin-gap { fill: var(--text-faint); font-size: 10.5px; font-style: italic; }

.lineage-find { position: relative; }
.lin-results {
  position: absolute; top: 100%; left: 0; z-index: 30; margin-top: 4px; padding: 4px;
  width: min(340px, 86vw); max-height: 360px; overflow: auto;
  background: var(--surface); border: 1px solid var(--line); border-radius: 8px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, .35);
}
.lin-res {
  display: block; width: 100%; text-align: left; background: none; border: 0;
  padding: 6px 8px; border-radius: 6px; color: var(--text); cursor: pointer; font-size: 13px;
}
.lin-res:hover { background: var(--surface-2); }
.lin-short { line-height: 1.55; margin: 8px 0 10px; }
.lin-path .chip { font-size: 11.5px; }
.lin-credit { margin-top: 18px; }
#lineage-rail .vref { color: var(--accent); cursor: pointer; border-bottom: 1px dotted var(--accent-soft); }

/* A person on the canvas. */
.tile.kind-person { border-left: 3px solid var(--thread-kin); }
.tile.kind-person .t-badge { color: var(--thread-kin); }
.tile .t-lineage {
  margin-top: 8px; background: none; border: 1px solid var(--line); border-radius: 6px;
  color: var(--thread-kin); font-size: 11.5px; padding: 3px 8px; cursor: pointer;
}
.tile .t-lineage:hover { border-color: var(--thread-kin); }
.edge.kin   { stroke: var(--thread-kin); stroke-width: 1.9; }
.edge.named { stroke: var(--thread-kin); stroke-dasharray: 3 3; }
.lin-more rect { fill: none; stroke: var(--line); stroke-dasharray: 4 3; }
.lin-more text { fill: var(--text-faint); font-size: 12px; }
.seg.wrap { flex-wrap: wrap; }
.tile.kind-person .t-back-body p { margin: 0 0 8px; line-height: 1.5; }
.tile.kind-person .t-back-body .vref { color: var(--accent); cursor: pointer; border-bottom: 1px dotted var(--accent-soft); }
/* A turned card still has its front in the way for clicks: backface-visibility
   hides a face but does not stop it catching the pointer, so nothing on a
   back could be clicked. Only the face showing takes clicks. */
.tile.flippable.flipped .tile-front,
.tile.flippable:not(.flipped) .tile-back { pointer-events: none; }
/* A card that has finished turning is laid flat (canvas.js _showFace), so its
   back takes clicks like any other element. */
.tile.flat .tile-inner { transition: none; transform: none; }
.tile.flat .tile-front { visibility: hidden; }
.tile.flat .tile-back  { transform: none; }

/* ─────────────────────────────────────────────── a journey on the map ── */

#map-svg.journeying .place-dot { opacity: .2; }
#map-svg.journeying .place-label { opacity: .35; }
.j-route { fill: none; stroke: var(--thread-kin); stroke-width: 2.2; stroke-dasharray: 6 5; stroke-linejoin: round; opacity: .9; }
.j-route.walked { stroke: var(--accent); stroke-width: 3; stroke-dasharray: none; }
.j-stop { cursor: pointer; }
.j-stop circle { fill: var(--surface); stroke: var(--thread-kin); stroke-width: 2; transition: r .2s, fill .2s; }
.j-stop text { fill: var(--text); font: 600 9.5px var(--sans); pointer-events: none; }
.j-stop .j-label {
  font-weight: 500; font-size: 11.5px; paint-order: stroke;
  stroke: var(--bg); stroke-width: 3px; stroke-linejoin: round;
}
.j-stop.past circle { fill: color-mix(in srgb, var(--thread-kin) 40%, var(--surface)); }
.j-stop.now circle { fill: var(--accent); stroke: var(--accent-bright, var(--accent)); r: 11px; }
/* A region or site the map has no exact point for (journeys.json "at"). */
.j-stop.approx circle { stroke-dasharray: 3 2; }
.j-caption { color: var(--text); font-weight: 600; margin-bottom: 2px; }
.map-journey {
  background: var(--surface); border: 1px solid var(--line); color: var(--text);
  border-radius: 7px; padding: 5px 8px; font-size: 13px; width: 118px; flex: 0 0 auto;
}
/* The toolbar holds search, filters, era, play and journeys; with the panel
   open there is not room for the hint as well, and the key it points at is
   in plain sight on the map. */
#map-play { white-space: nowrap; flex: 0 0 auto; }
#map-era { max-width: 150px; }
#map-search { width: 160px; }
@media (max-width: 1700px) { .map-tools > .hint { display: none; } }
.j-stop.now text { fill: var(--on-accent, #111); }
.j-stop.now .j-label { fill: var(--accent); font-weight: 700; }
.j-remembered { fill: none; stroke: var(--thread-kin); stroke-width: 1.5; stroke-dasharray: 2 3; opacity: .6; }
.j-row { cursor: pointer; }
.j-row.now { background: var(--surface-2); box-shadow: inset 3px 0 0 var(--accent); }
.j-add {
  background: none; border: 1px solid var(--line); border-radius: 6px; color: var(--text-dim);
  width: 26px; height: 24px; cursor: pointer; align-self: center;
}
.j-add:hover { color: var(--accent); border-color: var(--accent-soft); }

/* Meaning: verses alike in sense, from the embeddings (scripts/neighbours.mjs). */
:root { --thread-meaning: #a595d6; }
:root[data-theme="parchment"] { --thread-meaning: #6a5799; }
:root[data-theme="linen"]     { --thread-meaning: #675a98; }
.edge.meaning { stroke: var(--thread-meaning); stroke-dasharray: 10 4 2 4; }
.tile .t-why[data-kind="meaning"] { color: var(--thread-meaning); }
.meaning-score { color: var(--thread-meaning); font-size: 11px; }

/* ─────────────────────────────────────────── a family on the map ── */

.fam-person { --c: #e0a458; }
.fam-route { fill: none; stroke: var(--c); stroke-width: 2.4; stroke-linejoin: round; opacity: .85; }
.fam-person.focus .fam-route { stroke-width: 3.4; }
.fam-stop { fill: var(--c); opacity: .9; }
.fam-end { fill: var(--c); stroke: var(--bg); stroke-width: 1.5; }
.fam-label {
  fill: var(--c); font: 600 11.5px var(--sans); paint-order: stroke;
  stroke: var(--bg); stroke-width: 3px; stroke-linejoin: round; pointer-events: none;
}
.fam-row {
  display: grid; grid-template-columns: 14px 1fr auto; gap: 10px; align-items: center;
  padding: 6px; border-radius: 7px; cursor: pointer; transition: opacity .2s;
}
.fam-row:hover { background: var(--surface-2); }
.fam-row.dim { opacity: .4; }
.fam-swatch { width: 12px; height: 12px; border-radius: 50%; background: var(--c); }
.fam-who .faint { font-size: 11.5px; }

/* Books 81-88, beyond the canon: dotted where the Apocrypha is dashed, and
   named on every card and search result. */
.tile.is-ex .tile-face, .tile.is-ex:not(.flippable) { border-left: 3px dotted var(--dict-accent); }
.tile.is-ex .t-ref::after { content: ' · beyond the canon'; font-weight: 400; color: var(--dict-accent); font-size: .85em; }
.result.is-ex .r-ref { color: var(--dict-accent); }

/* The Daily Ten card's way onto the canvas: gold, like Follow its threads. */
.mini.follow-mini { color: var(--gold); border-color: var(--gold-soft); }

/* The back of a Daily Ten card: its reference, and the way to reading size. */
.card-ref-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.card-ref-row .card-expand { font-size: 14px; }

/* ─────────────────────────────── Lineage, left to right, over a map ── */

/* Era bands behind the columns, labelled along the top. */
.lin-band { fill: color-mix(in srgb, var(--surface) 55%, transparent); }
.lin-band.alt { fill: color-mix(in srgb, var(--surface-2) 60%, transparent); }
.lin-band-label { fill: var(--text-dim); font: 600 12px var(--sans); letter-spacing: .04em; text-transform: uppercase; }
.lin-time { fill: var(--text-faint); font: italic 12px var(--sans); }

/* One color only on the tree: gold for the line of Jesus. The stripe used to
   show the part of the Bible a person is first named in, which fought the
   era columns: the kings' contemporaries named only in Luke 3 wore Gospels
   orchid under "Divided Monarchy". The era says when; the card says where. */
.lin-node rect.lin-stripe { stroke: none; fill: var(--line); }
.lin-node.line rect.lin-stripe { fill: var(--gold); }

/* The tree's key, in the Lineage toolbar. */
.lin-key { display: inline-flex; flex-wrap: wrap; gap: 6px 14px; align-items: center; font-size: 12px; color: var(--text-dim); }
.lk-item { display: inline-flex; align-items: center; gap: 6px; cursor: help; white-space: nowrap; }
.lk-gold { width: 18px; height: 3px; border-radius: 2px; background: var(--gold); }
.lk-dot { width: 18px; border-top: 2px dotted var(--text-faint); }
.lk-era { width: 18px; height: 12px; border-radius: 3px; background: var(--surface-2); border: 1px solid var(--line); }
.lin-route-dot { stroke: var(--bg); stroke-width: 1.5; }

/* The map beneath the tree. */
.lineage-map {
  height: 34%; min-height: 190px; display: flex; flex-direction: column;
  border-top: 1px solid var(--line); background: var(--map-sea, var(--bg));
}
.lineage-map-bar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 6px 12px; background: var(--surface); border-bottom: 1px solid var(--line);
}
.lineage-map-bar .hint { flex: 1; min-width: 160px; }
#lineage-map-svg { flex: 1; width: 100%; display: block; cursor: pointer; }
.lm-land { fill: var(--map-land, var(--surface-2)); stroke: var(--map-coast, var(--line)); stroke-width: .7; }
.lm-route { --c: var(--thread-kin); }
.lm-line { fill: none; stroke: var(--c); stroke-width: 2.2; stroke-linejoin: round; opacity: .9; }
.lm-stop { fill: var(--c); stroke: var(--bg); stroke-width: 1.2; }
.lm-num { fill: var(--bg); font: 700 9px var(--sans); pointer-events: none; }
.lm-label {
  fill: var(--c); font: 600 11px var(--sans); paint-order: stroke;
  stroke: var(--bg); stroke-width: 3px; stroke-linejoin: round; pointer-events: none;
}

/* The running build, faint, beside Credits. */
.build { font: 11px var(--sans); color: var(--text-faint); white-space: nowrap; cursor: default; }
/* Kept on every page: it is how a deploy is told from a stale cache. Hidden
   below 1500px, where the top bar has no room for it (the 1366 fix). */
@media (max-width: 1500px) { .build { display: none; } }

/* On the front of a Daily Ten card once it has been read: what was made of it. */
.card-seen { color: var(--good); font-size: 11px; font-weight: 600; }

/* ─────────────────────────────── laptop screens (1366 × 768 and so on) ── */
/* Above phone widths only; the phone rules higher up stand as they are. */

/* The key never runs off the top of the canvas; a long one scrolls. */
.legend { display: flex; flex-direction: column; max-height: calc(100% - 24px); }
.legend-body { overflow-y: auto; min-height: 0; }

@media (min-width: 821px) {
  .tabs { flex-wrap: nowrap; }
  .tab { white-space: nowrap; }
  .thread-bar { flex-wrap: nowrap; }
  .thread-bar > * { flex-shrink: 0; }
  .thread-bar > #canvas-hint {
    flex: 1 1 0; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
}
@media (min-width: 821px) and (max-width: 1500px) {
  .topbar { gap: 12px; }
  .tab { padding: 7px 9px; }
  #search { width: 230px; }
  .topbar-right { gap: 8px; }
}
@media (min-width: 821px) and (max-width: 1200px) {
  .brand h1 { display: none; }
  #search { width: 180px; }
}
@media (min-width: 821px) and (max-width: 1500px) {
  .topbar:has(#who) #search { width: 170px; }   /* /me: the corner needs the room */
}

/* ─────────────────────────────── an adventure's steps (app.js updateSteps) ── */

.adv-steps {
  position: absolute; top: 12px; left: 12px; right: 12px; margin: 0 auto; width: fit-content; z-index: 45;
  display: flex; align-items: center; gap: 10px; max-width: 620px;
  padding: 8px 10px; border: 1px solid var(--line); border-radius: 10px;
  background: color-mix(in srgb, var(--surface) 94%, transparent); backdrop-filter: blur(3px);
  box-shadow: 0 8px 26px rgba(0,0,0,.35);
}
.adv-steps[hidden] { display: none; }
.adv-steps .btn { flex: 0 0 auto; }
.adv-steps .btn:disabled { opacity: .35; cursor: default; }
.as-text { flex: 1; min-width: 0; }
.as-count { font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase; color: var(--text-faint); }
.as-cap { font: 14px/1.35 var(--serif); color: var(--text); }
.as-close { background: none; border: 0; color: var(--text-faint); cursor: pointer; padding: 4px; }
.as-close:hover { color: var(--text); }
@media (max-width: 700px) { .adv-steps { top: 8px; padding: 6px 8px; } .as-cap { font-size: 13px; } }

/* ───────────────────────────── the day's strand (daily.js load, _band) ── */

/* Full-width lines across the card grid: the verse of the day, the button
   that takes the whole strand to the canvas, then the verses joined to it. */
.daily-band { grid-column: 1 / -1; margin: 4px 0 -4px; }
.daily-band h3 { margin: 0; font: 600 15px var(--serif); color: var(--text); }
.daily-band p { margin: 2px 0 0; font-size: 12.5px; }
.daily-band:first-child { margin-top: 0; }

.daily-follow { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 2px 0 2px; }
.follow-strand { font-size: 15px; padding: 10px 18px; border-radius: 9px; }
.daily-follow span { font-size: 12.5px; }

/* The verse of the day sits alone on its row, so the eye starts there. */
.card.is-anchor { grid-column: 1 / -1; max-width: 520px; }

/* Why a card is in today's strand, in the colors the canvas uses for the same
   kinds of thread. */
.card-join { color: var(--text-faint); }
.card-join.is-meaning { color: var(--thread-meaning); }
.card-join.is-leap { color: var(--thread-leap); }
@media (max-width: 700px) {
  .card.is-anchor { max-width: none; }
  .follow-strand { width: 100%; justify-content: center; }
}

/* ──────────────────────────────────────────────────────────── tablets ── */

/* Between the phone rules (700px) and the desktop ones (821px) there was a
   gap, and a Samsung Tab A9 in landscape lands in it: ~960 x 600. The map
   toolbar needed 949px inside a 604px column — the panel had taken the rest —
   so Play, the era picker and the search ran off the edge with no way to
   reach them, on a breakpoint that never scrolled them either.

   Two fixes, both of which help every awkward width, not only this one:
   the toolbars wrap to a second row instead of overflowing, and the panel
   starts closed (app.js) so the view keeps its width. Wrapping rather than
   scrolling sideways because .thread-bar holds an absolutely positioned menu,
   and a scroll container would clip it. */

/* From tablet portrait up. Below this a phone keeps the sideways scroll:
   wrapping a toolbar at 375px makes four rows of chrome above the view. */
@media (min-width: 560px) and (max-width: 1200px) {
  .map-tools, .canon-tools, .thread-bar { flex-wrap: wrap; row-gap: 8px; overflow: visible; }
  /* The running hints are the first thing worth losing when room is short. */
  .map-tools > .hint, .canon-tools > .hint { display: none; }
}

/* The player and the key share the bottom of the map. On a short screen the
   player covers the key, which is why the key hides while it is open — but
   the key has to be reachable again the moment it closes, and on a tablet
   the player sat over the tab bar as well. */
@media (max-width: 1200px) and (max-height: 820px) {
  .map-player { bottom: 10px; padding: 8px 10px 10px; }
  .map-legend { max-height: 46vh; overflow-y: auto; }
}

/* ────────────────────────────── a study path, on the daily tab (daily.js) ── */

.path-day {
  margin: 8px 26px 4px; padding: 16px 18px;
  border: 1px solid var(--line); border-radius: 12px; background: var(--surface);
}
.path-day.is-offer { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.path-day.is-offer h3 { margin: 0; }
.path-day.is-offer p { margin: 0; flex: 1 1 260px; font-size: 13px; }
.path-head { display: flex; align-items: center; gap: 10px; }
.path-name { font-size: 11px; letter-spacing: .09em; text-transform: uppercase; color: var(--accent); }
.path-count { font-size: 11px; color: var(--text-faint); flex: 1; }
.path-day > h3 { margin: 4px 0 12px; font: 600 19px var(--serif); }

.path-step { display: flex; gap: 12px; padding: 10px 0; border-top: 1px solid var(--line-soft); }
.ps-n {
  flex: 0 0 22px; height: 22px; border-radius: 50%; text-align: center; line-height: 22px;
  font-size: 11px; background: var(--surface-2); color: var(--text-dim);
}
.ps-body { flex: 1; min-width: 0; }
.ps-label { font-size: 10.5px; letter-spacing: .09em; text-transform: uppercase; color: var(--text-faint); margin-bottom: 5px; }
.ps-notice { margin: 0; padding-left: 18px; font-size: 13.5px; line-height: 1.55; }
.ps-notice li { margin-bottom: 5px; }
.ps-verse { font-family: var(--serif); font-size: 15px; line-height: 1.5; margin-bottom: 4px; }
.ps-caption { font-size: 13px; color: var(--text-dim); margin: 8px 0 0; line-height: 1.55; }
.ps-root { border-left: 2px solid var(--accent-soft); padding-left: 10px; }
.ps-keep { font-family: var(--serif); font-size: 15px; margin-bottom: 7px; }
.ps-line {
  width: 100%; padding: 8px 10px; border-radius: 8px;
  background: var(--bg); border: 1px solid var(--line); color: var(--text); outline: none;
}
.ps-line:focus { border-color: var(--accent-soft); }
.path-day .chips { margin-top: 8px; }
.chip.is-meaning { border-color: var(--thread-meaning); color: var(--thread-meaning); }
.path-foot { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding-top: 12px; border-top: 1px solid var(--line-soft); }
.path-next { font-style: italic; }
.path-note { font-size: 11.5px; }
@media (max-width: 700px) {
  .path-day { margin: 8px 14px 4px; padding: 13px 14px; }
  .path-foot .btn { width: 100%; }
}

/* ───────────────────────────────────── the prayers of Scripture (prayers.js) ── */

/* A .view is a flex row that does not scroll; a full-page reading view has to
   say so for itself, as #view-about and #view-howto each do. Every new view of
   this kind needs this line, and forgetting it is a page that simply stops at
   the bottom of the window. */
#view-prayers { flex-direction: column; overflow: auto; }

.pr-kinds { display: flex; flex-wrap: wrap; gap: 7px; margin: 14px 0 6px; }
.pr-kind {
  background: var(--surface); border: 1px solid var(--line); color: var(--text-dim);
  border-radius: 999px; padding: 5px 13px; font-size: 12.5px; cursor: pointer;
}
.pr-kind:hover { border-color: var(--accent-soft); color: var(--text); }
.pr-kind.on { background: var(--accent-soft); border-color: var(--accent); color: var(--on-accent); }

.pr-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(290px, 1fr)); gap: 14px; margin: 10px 0 6px; }
.pr-card {
  border: 1px solid var(--line); border-radius: 11px; padding: 14px 15px;
  background: var(--surface); display: flex; flex-direction: column; gap: 6px;
}
.pr-top { display: flex; align-items: center; gap: 8px; }
.pr-who { font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--text-faint); flex: 1; }
.pr-tag {
  font-size: 10.5px; padding: 2px 8px; border-radius: 999px; cursor: help;
  background: var(--surface-2); color: var(--text-dim);
}
.pr-tag.is-lament { color: var(--info-dim); }
.pr-tag.is-confessing { color: var(--gospel-dim, var(--text-dim)); }
.pr-tag.is-thanks { color: var(--good-dim); }
.pr-tag.is-yielding { color: var(--accent); }
.pr-name { margin: 0; font: 600 16px var(--serif); }
.pr-ref { font-size: 12px; color: var(--accent); }
.pr-blurb { margin: 2px 0 0; font-size: 13.5px; line-height: 1.55; color: var(--text-dim); flex: 1; }
.pr-acts { display: flex; gap: 8px; margin-top: 8px; }
@media (max-width: 700px) {
  .pr-grid { grid-template-columns: 1fr; }
}

/* The prayer cards turn over like the daily ones; the back is the prayer. */
.pr-card { height: 300px; }
.pr-card .card-front, .pr-card .card-back { display: flex; flex-direction: column; gap: 6px; }
.pr-card .pr-blurb { flex: 1; overflow: hidden; }
.pr-foot { color: var(--text-faint); }
.pr-text { flex: 1; overflow-y: auto; margin: 6px 0 0; padding-right: 4px; }
.pr-line { margin: 0 0 7px; font-family: var(--serif); font-size: 13.5px; line-height: 1.55; }
.pr-n { font-size: 10px; color: var(--text-faint); vertical-align: super; margin-right: 4px; font-family: var(--sans); }
.pr-card .pr-acts { margin-top: 6px; }
.pr-pick { margin: 10px 0 0; }
.pr-tag.is-psalm { color: var(--accent); }
.pr-part { margin: 16px 0 0; font: 600 14px var(--sans); letter-spacing: .04em; color: var(--text-dim); }
.tt-differs { font-size: 12.5px; line-height: 1.55; color: var(--text-dim); padding: 8px 2px 0; }
.tt-row .l-ref { white-space: normal; }

/* A book's written introduction in the Whole Bible panel (canon.js pickBook). */
.bi-row { display: grid; grid-template-columns: 96px 1fr; gap: 10px; padding: 6px 0; }
.bi-label { font-size: 10.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--text-faint); padding-top: 2px; }
.bi-text { font-size: 13.5px; line-height: 1.55; }
.bi-verse { margin-top: 10px; padding-left: 10px; border-left: 2px solid var(--accent-soft); }
.bi-quote { font-family: var(--serif); font-size: 14px; line-height: 1.55; margin-bottom: 6px; }
.bi-cite { font-size: 11.5px; }
/* The same introduction in the overlay, where it has room to be read. */
.bi-large { margin-bottom: 18px; }
.bi-large .bi-row { grid-template-columns: 120px 1fr; padding: 8px 0; }
.bi-large .bi-text { font-size: 14.5px; line-height: 1.65; }
.bi-large .bi-quote { font-size: 16px; }
@media (max-width: 700px) {
  .bi-row, .bi-large .bi-row { grid-template-columns: 1fr; gap: 2px; }
}
.tm-row.tm-topic .tm-name { color: var(--text); }
.tm-row.tm-topic:hover { background: var(--surface-2); }

/* The two halves of the Prayers tab, named at the top rather than stacked. */
.pr-switch { display: flex; gap: 10px; flex-wrap: wrap; margin: 16px 0 4px; }
.pr-half {
  display: flex; align-items: center; gap: 10px; cursor: pointer;
  background: var(--surface); border: 1px solid var(--line); border-radius: 10px;
  padding: 11px 16px; color: var(--text-dim); font-size: 14px;
}
.pr-half:hover { border-color: var(--accent-soft); color: var(--text); }
.pr-half.on { background: var(--surface-2); border-color: var(--accent); color: var(--text); }
.pr-half .ph-n { font-size: 11.5px; color: var(--text-faint); }
.pr-half.on .ph-n { color: var(--accent); }
.pr-rows { margin-bottom: 14px; }

/* A prayer opened at reading size, in the shared card overlay. */
.pr-large { margin-bottom: 14px; }
.pr-large .pr-line { font-size: 16px; line-height: 1.7; margin-bottom: 10px; }
.card-verse-note { color: var(--text-dim); font-size: 13.5px; line-height: 1.6; margin: 0 0 14px; }
.pr-large-acts { display: flex; gap: 10px; flex-wrap: wrap; }

/* Who is reading, at /me (app.js presenceLine). */
.pz-row { display: flex; gap: 22px; margin: 6px 0 8px; }
.pz-n { font: 600 26px var(--serif); color: var(--accent); line-height: 1.1; }
.pz-l { font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--text-faint); }
/* The meaning of a name on a Lineage card, from Strong's or Easton's. */
.lin-meaning { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin: 10px 0 2px; padding: 8px 12px; border-left: 2px solid var(--gold-soft); background: color-mix(in srgb, var(--gold) 5%, transparent); border-radius: 0 4px 4px 0; cursor: help; }
.lin-meaning-label { font-size: 10.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--text-faint); }
.lin-meaning-text { font-family: var(--serif); font-size: 15.5px; line-height: 1.45; color: var(--gold-dim); }
