/* ------------------------------------------------------------------ *
   The Book — chronological reader
   Light is a leaf of vellum on a table; dark is the same room unlit.
   Both are defined as complete palettes so neither depends on the other.
 * ------------------------------------------------------------------ */

/* Two accents, and the difference between them is the whole system.

   RUBRIC is the red a scribe changed pens for. In a manuscript it marks
   the structure of the text and nothing else — the chapter number, the
   verse number, the heading, the initial — which is where the word
   rubric comes from, and it does exactly that job here.

   TYRIAN is the site's own machinery: a link, a focus ring, the control
   you just pressed. It is the argaman of Exodus 26 and the trade of
   Lydia in Acts 16, the dye of the coast these texts were written on.

   So a red mark on this site is the book speaking and a purple one is
   the reader speaking, and neither is ever used for the other's work.
   Everything else follows from materials: unbleached parchment for the
   ground, a brighter leaf raised off it, and iron-gall ink — which
   oxidises violet-black rather than grey — for type. Dark inverts the
   two, which is what a photographic negative of a manuscript looks
   like: the leaf goes to the colour of the ink and the ink to the
   colour of the leaf.

   No font, image or texture is fetched. The site ships no dependencies
   and its single-file build has to open from file:// with the network
   off, so the grain of the paper is a gradient and the type is whatever
   the device already has. */

:root {
  --paper:      #eee7d9;
  --paper-2:    #e4dbc9;
  --raised:     #fcf9f2;
  --ink:        #1d1822;
  --ink-soft:   #554d5c;
  --ink-faint:  #837a89;
  --rule:       #d4cab8;
  --rule-soft:  #e3dac9;
  --accent:     #632a55;
  --accent-2:   #83406f;
  --accent-bg:  #efe3ec;
  --rubric:     #9b2f21;
  --rubric-2:   #b8503f;
  --rubric-bg:  #f5e4df;
  --gilt:       #9d7526;
  --good:       #2f6b5f;
  --good-bg:    #dfeae6;
  --warn:       #8a5a12;
  --warn-bg:    #f2e7cf;
  --fix:        #33587e;
  --fix-bg:     #e0e7f0;
  --mark:       #f4dd9c;

  /* The gutter of a bound leaf, and the grain across it. Both are drawn
     rather than photographed, and both are nearly invisible on purpose:
     texture a reader notices is texture in the way. */
  --spine:      rgba(74, 55, 30, .17);
  --grain:      rgba(74, 55, 30, .022);
  --wash-1:     rgba(255, 253, 246, .75);
  --wash-2:     rgba(99, 42, 85, .045);

  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua",
           Georgia, "Times New Roman", serif;
  --sans:  ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
           "Helvetica Neue", Arial, sans-serif;
  --mono:  ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --shadow: 0 1px 2px rgba(58, 44, 24, .07), 0 10px 30px rgba(58, 44, 24, .09);
  --radius: 10px;
  --measure: 34rem;
  /* The leaf the reader is set on, and the width every control above it
     lines up with. One number, so they cannot drift apart. */
  --leaf: calc(var(--measure) + 5rem);
  --reader-size: 1.075rem;

  /* Native widgets -- select dropdowns, scrollbars -- are drawn by the
     browser itself, and follow this rather than the palette above. */
  color-scheme: light;
}

/* The unlit room. Kept as one block and applied twice, because the theme
   can be chosen as well as inherited and neither route may be the poor
   relation of the other. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper:     #14121a;
    --paper-2:   #1c1925;
    --raised:    #211d2b;
    --ink:       #ece3d3;
    --ink-soft:  #aea5b1;
    --ink-faint: #837a8b;
    --rule:      #383140;
    --rule-soft: #2b2535;
    --accent:    #d29ac1;
    --accent-2:  #e7b8d5;
    --accent-bg: #2d2231;
    --rubric:    #e2836b;
    --rubric-2:  #f0a893;
    --rubric-bg: #301f1d;
    --gilt:      #d9b46b;
    --good:      #78c0b0;
    --good-bg:   #162623;
    --warn:      #d9b269;
    --warn-bg:   #262015;
    --fix:       #8ab3d8;
    --fix-bg:    #182231;
    --mark:      #5a4520;
    --spine:     rgba(0, 0, 0, .55);
    --grain:     rgba(255, 250, 235, .014);
    --wash-1:    rgba(60, 52, 78, .40);
    --wash-2:    rgba(210, 154, 193, .05);
    --shadow: 0 1px 2px rgba(0, 0, 0, .45), 0 12px 34px rgba(0, 0, 0, .40);
    color-scheme: dark;
  }
}

:root[data-theme="light"] { color-scheme: light; }

:root[data-theme="dark"] {
  --paper:     #14121a;
  --paper-2:   #1c1925;
  --raised:    #211d2b;
  --ink:       #ece3d3;
  --ink-soft:  #aea5b1;
  --ink-faint: #837a8b;
  --rule:      #383140;
  --rule-soft: #2b2535;
  --accent:    #d29ac1;
  --accent-2:  #e7b8d5;
  --accent-bg: #2d2231;
  --rubric:    #e2836b;
  --rubric-2:  #f0a893;
  --rubric-bg: #301f1d;
  --gilt:      #d9b46b;
  --good:      #78c0b0;
  --good-bg:   #162623;
  --warn:      #d9b269;
  --warn-bg:   #262015;
  --fix:       #8ab3d8;
  --fix-bg:    #182231;
  --mark:      #5a4520;
  --spine:     rgba(0, 0, 0, .55);
  --grain:     rgba(255, 250, 235, .014);
  --wash-1:    rgba(60, 52, 78, .40);
  --wash-2:    rgba(210, 154, 193, .05);
  --shadow: 0 1px 2px rgba(0, 0, 0, .45), 0 12px 34px rgba(0, 0, 0, .40);
  color-scheme: dark;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.62;
  -webkit-text-size-adjust: 100%;
}

/* The ground the leaves sit on: two soft washes and the laid lines of a
   sheet of paper, drawn with gradients because nothing here may be
   fetched. Fixed and behind everything, so it does not scroll with the
   text and does not repaint as the page grows. Dropped for a reader who
   has asked for less: it is decoration and nothing depends on it. */
body::before {
  content: "";
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background:
    repeating-linear-gradient(0deg, var(--grain) 0 1px, transparent 1px 3px),
    radial-gradient(120% 80% at 8% -15%, var(--wash-1), transparent 62%),
    radial-gradient(90% 65% at 100% 0%, var(--wash-2), transparent 58%),
    var(--paper);
}
@media (prefers-reduced-transparency: reduce) {
  body::before { background: var(--paper); }
}

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--accent-2); }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--accent); color: #fff; padding: .6rem 1rem;
}
.skip:focus { left: .5rem; top: .5rem; }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }

/* ---------- top bar ---------- */

.topbar {
  position: sticky; top: 0; z-index: 40;
  display: flex; align-items: center; gap: 1rem;
  padding: .55rem clamp(.75rem, 3vw, 1.6rem);
  background: color-mix(in srgb, var(--paper) 86%, transparent);
  backdrop-filter: blur(12px) saturate(1.1);
  border-bottom: 1px solid var(--rule);
  flex-wrap: wrap;
}
/* The head rule a printer sets under a running head: a hairline of the
   book's own red, not another grey line. */
.topbar::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
  background: linear-gradient(90deg,
    var(--rubric) 0, color-mix(in srgb, var(--rubric) 30%, transparent) 38%,
    transparent 72%);
  opacity: .55; pointer-events: none;
}

/* The wordmark. The subtitle is the whole argument of the project in five
   words, so it belongs in the mark rather than buried on the home page. */
.brand {
  display: inline-flex; align-items: center; gap: .5rem;
  color: var(--ink); text-decoration: none; white-space: nowrap;
}
.brand-mark { color: var(--rubric); display: flex; align-items: center; }
.brand:hover .brand-mark { color: var(--rubric-2); }
.brand-text { display: flex; flex-direction: column; line-height: 1.05; }
.brand-name {
  font-family: var(--serif); font-size: 1.16rem; font-weight: 600;
  letter-spacing: .005em;
}
.brand-sub {
  font-size: .62rem; color: var(--ink-faint);
  letter-spacing: .07em; text-transform: uppercase;
}
.brand:hover .brand-name { color: var(--accent); }

/* Visible only to screen readers. */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

.nav { display: flex; gap: .15rem; flex: 1; flex-wrap: wrap; }
.nav a {
  padding: .34rem .68rem; border-radius: 999px;
  color: var(--ink-soft); text-decoration: none;
  font-size: .875rem; white-space: nowrap;
}
.nav a:hover { background: var(--paper-2); color: var(--ink); }
.nav a[aria-current="page"] {
  background: var(--accent-bg); color: var(--accent); font-weight: 600;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 22%, transparent);
}

.tools { display: flex; gap: .3rem; align-items: center; }

button.ghost {
  font: inherit; font-size: .84rem;
  background: transparent; color: var(--ink-soft);
  border: 1px solid var(--rule); border-radius: 999px;
  padding: .3rem .7rem; cursor: pointer;
}
button.ghost:hover { background: var(--paper-2); color: var(--ink); border-color: var(--ink-faint); }

/* ---------- layout ---------- */

main { padding: clamp(1.2rem, 4vw, 2.6rem) clamp(.9rem, 4vw, 2rem) 4rem; }
.wrap { max-width: 60rem; margin: 0 auto; }
.wrap-wide { max-width: 74rem; margin: 0 auto; }

h1, h2, h3, h4 {
  font-family: var(--serif); line-height: 1.18; font-weight: 600;
  text-wrap: balance;
}
h1 {
  font-size: clamp(1.9rem, 5.2vw, 3rem); margin: 0 0 .6rem;
  letter-spacing: -.018em;
}
h2 { font-size: 1.48rem; margin: 2.6rem 0 .7rem; letter-spacing: -.008em; }
h3 { font-size: 1.1rem; margin: 1.6rem 0 .4rem; }

.lede { font-size: 1.08rem; color: var(--ink-soft); max-width: 44rem; }
.muted { color: var(--ink-faint); font-size: .875rem; }
.tiny  { font-size: .78rem; color: var(--ink-faint); }

.rule { border: 0; border-top: 1px solid var(--rule); margin: 2.4rem 0; }

/* The canon table's own footnotes: why a book is absent, or which part of
   one is here. Closed by default -- the table is a table first. */
.why { margin-top: .3rem; max-width: 34rem; }
.why > summary { cursor: pointer; color: var(--accent); }
.why p { margin: .35rem 0 0; }

/* ---------- home ---------- */

/* A title page. The rule above the title is the one a printer sets there,
   and the mark on it is the same five rectangles as the tab icon. */
.hero { padding: 1.6rem 0 .5rem; position: relative; }
.hero::before {
  content: "";
  display: block; width: 3.2rem; height: 2px; margin: 0 0 1.3rem;
  background: var(--rubric); opacity: .8;
}
.hero h1 { max-width: 18ch; }
.hero .lede { margin-top: 1rem; }

/* The numbers are a colophon rather than a dashboard: a row of figures
   under a rule, in the book's own type, with nothing boxed. */
.stats {
  display: grid; gap: 0 1.6rem; margin: 2.2rem 0 .5rem;
  grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));
  border-top: 1px solid var(--rule);
  padding-top: 1rem;
}
.stat { padding: .35rem 0; }
.stat b {
  display: block; font-family: var(--serif); font-size: 1.75rem;
  font-weight: 600; letter-spacing: -.02em; line-height: 1.1;
  font-variant-numeric: tabular-nums lining-nums;
}
.stat span {
  display: block; margin-top: .15rem;
  font-size: .7rem; color: var(--ink-faint);
  text-transform: uppercase; letter-spacing: .09em;
}

.callout {
  border-left: 3px solid var(--rubric);
  background: var(--paper-2);
  padding: .9rem 1.1rem; border-radius: 0 var(--radius) var(--radius) 0;
  margin: 1.6rem 0; font-size: .94rem;
}
.callout p { margin: .35rem 0; }
.callout p:first-child { margin-top: 0; }
.callout p:last-child { margin-bottom: 0; }

/* ---------- timeline ---------- */

.timeline { position: relative; margin: 2rem 0 0; padding-left: 1.6rem; }
.timeline::before {
  content: ""; position: absolute; left: .34rem; top: .6rem; bottom: .6rem;
  width: 2px; background: linear-gradient(var(--rule), var(--rule-soft));
}

.era { position: relative; margin: 0 0 .5rem; }
.era::before {
  content: ""; position: absolute; left: -1.6rem; top: 1.15rem;
  width: .72rem; height: .72rem; border-radius: 50%;
  background: var(--paper); border: 2px solid var(--accent);
}
.era[data-collection="1"]::before { border-color: var(--ink-faint); }

.era-head {
  width: 100%; text-align: left; cursor: pointer;
  background: transparent; border: 0; border-radius: var(--radius);
  padding: .75rem .8rem; font: inherit; color: inherit;
  display: flex; align-items: baseline; gap: .7rem; flex-wrap: wrap;
}
.era-head:hover { background: var(--paper-2); }
.era-num {
  font-family: var(--mono); font-size: .72rem; color: var(--accent);
  border: 1px solid var(--accent); border-radius: 4px;
  padding: .05rem .3rem; letter-spacing: .04em;
}
.era-num { color: var(--rubric); border-color: color-mix(in srgb, var(--rubric) 35%, transparent); }
.era[data-collection="1"] .era-num { color: var(--ink-faint); border-color: var(--rule); }
.era-name { font-family: var(--serif); font-size: 1.14rem; font-weight: 600; }
.era-date { color: var(--ink-faint); font-size: .84rem; font-variant-numeric: tabular-nums; }
.era-count { margin-left: auto; color: var(--ink-faint); font-size: .78rem; }

.era-body { padding: 0 .8rem 1.1rem 1.5rem; display: none; }
.era[open] .era-body, .era.open .era-body { display: block; }
.era-intro { font-size: .93rem; color: var(--ink-soft); max-width: 46rem; margin: 0 0 1rem; }

.works { display: grid; gap: .4rem; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); }
.work {
  display: block; text-decoration: none; color: inherit;
  background: var(--raised); border: 1px solid var(--rule-soft);
  border-radius: 8px; padding: .55rem .7rem;
}
.work {
  background: var(--raised);
  transition: border-color .15s, background-color .15s, transform .15s;
}
.work:hover {
  border-color: var(--accent); background: var(--accent-bg);
  transform: translateY(-1px);
}
@media (prefers-reduced-motion: reduce) {
  .work { transition: none; }
  .work:hover { transform: none; }
}
.work-title { font-family: var(--serif); font-size: .97rem; display: block; }
.work-meta { font-size: .74rem; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.work.note-only { background: transparent; border-style: dashed; }
.work.note-only .work-meta { font-style: italic; }

/* ---------- contents ---------- */

.toolbar {
  display: flex; gap: .5rem; align-items: center; flex-wrap: wrap;
  margin: 1.4rem 0;
}
.seg { display: inline-flex; border: 1px solid var(--rule); border-radius: 999px; overflow: hidden; }
.seg button {
  font: inherit; font-size: .82rem; padding: .34rem .85rem;
  background: transparent; color: var(--ink-soft); border: 0; cursor: pointer;
}
.seg button[aria-pressed="true"] { background: var(--accent); color: #fff; }

input[type="search"], input[type="text"], select {
  font: inherit; font-size: .92rem; color: var(--ink);
  background: var(--raised); border: 1px solid var(--rule);
  border-radius: 8px; padding: .45rem .7rem;
}
input[type="search"] { width: 100%; }

table.grid { width: 100%; border-collapse: collapse; font-size: .87rem; }
table.grid th, table.grid td {
  text-align: left; padding: .42rem .6rem; border-bottom: 1px solid var(--rule-soft);
  vertical-align: top;
}
/* The head is not sticky, and cannot be. It was, at top: 3.2rem, to clear
   the bar -- but a wide table is wrapped in .scroller so a phone can push it
   sideways, and a box that scrolls in one axis is a scrollport in both. A
   sticky offset is measured from the scrollport rather than the viewport,
   and sticky pushes an element *down* to its offset even at scroll zero, so
   the head was landing 51px into the table and sitting on top of the first
   row -- The Song of the Sea on the contents, Genesis on the canons: in
   each case the first line of the thing being listed. Nothing in CSS gets
   both, because the wrapper that makes the table scrollable is the same box
   that redefines what the head is sticky to. The row is worth more than the
   head, so the head goes. */
table.grid thead th {
  border-bottom: 1px solid var(--rule); font-size: .78rem;
  text-transform: uppercase; letter-spacing: .05em; color: var(--ink-faint);
  font-weight: 600;
}
table.grid tbody tr:hover { background: var(--paper-2); }
.scroller { overflow-x: auto; border-radius: var(--radius); }

.yes { color: var(--good); font-weight: 700; }
.no  { color: var(--ink-faint); }
.part { color: var(--warn); font-weight: 700; }

/* ---------- threads ---------- */

.thread-cards {
  display: grid; gap: .8rem; margin: 1.8rem 0;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
}
.thread-card {
  display: block; text-decoration: none; color: inherit;
  background: var(--raised); border: 1px solid var(--rule-soft);
  border-radius: var(--radius); padding: 1.1rem 1.2rem;
  border-left: 3px solid var(--accent);
}
.thread-card {
  background: var(--raised); box-shadow: var(--shadow);
  border-left-color: var(--rubric);
}
.thread-card:hover { border-color: var(--accent); background: var(--accent-bg); }
.thread-card h2 {
  margin: 0 0 .45rem; font-size: 1.16rem; line-height: 1.25;
  text-wrap: balance;
}
.thread-card p { margin: 0 0 .7rem; font-size: .89rem; color: var(--ink-soft); }
.thread-meta {
  font-size: .72rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--ink-faint);
}

/* The spine down the left is the passage of time; each stop hangs off it. */
.thread { list-style: none; margin: 2rem 0 0; padding: 0; position: relative; }
.thread::before {
  content: ""; position: absolute; left: 3.1rem; top: .5rem; bottom: 2rem;
  width: 2px; background: linear-gradient(var(--accent), var(--rule-soft));
}

.stop { display: flex; gap: 1.1rem; margin: 0 0 1.7rem; position: relative; }

.stop-when {
  flex: 0 0 5.4rem; text-align: right; padding-top: .15rem;
  display: flex; flex-direction: column; align-items: flex-end; gap: .1rem;
}
.stop-era {
  font-family: var(--mono); font-size: .74rem; color: var(--accent);
  border: 1px solid var(--accent); border-radius: 4px;
  padding: .05rem .34rem; background: var(--paper);
  position: relative; z-index: 1;
}
.stop-date {
  font-size: .68rem; color: var(--ink-faint);
  font-variant-numeric: tabular-nums; max-width: 5.2rem;
}

.stop-card { flex: 1; min-width: 0; padding-left: .9rem; }
.stop-ref {
  display: inline-block; font-size: .78rem; font-weight: 600;
  text-decoration: none; margin-bottom: .5rem;
  text-transform: uppercase; letter-spacing: .04em;
}
.stop-text {
  font-family: var(--serif); font-size: 1.03rem; line-height: 1.6;
  margin: 0 0 .6rem; padding: 0; color: var(--ink);
}
.stop-vnum {
  font-family: var(--sans); font-size: .62em; font-weight: 600;
  color: var(--accent); vertical-align: .4em; margin-right: .3em;
}
.stop-why { margin: 0; font-size: .875rem; color: var(--ink-soft); }
.stop-aside {
  margin: .6rem 0 0; font-size: .78rem; color: var(--warn);
  background: var(--warn-bg); border-radius: 6px; padding: .5rem .65rem;
}

@media (max-width: 620px) {
  .thread::before { left: 2.2rem; }
  .stop { gap: .7rem; }
  .stop-when { flex-basis: 3.6rem; }
  .stop-date { font-size: .62rem; max-width: 3.6rem; }
  .stop-card { padding-left: .5rem; }
}

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

/* Everything on a reading page is the same column: the leaf sets the
   width and the head, the controls and the pager line up with it, so the
   page reads as one object rather than as a wide header with a page
   floating somewhere under it. */
.reader-head, .pager, .witnesses {
  max-width: var(--leaf); margin-left: auto; margin-right: auto;
}
.reader-head {
  border-bottom: 1px solid var(--rule);
  padding-bottom: 1rem; margin-bottom: 1.4rem;
}
.crumbs { font-size: .8rem; color: var(--ink-faint); margin-bottom: .35rem; }
.crumbs a { color: var(--ink-faint); }

.chapter-strip {
  display: flex; gap: .28rem; flex-wrap: wrap; margin: 1rem 0 0;
  max-height: 8.2rem; overflow-y: auto; padding: .15rem;
}
.chapter-strip a {
  min-width: 2.1rem; text-align: center; padding: .16rem .38rem;
  border: 1px solid var(--rule-soft); border-radius: 6px;
  font-size: .8rem; text-decoration: none; color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}
.chapter-strip a:hover { border-color: var(--accent); color: var(--accent); }
.chapter-strip a[aria-current="true"] { background: var(--accent); color: #fff; border-color: var(--accent); }

/* The text is set on a leaf rather than on the page's own ground: a
   brighter surface, a hairline, and a gutter shadow down the bound edge.
   That is the mark of this volume drawn at full size -- a spine and the
   leaves hanging off it -- and it is what tells the eye where the book
   stops and the apparatus around it starts.

   The measure is unchanged. The leaf is the measure plus its margins,
   which is why every control above it is sized from the same token. */
.reader {
  position: relative;
  font-family: var(--serif);
  font-size: var(--reader-size);
  line-height: 1.75;
  max-width: var(--leaf);
  margin: 0 auto;
  padding: clamp(1.3rem, 4vw, 2.5rem) clamp(1rem, 4vw, 2.5rem);
  background: var(--raised);
  border: 1px solid var(--rule-soft);
  border-radius: 2px var(--radius) var(--radius) 2px;
  /* Two leaves under this one, drawn as offset hairlines rather than as
     an image, so the chapter reads as a page in a book with more of the
     book behind it. */
  box-shadow:
    3px 3px 0 -1px var(--raised), 3px 3px 0 0 var(--rule-soft),
    6px 6px 0 -1px var(--raised), 6px 6px 0 0 var(--rule-soft),
    var(--shadow);
  hanging-punctuation: first;
  text-wrap: pretty;
  margin-top: .9rem;
}
.reader::before {
  content: "";
  position: absolute; left: 0; top: 0; bottom: 0; width: 9px;
  border-radius: 2px 0 0 2px;
  background: linear-gradient(90deg, var(--spine), transparent);
  pointer-events: none;
}
/* Set out this way the verse is a line, and a line's number belongs in
   the margin beside it rather than in front of it. */
.reader.verse-per-line .v {
  display: block; margin: 0 0 .5rem;
  padding-left: 2.1rem; text-indent: -2.1rem;
}
.reader.verse-per-line .vnum {
  display: inline-block; min-width: 1.7rem; text-align: right;
  margin-right: .4rem; vertical-align: baseline; font-size: .74em;
}
.reader .v { transition: background-color .25s; }
.reader .v.target { background: var(--mark); border-radius: 3px; }
.reader p { margin: 0 0 1.05rem; }

/* The verse number is a button now, but must still read as a superscript
   numeral inside flowing text rather than as a control. */
.vnum {
  font-family: var(--sans); font-size: .66em; font-weight: 700;
  color: var(--rubric); vertical-align: .38em;
  margin-right: .24em; font-variant-numeric: tabular-nums lining-nums;
  background: none; border: 0; padding: 0 .1em; cursor: pointer;
  line-height: 1;
}
.vnum:hover { color: var(--rubric-2); text-decoration: underline; }
/* Opened, it is a control rather than a numeral, so it changes colour
   as well as ground: purple is the site talking. */
.vnum[aria-expanded="true"] {
  background: var(--accent); color: #fff; border-radius: 3px;
}

/* A saved verse keeps a quiet marker in the margin of the text. */
.v.is-saved {
  background: linear-gradient(transparent 60%, var(--mark) 60%);
  border-radius: 2px;
}

.vmenu {
  position: absolute; z-index: 50;
  margin-top: .3rem;
  display: flex; flex-direction: column;
  background: var(--raised); border: 1px solid var(--rule);
  border-radius: var(--radius); box-shadow: var(--shadow);
  min-width: 15rem; padding: .25rem;
  font-family: var(--sans);
}
.vmenu button {
  font: inherit; font-size: .85rem; text-align: left;
  background: transparent; border: 0; border-radius: 6px;
  padding: .5rem .6rem; cursor: pointer; color: var(--ink);
}
.vmenu button:hover { background: var(--paper-2); }

.v { position: relative; }

/* ---------- saved ---------- */

.saved-row {
  border-bottom: 1px solid var(--rule-soft);
  padding: 1rem 0;
  display: flex; flex-direction: column; align-items: flex-start; gap: .5rem;
}
.saved-text {
  font-family: var(--serif); font-size: 1rem; line-height: 1.62;
  margin: 0; padding-left: .9rem;
  border-left: 3px solid var(--accent-bg);
  color: var(--ink);
}
.saved-note {
  font: inherit; font-size: .87rem; width: 100%;
  background: var(--paper-2); color: var(--ink);
  border: 1px solid var(--rule-soft); border-radius: 8px;
  padding: .45rem .6rem; resize: vertical;
}
.saved-note::placeholder { color: var(--ink-faint); }

.pager {
  display: flex; justify-content: space-between; gap: 1rem;
  margin: 2.6rem auto 0; max-width: var(--measure); align-items: center;
}
.pager a {
  text-decoration: none; font-size: .88rem; padding: .45rem .8rem;
  border: 1px solid var(--rule); border-radius: 8px; color: var(--ink-soft);
  max-width: 45%;
}
.pager a:hover { border-color: var(--accent); color: var(--accent); }
.pager .spacer { flex: 1; }

.note-block {
  font-family: var(--sans); font-size: .93rem; color: var(--ink-soft);
  background: transparent; border-left: 2px solid var(--rule);
  border-radius: 0;
  padding: .2rem 0 .2rem 1.1rem; margin: 0 auto 1.8rem;
  max-width: var(--leaf);
}

.reader-controls {
  display: flex; gap: .4rem; align-items: center; justify-content: flex-end;
  flex-wrap: wrap; margin: .9rem auto 0; max-width: var(--leaf);
}
/* The chapter's own heading, in the red a scribe would have changed pens
   for, with the hairline that separates it from the leaf above. */
.chapter-title {
  margin: 0 0 1.2rem;
  color: var(--rubric);
  letter-spacing: .16em; text-transform: uppercase; font-size: .72rem;
  font-family: var(--sans); font-weight: 700;
  padding-bottom: .5rem; border-bottom: 1px solid var(--rule-soft);
}
.note-block p { margin: .4rem 0; }
.note-block p:first-child { margin-top: 0; }
.note-block p:last-child { margin-bottom: 0; }

/* ---------- who wrote this, and when ----------
   Two columns, deliberately identical in weight. Neither tradition is
   styled as the default reading; the reader compares and decides. */

.positions { margin: 0 auto 1.6rem; max-width: var(--leaf); }

.positions-head {
  width: 100%; text-align: left; cursor: pointer; font: inherit; color: inherit;
  background: transparent; border: 1px solid var(--rule); border-radius: var(--radius);
  padding: .6rem .85rem; display: flex; align-items: center; gap: .6rem;
  font-size: .9rem;
}
.positions-head:hover { background: var(--paper-2); }
.positions-head .caret { color: var(--ink-faint); font-size: .75rem; margin-left: auto; }

.gap-tag {
  font-size: .68rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .05em; padding: .1rem .45rem; border-radius: 4px;
}
.gap-tag.none   { background: var(--good-bg); color: var(--good); }
.gap-tag.narrow { background: var(--fix-bg);  color: var(--fix); }
.gap-tag.wide   { background: var(--warn-bg); color: var(--warn); }

.positions-body {
  display: none; flex-direction: column; gap: .7rem; margin-top: .6rem;
}
.positions.open .positions-body { display: flex; }

/* The two views sit side by side where there is room and stack where there
   is not; the date card above them always runs the full width, because the
   whole point of it is the distance between the two. */
.stances {
  display: grid; gap: .7rem;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}

/* ---------- the date card ----------
   Two spans on one scale. Reading it should take about a second: if the bars
   overlap the positions agree about the date, and if they do not, the gap on
   the page is the gap in the scholarship. */
.datecard {
  background: var(--raised); border: 1px solid var(--rule-soft);
  border-radius: var(--radius); padding: .8rem .9rem;
}

.datescale { display: flex; flex-direction: column; gap: .45rem; }

.daterow { display: grid; align-items: center; gap: .5rem;
           grid-template-columns: 5.5rem 1fr 8.5rem; }

.datelabel {
  font-family: var(--sans); font-size: .68rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em; color: var(--ink-faint);
}

.datetrack {
  position: relative; height: 1.15rem; border-radius: 3px;
  background: var(--paper-2); overflow: hidden;
}

.datebar {
  position: absolute; top: 0; bottom: 0; border-radius: 3px; min-width: 3px;
}
.daterow.trad .datebar { background: var(--warn); }
.daterow.crit .datebar { background: var(--fix); }

/* A span read from a century or a named period is a looser claim than one
   read from a year, and is drawn as one rather than pretending to an
   exactness the position never had. */
.datebar.century,
.datebar.period,
.datebar.decade { opacity: .62; }
.datebar.period {
  background-image: repeating-linear-gradient(
    45deg, transparent 0 4px, rgba(255, 255, 255, .35) 4px 8px);
}

.dateunknown {
  position: absolute; inset: 0; display: flex; align-items: center;
  padding-left: .4rem; font-size: .7rem; color: var(--ink-faint);
  font-style: italic;
}

.datespan {
  font-family: var(--sans); font-size: .74rem; color: var(--ink-soft);
  text-align: right; font-variant-numeric: tabular-nums;
}

.dateverdict {
  margin: .6rem 0 0; font-size: .84rem; color: var(--ink-soft);
}

.datecite {
  margin: .45rem 0 0; padding-top: .45rem;
  border-top: 1px solid var(--rule-soft);
  font-size: .74rem; color: var(--ink-faint);
}
.datecite a { color: inherit; }

/* On a phone the three-column row has nowhere to go, so the figure moves
   under the bar rather than squeezing it to nothing. */
@media (max-width: 30rem) {
  .daterow { grid-template-columns: 5rem 1fr; row-gap: .15rem; }
  .datespan { grid-column: 2; text-align: left; }
}

.stance {
  background: var(--raised); border: 1px solid var(--rule-soft);
  border-radius: var(--radius); padding: .8rem .9rem;
}
.positions-h { margin: 0; font-size: inherit; font-weight: inherit; }

.stance h3 {
  margin: 0 0 .3rem; font-family: var(--sans); font-size: .7rem;
  text-transform: uppercase; letter-spacing: .06em; color: var(--ink-faint);
  font-weight: 700;
}
.stance .claim { font-family: var(--serif); font-size: 1rem; margin: 0 0 .4rem; }
.stance .why { font-size: .84rem; color: var(--ink-soft); margin: 0 0 .5rem; }

/* The citation is the point of the panel: it is what makes an editorial
   claim checkable rather than merely asserted. */
.stance .cite {
  font-size: .76rem; color: var(--ink-faint); margin: 0;
  padding-top: .45rem; border-top: 1px solid var(--rule-soft);
  font-style: italic;
}

.positions-foot {
  font-size: .78rem; color: var(--ink-faint); margin: 0;
}

/* ---------- lexicon panel ----------
   A sheet rather than a tooltip: entries run long and carry links, which a
   hover bubble cannot hold. Side panel on desktop, bottom sheet on a phone,
   where thumbs reach the bottom of the screen and not the right edge. */

.lex {
  position: fixed; z-index: 60;
  background: var(--raised);
  border: 1px solid var(--rule);
  box-shadow: var(--shadow);
  display: flex; flex-direction: column;
  right: 1rem; bottom: 1rem; top: auto;
  width: min(24rem, calc(100vw - 2rem));
  max-height: min(28rem, 70vh);
  border-radius: var(--radius);
  animation: lex-in .16s ease-out;
}

@keyframes lex-in { from { opacity: 0; transform: translateY(.4rem); } }
@media (prefers-reduced-motion: reduce) { .lex { animation: none; } }

.lex-head {
  display: flex; align-items: baseline; gap: .6rem;
  padding: .7rem .9rem .5rem;
  border-bottom: 1px solid var(--rule-soft);
}
.lex-head h2 {
  font-family: var(--serif); font-size: 1.06rem; flex: 1; margin: 0;
}
.lex-close {
  background: transparent; border: 0; cursor: pointer;
  color: var(--ink-faint); font-size: 1rem; padding: .1rem .3rem;
  line-height: 1;
}
.lex-close:hover { color: var(--ink); }

.lex-body { overflow-y: auto; padding: .8rem .9rem 1rem; }
.lex-text { margin: 0 0 .7rem; font-size: .92rem; line-height: 1.6; }
.lex-none { margin: 0; font-size: .9rem; color: var(--ink-soft); }

.lex-flag {
  margin: 0 0 .7rem; font-size: .8rem;
  padding: .5rem .65rem; border-radius: 6px;
  background: var(--warn-bg); color: var(--warn);
  border-left: 3px solid var(--warn);
}
.lex-flag.measure { background: var(--fix-bg); color: var(--fix); border-color: var(--fix); }

.lex-cite {
  margin: 0 0 .8rem; font-size: .76rem; font-style: italic;
  color: var(--ink-faint);
  padding-top: .5rem; border-top: 1px solid var(--rule-soft);
}

@media (max-width: 620px) {
  .lex {
    left: 0; right: 0; bottom: 0; width: auto;
    border-radius: var(--radius) var(--radius) 0 0;
    border-left: 0; border-right: 0; border-bottom: 0;
    max-height: 62vh;
  }
}

/* A quiet hint that the text responds to a tap at all. */
.reader { cursor: text; }

.apparatus {
  font-family: var(--sans); font-size: .8rem; color: var(--ink-faint);
  border-top: 1px solid var(--rule-soft); padding-top: .8rem;
  margin: 2.4rem auto 0; max-width: var(--measure);
}
.apparatus code { font-family: var(--mono); font-size: .95em; background: var(--paper-2); padding: 0 .25em; border-radius: 3px; }

/* ---------- search ---------- */

.results { margin-top: 1.6rem; }
.result {
  border-bottom: 1px solid var(--rule-soft); padding: .85rem 0;
}
.result-ref {
  display: flex; gap: .5rem; align-items: baseline; flex-wrap: wrap;
  font-size: .8rem; margin-bottom: .2rem;
}
.result-ref a { font-weight: 600; text-decoration: none; }
.result-era { color: var(--ink-faint); }
.result-text { font-family: var(--serif); font-size: 1rem; line-height: 1.62; }
mark { background: var(--mark); color: inherit; padding: 0 .1em; border-radius: 2px; }

.progress { height: 2px; background: var(--rule-soft); border-radius: 2px; overflow: hidden; margin: 1rem 0; }
.progress i { display: block; height: 100%; background: var(--accent); width: 0; transition: width .2s; }

/* ---------- accuracy ---------- */

.finding {
  border: 1px solid var(--rule-soft); border-radius: var(--radius);
  padding: .85rem 1rem; margin: .6rem 0; background: var(--raised);
}
.finding h4 { margin: 0 0 .3rem; font-size: .98rem; }
.finding p { margin: 0; font-size: .9rem; color: var(--ink-soft); }
.badge {
  display: inline-block; font-size: .68rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em;
  padding: .12rem .45rem; border-radius: 4px; margin-right: .5rem;
  vertical-align: .1em;
}
.badge.pass      { background: var(--good-bg); color: var(--good); }
.badge.fixed     { background: var(--fix-bg);  color: var(--fix); }
.badge.corrected { background: var(--warn-bg); color: var(--warn); }
.badge.gap       { background: var(--warn-bg); color: var(--warn); }
.badge.note      { background: var(--paper-2); color: var(--ink-faint); }

.group-head { display: flex; align-items: baseline; gap: .6rem; flex-wrap: wrap; }
.group-head h2 { margin-bottom: .2rem; }

/* ---------- misc ---------- */

.loading { color: var(--ink-faint); font-size: .9rem; padding: 2rem 0; }
.empty { color: var(--ink-faint); padding: 2rem 0; font-size: .95rem; }

.chips { display: flex; gap: .35rem; flex-wrap: wrap; margin: .8rem 0; }
.chip {
  font-size: .78rem; padding: .2rem .6rem; border-radius: 999px;
  border: 1px solid var(--rule); color: var(--ink-soft);
  background: transparent; cursor: pointer; font-family: inherit;
  text-decoration: none;
}
.chip { background: var(--raised); }
.chip:hover { border-color: var(--accent); color: var(--accent); }
.chip[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: #fff; }

.foot {
  border-top: 1px solid var(--rule); padding: 1.6rem clamp(.9rem, 4vw, 2rem) 3rem;
  font-size: .84rem; color: var(--ink-soft);
}
.foot p { max-width: 52rem; margin: .4rem 0; }

.keys { margin: 1.2rem 0 0; max-width: 52rem; }
.keys summary {
  cursor: pointer; font-size: .84rem; color: var(--ink-soft);
  padding: .3rem 0;
}
.keys summary:hover { color: var(--ink); }
.keys dl {
  display: grid; grid-template-columns: auto 1fr; gap: .4rem .9rem;
  margin: .7rem 0; font-size: .84rem; align-items: baseline;
}
.keys dt { margin: 0; }
.keys dd { margin: 0; color: var(--ink-soft); }
.keys kbd {
  font-family: var(--mono); font-size: .78rem;
  background: var(--paper-2); border: 1px solid var(--rule);
  border-radius: 4px; padding: .1rem .35rem; color: var(--ink);
}

@media (max-width: 620px) {
  /* The nav has to claim lines of its own. `width: 100%` cannot make it: the
     base rule's `flex: 1` sets a basis of 0%, which beats width on a flex
     item, so the nav collapsed into whatever was left beside the brand --
     ninety pixels on a phone -- and crushed all seven links into a sliver at
     the right edge. The basis is the thing that has to change.

     Given its own width it wraps to two rows and every link is visible. A
     link behind a sideways swipe is a feature most people never find out
     about, which is too high a price for one row; the height it costs is
     given back below by tucking the whole bar away as you read. */
  .topbar { gap: .5rem .6rem; padding: .45rem .7rem; }
  .nav {
    flex: 1 0 100%; order: 3;
    gap: .12rem .15rem;
  }
  .nav a { padding: .3rem .58rem; font-size: .84rem; flex: 0 0 auto; }

  /* Reading is what the screen is for. The bar leaves as you go down the
     page and comes back the moment you turn back up, so the two rows of
     links cost nothing while you are actually reading. */
  .topbar { transition: transform .2s ease; }
  .topbar.tucked { transform: translateY(-100%); }


  /* Keep the name, drop only the strapline. A lone icon is not a wordmark. */
  .brand-sub { display: none; }
  .brand-name { font-size: 1.02rem; }
  .tools { margin-left: auto; }
  table.grid thead th { top: 5.6rem; }
}

@media print {
  .topbar, .foot, .pager, .chapter-strip, .toolbar { display: none; }
  body { background: #fff; color: #000; }
  .reader { max-width: none; }
}

/* The threads block on the home page: the argument, before the filing. */
.threads-hero { margin: 2.2rem 0 .5rem; }
.threads-hero h2 { margin: 0 0 .3rem; font-size: 1.34rem; }
.threads-hero .thread-cards { margin-top: 1rem; }
.threads-hero .thread-card h3 {
  margin: 0 0 .45rem; font-family: var(--serif); font-size: 1.1rem;
  font-weight: 600; line-height: 1.25; text-wrap: balance;
}

/* Chapter jump, for books too long to scan as a grid. */
.chapter-jump { display: flex; gap: .4rem; align-items: center; margin: .8rem 0 0; }
.chapter-jump input {
  width: 6.5rem; font: inherit; font-size: .85rem;
  background: var(--raised); color: var(--ink);
  border: 1px solid var(--rule); border-radius: 8px; padding: .32rem .55rem;
}
.chapter-jump button { cursor: pointer; }

/* Content arriving should settle rather than snap. */
main > * { animation: rise .18s ease-out; }
@keyframes rise { from { opacity: 0; transform: translateY(.25rem); } }
@media (prefers-reduced-motion: reduce) {
  main > * { animation: none; }
  .topbar { transition: none; }
}

.loading::after {
  content: ""; display: inline-block; width: .5rem; height: .5rem;
  margin-left: .4rem; border-radius: 50%;
  background: var(--accent); animation: pulse 1s ease-in-out infinite;
}
@keyframes pulse { 50% { opacity: .25; } }
@media (prefers-reduced-motion: reduce) { .loading::after { animation: none; } }

/* ---------- place, in the definition panel ----------
   Colour carries how firm the identification is, so a region never looks
   like a pin and a guess never looks like a survey point. */

.place {
  background: var(--paper-2); border-radius: var(--radius);
  padding: .75rem .85rem; margin: 0 0 .9rem;
  border-left: 3px solid var(--good);
}
.place-approximate { border-left-color: var(--warn); }
.place-region      { border-left-color: var(--fix); }
.place-within      { border-left-color: var(--ink-faint); }

.place-kind {
  display: flex; align-items: center; gap: .4rem;
  font-size: .7rem; text-transform: uppercase; letter-spacing: .06em;
  font-weight: 700; color: var(--good); margin-bottom: .4rem;
}
.place-approximate .place-kind { color: var(--warn); }
.place-region .place-kind      { color: var(--fix); }
.place-within .place-kind      { color: var(--ink-faint); }

.place-dot {
  width: .5rem; height: .5rem; border-radius: 50%;
  background: currentColor; flex: 0 0 auto;
}
.place-region .place-dot { border-radius: 2px; width: .62rem; height: .42rem; }
.place-approximate .place-dot { opacity: .55; }

.place-modern { margin: 0 0 .3rem; font-size: .9rem; font-weight: 600; }
.place-note   { margin: 0 0 .4rem; font-size: .82rem; color: var(--ink-soft); }
.place-coords {
  margin: 0 0 .6rem; font-family: var(--mono); font-size: .74rem;
  color: var(--ink-faint); font-variant-numeric: tabular-nums;
}
.place-links { display: flex; gap: .35rem; flex-wrap: wrap; }
.place-links .chip { text-decoration: none; }
.chip.primary {
  background: var(--accent); border-color: var(--accent); color: #fff;
}
.chip.primary:hover { background: var(--accent-2); border-color: var(--accent-2); color: #fff; }
.place-cite {
  margin: .6rem 0 0; font-size: .72rem; font-style: italic;
  color: var(--ink-faint);
}

/* ---------- surviving manuscripts ----------
   Links out, never reproductions: these objects are all rights reserved.
   Closed by default so it never competes with the text itself. */

.witnesses {
  margin: 0 auto 1.6rem; max-width: var(--leaf);
  border: 1px solid var(--rule); border-radius: var(--radius);
  background: var(--raised);
}
.witnesses summary {
  cursor: pointer; padding: .6rem .85rem; font-size: .88rem;
  color: var(--ink-soft); list-style-position: inside;
}
.witnesses summary:hover { color: var(--ink); }
.witnesses[open] summary {
  border-bottom: 1px solid var(--rule-soft); color: var(--ink);
}

.witness { padding: .85rem; border-bottom: 1px solid var(--rule-soft); }
.witness:last-child { border-bottom: 0; }
.witness h3 {
  margin: 0 0 .25rem; font-size: 1rem;
}
.witness h3 a { text-decoration: none; }
.witness h3 a::after { content: " ↗"; font-size: .7em; opacity: .6; }
.witness-when {
  margin: 0 0 .45rem; font-size: .74rem; color: var(--ink-faint);
  text-transform: uppercase; letter-spacing: .04em;
}
.witness-holds { margin: 0 0 .4rem; font-size: .88rem; }
.witness-why   { margin: 0 0 .5rem; font-size: .85rem; color: var(--ink-soft); }
.witness-rights {
  margin: 0; font-size: .72rem; font-style: italic; color: var(--ink-faint);
}

/* ---------- read aloud ----------
   The passage being spoken is marked twice: the whole verse takes a quiet
   ground so you can find your place after looking away, and the individual
   word takes the highlighter, so following along is possible at speed.
   Word marking uses the Custom Highlight API — where it is missing the
   verse marking alone still carries the position. */

.chapter-title.is-speaking,
.reader .v.is-speaking,
.reader p.is-speaking {
  background: var(--accent-bg);
  border-radius: 3px;
  box-shadow: 0 0 0 .18em var(--accent-bg);
}

::highlight(book-speaking) {
  background: var(--mark);
  color: var(--ink);
}

/* Said out loud where the button is, not only to the live region. */
.listen-note {
  max-width: var(--leaf);
  margin: .5rem auto 0;
  font-family: var(--sans); font-size: .82rem; line-height: 1.5;
  color: var(--warn); background: var(--warn-bg);
  border-radius: var(--radius); padding: .55rem .75rem;
}

.chip[disabled] { opacity: .55; cursor: default; }
.chip[disabled]:hover { border-color: var(--rule); color: var(--ink-soft); }

.player {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  isolation: isolate;
  background: var(--raised); border-top: 1px solid var(--rule);
  box-shadow: var(--shadow);
  font-family: var(--sans);
  padding: .5rem max(.8rem, env(safe-area-inset-left))
           calc(.5rem + env(safe-area-inset-bottom))
           max(.8rem, env(safe-area-inset-right));
  display: flex; flex-direction: column; gap: .4rem;
}
.player[hidden] { display: none; }

.player-line { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }

.player-btn {
  font: inherit; font-size: .95rem; line-height: 1;
  background: transparent; color: var(--ink);
  border: 1px solid var(--rule); border-radius: 999px;
  width: 2.2rem; height: 2.2rem; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  flex: none;
}
.player-btn:hover { border-color: var(--accent); color: var(--accent); }
/* The accent is a deep purple in light and a pale one in dark, so the glyph
   takes the ground colour rather than a fixed white and stays legible in both. */
.player-bar i { background: var(--rubric); }
.player-play {
  background: var(--accent); border-color: var(--accent); color: var(--paper);
  width: 2.6rem; height: 2.6rem; font-size: 1.05rem;
}
.player-play:hover {
  background: var(--accent-2); border-color: var(--accent-2); color: var(--paper);
}
.player-cont[aria-pressed="true"] { background: var(--accent-bg); border-color: var(--accent); color: var(--accent); }

.player-pos {
  display: flex; flex-direction: column; min-width: 0; line-height: 1.25;
  flex: 1;
}
.player-where {
  font-size: .84rem; font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.player-unit { font-size: .74rem; color: var(--ink-faint); }

/* How far through the chapter, as a hairline along the top edge — the same
   place a player puts it, and out of the way of the controls. */
.player-bar {
  position: absolute; top: 0; left: 0; right: 0; height: 2px;
  background: var(--rule-soft); overflow: hidden;
}
.player-bar i {
  display: block; height: 100%; width: 0;
  background: var(--accent); transition: width .3s linear;
}
@media (prefers-reduced-motion: reduce) { .player-bar i { transition: none; } }

.player-opts select {
  font: inherit; font-size: .78rem; color: var(--ink);
  background: var(--paper-2); border: 1px solid var(--rule-soft);
  border-radius: 8px; padding: .28rem .4rem; max-width: 11rem;
}
.player-opts { justify-content: flex-start; }
.player-close { margin-left: auto; }

/* The voice drawer is grouped by how the voices sound; the headings carry
   that, so they have to read as headings and not as choices. */
.player-opts optgroup { font-style: normal; font-weight: 600; }
.player-opts option { font-weight: 400; }

/* Try-this-voice sits with the drawer it belongs to, and smaller than the
   transport: it is a convenience, not a control. */
.player-try { width: 2rem; height: 2rem; font-size: .85rem; }

/* Only shown when the device has nothing good installed, which is a fact
   about the device and not a failure of the page. It opens rather than
   hovering: the phone that most needs it has no tooltips. */
.player-hint {
  margin: 0; font-size: .72rem; line-height: 1.45; color: var(--ink-faint);
  max-width: 42rem;
}
.player-hint[hidden] { display: none; }
.player-hint > summary { cursor: pointer; }
.player-hint > summary:hover { color: var(--ink); }
.player-hint > p { margin: .4rem 0 0; }
.player-hint > p strong { color: var(--ink-soft); font-weight: 600; }
/* Opened, it is a paragraph or five, and the player is already at the
   bottom of the screen. */
.player-hint[open] { max-height: 40vh; overflow-y: auto; }

/* The player covers the last inch of the page; the reader gets that back.
   Measured rather than assumed, because the player is a different height
   with the hint up, and on a narrow phone where the options wrap. */
body.listening { padding-bottom: calc(var(--player-h, 7.5rem) + 1rem); }

@media (max-width: 620px) {
  .player-opts select { max-width: 7.5rem; }
  .player-where { font-size: .8rem; }
}

@media print { .player { display: none; } }


/* ---------- the timeline ----------
   Every work as a bar on one axis. The length of a bar is the length of the
   claim behind it, which is the thing a list of dates cannot show. */

.tl-axis {
  position: relative; height: 1.4rem; margin: .3rem 0 .2rem;
  border-bottom: 1px solid var(--rule);
}

.tl-tick {
  position: absolute; bottom: .15rem; transform: translateX(-50%);
  font-family: var(--sans); font-size: .66rem; color: var(--ink-faint);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.tl-tick::after {
  content: ""; position: absolute; left: 50%; bottom: -.35rem;
  width: 1px; height: .3rem; background: var(--rule);
}

.tl-rows { display: flex; flex-direction: column; }

.tl-row {
  display: grid; align-items: center; gap: .5rem; padding: .12rem .25rem;
  grid-template-columns: 13rem 1fr 8rem;
  color: inherit; text-decoration: none; border-radius: 4px;
}
.tl-row:hover, .tl-row:focus-visible { background: var(--paper-2); }

.tl-name {
  font-size: .78rem; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis;
}

.tl-track {
  position: relative; height: .62rem; border-radius: 2px;
  background: var(--rule-soft);
}

.tl-bar {
  position: absolute; top: 0; bottom: 0; border-radius: 2px;
  background: var(--accent); min-width: 2px;
}

/* A span read from a century or a period commits to less than one read from
   a year, and a work placed by its era commits to less still. Both are drawn
   as the looser claims they are rather than being levelled up. */
.tl-bar.century, .tl-bar.period, .tl-bar.decade { opacity: .7; }
.tl-row.placed-section .tl-bar { background: var(--ink-faint); opacity: .45; }

/* An open end runs off the edge instead of stopping at a year nobody stated. */
.tl-bar.open-before {
  border-top-left-radius: 0; border-bottom-left-radius: 0;
  -webkit-mask-image: linear-gradient(to right, transparent, #000 3rem);
  mask-image: linear-gradient(to right, transparent, #000 3rem);
}
.tl-bar.open-after {
  border-top-right-radius: 0; border-bottom-right-radius: 0;
  -webkit-mask-image: linear-gradient(to left, transparent, #000 3rem);
  mask-image: linear-gradient(to left, transparent, #000 3rem);
}

.tl-when {
  font-family: var(--sans); font-size: .68rem; color: var(--ink-faint);
  text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums;
}

.tl-note {
  margin: .9rem 0 0; padding-top: .6rem; border-top: 1px solid var(--rule-soft);
  font-size: .8rem; color: var(--ink-soft);
}
.tl-note a { color: inherit; }

.tl-undated { margin-top: .8rem; font-size: .82rem; }
.tl-undated summary { cursor: pointer; color: var(--ink-soft); }
.tl-undated-list { display: flex; flex-wrap: wrap; gap: .3rem; margin-top: .5rem; }

/* On a phone the title needs the width more than the figure does, so the
   figure goes under the bar. */
@media (max-width: 40rem) {
  .tl-row { grid-template-columns: 8.5rem 1fr; row-gap: .1rem; }
  .tl-when { grid-column: 2; text-align: left; font-size: .64rem; }
  .tl-name { font-size: .72rem; }
}

/* ---------- the chapter map ----------
   Land, water, and the places the chapter names. The canvas is the picture;
   the list under it is the content, and is what a keyboard and a screen
   reader use. Both are always present. */

.chapter-map {
  margin: 1.4rem 0 .4rem;
  border-top: 1px solid var(--rule-soft);
  padding-top: .7rem;
}

.chapter-map > summary {
  cursor: pointer;
  font-family: var(--sans);
  font-size: .82rem;
  color: var(--ink-soft);
}
.chapter-map > summary:hover { color: var(--ink); }

.map-body { margin-top: .7rem; }

/* --map-aspect is set from the frame being drawn. Capping the height and
   then deriving the width from it is what keeps the box the shape of the
   map, rather than a wide letterbox with the map adrift in the middle. */
.map-stage {
  position: relative;
  border: 1px solid var(--rule);
  border-radius: 6px;
  overflow: hidden;
  background: var(--paper);
  --map-aspect: 1.2;
  --map-height: 26rem;
  aspect-ratio: var(--map-aspect);
  max-height: var(--map-height);
  max-width: calc(var(--map-height) * var(--map-aspect));
  width: 100%;
  margin: 0 auto;
}

.map-canvas {
  display: block;
  width: 100%;
  height: 100%;
  touch-action: none;   /* the canvas handles its own drag */
  cursor: grab;
}
.map-canvas:active { cursor: grabbing; }

@media (max-width: 40rem) {
  .map-stage { --map-height: 17rem; }
}

.map-tools {
  display: flex;
  gap: .4rem;
  margin: .5rem 0 .2rem;
}

.map-caption {
  font-size: .76rem;
  color: var(--ink-faint);
  line-height: 1.5;
  margin: .5rem 0 .7rem;
}

.map-detail { margin: .7rem 0; }
.map-detail-name {
  font-family: var(--sans);
  font-size: .9rem;
  margin: 0 0 .3rem;
}

.map-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: .3rem;
}

.map-place {
  display: inline-flex;
  align-items: baseline;
  gap: .35rem;
  font-family: var(--sans);
  font-size: .74rem;
  padding: .2rem .5rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--raised);
  color: var(--ink);
  cursor: pointer;
}
.map-place:hover, .map-place:focus-visible {
  border-color: var(--accent);
  color: var(--accent);
}

/* The same three grades the canvas draws, so the list is not a lesser copy:
   solid for identified, dashed for approximate, faint for a region. */
.map-place::before {
  content: "";
  width: .5rem; height: .5rem;
  border-radius: 50%;
  background: var(--accent);
  flex: none;
}
.map-place.map-approximate::before {
  background: transparent;
  border: 1px dashed var(--accent);
}
.map-place.map-region::before {
  background: var(--accent);
  opacity: .3;
}
.map-place.map-within::before {
  background: var(--accent);
  opacity: .6;
}

.map-place-kind, .map-place-first {
  /* Named for the screen reader, not shown: the dot carries it for the eye. */
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* The list's copy of the canvas's dotted outer ring. A ring rather than a
   fill, so it reads as something added around the grade rather than as a
   fourth grade of its own -- the place is still whatever it was. */
.map-place.map-first {
  box-shadow: 0 0 0 1px var(--accent);
}

/* ---- what a place is named beside ---- */

.map-kin { margin-top: .9rem; }
.map-kin h4 {
  font-family: var(--sans);
  font-size: .72rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0 0 .4rem;
}
.map-kin-list {
  list-style: none;
  margin: 0; padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: .3rem;
}
.map-kin-list li { display: flex; }
.map-kin-here, .map-kin-name {
  font-family: var(--sans);
  font-size: .74rem;
  padding: .2rem .5rem;
  border-radius: 999px;
  border: 1px solid var(--rule);
  background: var(--raised);
  color: var(--ink);
}
/* Only the ones already on this canvas are buttons; the rest are named but
   not offered, because there is nothing here to point at. */
.map-kin-here { cursor: pointer; }
.map-kin-here:hover, .map-kin-here:focus-visible {
  border-color: var(--accent);
  color: var(--accent);
}
.map-kin-name {
  border-style: dashed;
  color: var(--ink-faint);
  text-transform: capitalize;
}
.map-kin-count { color: var(--ink-faint); }
.map-kin-note, .map-kin-none, .map-arrival {
  font-size: .76rem;
  line-height: 1.5;
  color: var(--ink-faint);
  margin: .5rem 0 0;
}
.map-arrival a { color: var(--accent); }
.map-arrival-note { color: var(--ink-faint); }
