/* ═══════════════════════════════════════════════════════════════
   差分宇宙 · Divergent Universe tab
   ------------------------------------------------------------
   A reading room: standing index on the left, one entry open on
   the right. Materiality is carved stone, deliberately unlike the
   parchment of the Books tab; the accent is terracotta (Nikador =
   blood and war) rather than the archive's usual gold.

   Three themes get their own token block; every rule below the
   token blocks is shared.
   ═══════════════════════════════════════════════════════════════ */

:root[data-theme="light"] {
  --dv-stone-top:  #d8d2c6;
  --dv-stone-bot:  #cbc4b6;
  --dv-stone-edge: rgba(46, 38, 30, 0.22);
  --dv-ink:        #241f1a;
  --dv-ink-soft:   #5c554a;
  --dv-ink-faint:  #857d6f;
  --dv-rule:       rgba(46, 38, 30, 0.14);
  --dv-rule-firm:  rgba(46, 38, 30, 0.20);
  --dv-accent:     #a64737;
  --dv-accent-dim: rgba(166, 71, 55, 0.30);
  --dv-accent-wash:rgba(166, 71, 55, 0.07);
  --dv-carve-lo:   rgba(255, 255, 255, 0.55);
  --dv-carve-hi:   rgba(46, 38, 30, 0.10);
  --dv-wash:       rgba(46, 38, 30, 0.028);
  --dv-grain-a:    rgba(120, 80, 30, 0.030);
  --dv-grain-b:    rgba(120, 80, 30, 0.018);
}
:root[data-theme="sepia"] {
  --dv-stone-top:  #ded2b8;
  --dv-stone-bot:  #d2c5a8;
  --dv-stone-edge: rgba(74, 54, 30, 0.24);
  --dv-ink:        #2c2216;
  --dv-ink-soft:   #5f5138;
  --dv-ink-faint:  #8a7c60;
  --dv-rule:       rgba(74, 54, 30, 0.16);
  --dv-rule-firm:  rgba(74, 54, 30, 0.24);
  --dv-accent:     #a34b2c;
  --dv-accent-dim: rgba(163, 75, 44, 0.32);
  --dv-accent-wash:rgba(163, 75, 44, 0.07);
  --dv-carve-lo:   rgba(255, 250, 232, 0.50);
  --dv-carve-hi:   rgba(74, 54, 30, 0.11);
  --dv-wash:       rgba(74, 54, 30, 0.030);
  --dv-grain-a:    rgba(80, 44, 14, 0.035);
  --dv-grain-b:    rgba(80, 44, 14, 0.022);
}
:root[data-theme="dark"] {
  --dv-stone-top:  #23211f;
  --dv-stone-bot:  #1b1917;
  --dv-stone-edge: rgba(0, 0, 0, 0.55);
  --dv-ink:        #ded6c9;
  --dv-ink-soft:   #a49b8c;
  --dv-ink-faint:  #7b7264;
  --dv-rule:       rgba(222, 214, 201, 0.13);
  --dv-rule-firm:  rgba(222, 214, 201, 0.22);
  --dv-accent:     #c26a4e;
  --dv-accent-dim: rgba(194, 106, 78, 0.35);
  --dv-accent-wash:rgba(194, 106, 78, 0.09);
  --dv-carve-lo:   rgba(255, 255, 255, 0.045);
  --dv-carve-hi:   rgba(0, 0, 0, 0.40);
  --dv-wash:       rgba(10, 8, 6, 0.62);
  --dv-grain-a:    rgba(220, 180, 120, 0.030);
  --dv-grain-b:    rgba(220, 180, 120, 0.018);
}

.dv-wrap { max-width: 1120px; margin: 0 auto; padding-bottom: 3rem; }

/* ── The room ────────────────────────────────────────────────── */
.dv-room {
  display: grid;
  grid-template-columns: 274px minmax(0, 1fr);
  gap: 2.6rem;
  align-items: start;
}

/* ── Standing index ──────────────────────────────────────────── */
.dv-rail {
  display: flex; flex-direction: column; gap: 1.9rem;
  border-right: 1px solid var(--dv-rule);
  padding-right: 1.5rem;
  position: sticky; top: 1.5rem;
  max-height: calc(100vh - 3rem);
  /* `scroll`, not `auto`: the track stays drawn even when the pointer is
     idle, so the index reads as having more below the fold. */
  overflow-y: scroll;
  scrollbar-gutter: stable;
}
/* Styled through the pseudo-elements only: setting `scrollbar-width` or
   `scrollbar-color` makes Chromium ignore them and collapse the track to
   a 1px overlay, which is the opposite of the point here. Firefox falls
   back to its own always-drawn bar, which `overflow-y: scroll` guarantees. */
.dv-rail::-webkit-scrollbar { width: 6px; }
.dv-rail::-webkit-scrollbar-track { background: var(--dv-rule); }
.dv-rail::-webkit-scrollbar-thumb { background: var(--dv-accent-dim); }
.dv-rail:hover::-webkit-scrollbar-thumb { background: var(--dv-accent); }
.dv-rail-head {
  font-family: var(--font-body); font-weight: 400;
  font-size: var(--fs-meta); letter-spacing: .14em; color: var(--dv-accent);
  margin: 0 0 .6rem;
}
.dv-rail-list { display: flex; flex-direction: column; }
.dv-rail-split { height: 1px; background: var(--dv-rule); margin: .55rem .75rem; }

.dv-rail-btn {
  display: flex; align-items: baseline; gap: .7rem;
  font-family: var(--font-body); background: none; cursor: pointer; text-align: left;
  border: 0; border-left: 2px solid transparent;
  padding: .5rem .75rem;
  transition: var(--transition);
}
.dv-rail-btn:hover { background: var(--dv-accent-wash); }
.dv-rail-btn.on { border-left-color: var(--dv-accent); background: var(--dv-accent-wash); }
.dv-rail-mark {
  flex: none; min-width: 2.6em;
  font-size: var(--fs-micro); letter-spacing: .08em; color: var(--dv-ink-faint);
}
/* Curio art sits in the same slot the level marks use, so both columns
   of the rail keep one left edge. */
.dv-rail-icon {
  /* Same em base as .dv-rail-mark so both slots measure 2.6em alike. */
  flex: none; width: 2.6em; font-size: var(--fs-micro); align-self: flex-start;
  display: grid; place-items: center;
}
.dv-rail-icon img { width: 26px; height: 26px; object-fit: contain; }
.dv-rail-btn.on .dv-rail-mark { color: var(--dv-accent); }
.dv-rail-text { display: flex; flex-direction: column; gap: .15rem; min-width: 0; }
.dv-rail-zh { font-size: var(--fs-small); color: var(--dv-ink-soft); letter-spacing: .03em; }
.dv-rail-btn.on .dv-rail-zh { color: var(--dv-ink); }
.dv-rail-en { font-size: var(--fs-micro); color: var(--dv-ink-faint); letter-spacing: .04em; }

/* ── Reader ──────────────────────────────────────────────────── */
.dv-reader { display: flex; flex-direction: column; min-width: 0; }
.dv-reader-head {
  display: flex; align-items: baseline; gap: 1rem; flex-wrap: wrap;
  padding-bottom: 1rem; border-bottom: 1px solid var(--dv-rule-firm);
}
.dv-reader-title { display: flex; align-items: baseline; gap: 1rem; flex-wrap: wrap; min-width: 0; }
.dv-reader-title h3 {
  font-family: var(--font-heading); font-weight: var(--font-weight-heading);
  font-size: var(--fs-h3); letter-spacing: .1em; color: var(--dv-ink);
}
.dv-reader-en { font-size: var(--fs-meta); letter-spacing: .08em; color: var(--dv-ink-faint); }
.dv-reader-meta {
  margin-left: auto; flex: none;
  font-size: var(--fs-micro); letter-spacing: .16em; color: var(--dv-accent);
}

/* ── The plate ───────────────────────────────────────────────── */
.dv-stele {
  position: relative;
  margin-top: 2.1rem; padding: 2.6rem 3.2rem 2.4rem;
  /* Two hairline weaves over the stone: the same trick the reading room
     uses on its paper, at a finer pitch. No image, no blend mode. */
  background:
    repeating-linear-gradient(0deg,  var(--dv-grain-a) 0 1px, transparent 1px 3px),
    repeating-linear-gradient(90deg, var(--dv-grain-b) 0 1px, transparent 1px 4px),
    linear-gradient(175deg, var(--dv-stone-top), var(--dv-stone-bot));
  border: 1px solid var(--dv-stone-edge);
  box-shadow: inset 0 1px 0 var(--dv-carve-lo), 0 1px 3px var(--dv-carve-hi);
}
/* Four corner brackets rather than a closed rule — how a plate is
   actually held down, and it stops the frame reading as a box. */
.dv-stele::before {
  content: ''; position: absolute; inset: 11px; pointer-events: none;
  --b: var(--dv-stone-edge);
  --arm: 15px;
  background:
    linear-gradient(var(--b), var(--b)) left  top    / var(--arm) 1px no-repeat,
    linear-gradient(var(--b), var(--b)) left  top    / 1px var(--arm) no-repeat,
    linear-gradient(var(--b), var(--b)) right top    / var(--arm) 1px no-repeat,
    linear-gradient(var(--b), var(--b)) right top    / 1px var(--arm) no-repeat,
    linear-gradient(var(--b), var(--b)) left  bottom / var(--arm) 1px no-repeat,
    linear-gradient(var(--b), var(--b)) left  bottom / 1px var(--arm) no-repeat,
    linear-gradient(var(--b), var(--b)) right bottom / var(--arm) 1px no-repeat,
    linear-gradient(var(--b), var(--b)) right bottom / 1px var(--arm) no-repeat;
}
/* Head mark, then the narrator; closing mark after the last line. */
.dv-ornament {
  display: flex; align-items: center; justify-content: center; gap: 1rem;
  color: var(--dv-accent); opacity: .75; margin-bottom: 1.9rem;
}
.dv-ornament > span {
  flex: 1; height: 1px; max-width: 120px;
  background: linear-gradient(90deg, transparent, var(--dv-accent-dim));
}
.dv-ornament > span:last-child { background: linear-gradient(90deg, var(--dv-accent-dim), transparent); }
.dv-closer {
  display: flex; align-items: center; justify-content: center; gap: .8rem;
  margin-top: 2.4rem;
}
.dv-closer > span { width: 26px; height: 1px; background: var(--dv-accent-dim); }


/* odes */
.dv-line {
  /* A long line is workable at this leading — 2.05 is what keeps the
     return sweep from slipping a row. Shorten the leading and the
     measure has to come down with it. */
  font-size: var(--fs-secondary); line-height: 2.05; color: var(--dv-ink);
  margin-bottom: 1.75em; text-align: justify;
}
.dv-line:last-child { margin-bottom: 0; }

/* Replies are a pause, not a dialogue turn: stacked flush left, each
   behind its own rule. */
.dv-choice {
  display: flex; flex-direction: column; align-items: flex-start; gap: .7rem;
  margin: 2.6rem 0;
}
.dv-choice-opt {
  border-left: 1px solid var(--dv-accent-dim);
  padding-left: .85rem;
  font-size: var(--fs-meta); line-height: 1.7; letter-spacing: .04em;
  color: var(--dv-accent);
}

/* equations — verse keeps its own line breaks */
.dv-verse {
  font-size: var(--fs-secondary); line-height: 2.05; color: var(--dv-ink);
  white-space: pre-line;
}

/* curios */
.dv-curio { display: grid; grid-template-columns: 128px minmax(0, 1fr); gap: 2.4rem; align-items: start; }
.dv-curio-fig {
  width: 128px; height: 128px; display: grid; place-items: center;
  border: 1px solid var(--dv-stone-edge);
  box-shadow: inset 0 1px 0 var(--dv-carve-lo);
}
.dv-curio-fig img { width: 100%; height: 100%; object-fit: contain; padding: 10px; }
.dv-prose { font-size: var(--fs-secondary); line-height: 1.95; color: var(--dv-ink); text-align: justify; }

/* boons */
.dv-bless-row {
  display: flex; align-items: baseline; gap: 1.6rem;
  padding: 1.4rem 0; border-bottom: 1px solid var(--dv-stone-edge);
}
.dv-bless-row:first-child { border-top: 1px solid var(--dv-stone-edge); }
/* Entries get their own column so nothing slides under the tier mark. */
.dv-bless-items { flex: 1; display: flex; flex-direction: column; gap: 1.4rem; }
.dv-bless-lv {
  flex: none; width: 3.4em; font-size: var(--fs-micro); letter-spacing: .18em;
  color: var(--dv-accent); text-transform: uppercase;
}
.dv-bless-name { font-size: var(--fs-secondary); color: var(--dv-ink); letter-spacing: .05em; }
.dv-bless-name small {
  color: var(--dv-ink-faint); font-size: var(--fs-micro); margin-left: .55em; letter-spacing: .05em;
}
.dv-bless-effect {
  margin-top: .5rem;
  font-size: var(--fs-small); line-height: 1.8; color: var(--dv-ink-soft);
}

/* What the entry does in play — set apart from the reading, below it. */
.dv-effect {
  margin-top: 2rem; padding-top: 1.4rem;
  border-top: 1px solid var(--dv-stone-edge);
}
.dv-effect-label {
  display: block; margin-bottom: .5rem;
  font-size: var(--fs-micro); letter-spacing: .16em; color: var(--dv-accent);
}
.dv-effect-text {
  font-size: var(--fs-small); line-height: 1.8; color: var(--dv-ink-soft);
}

/* ── Step through the whole section ──────────────────────────── */
.dv-step {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  margin-top: 1.4rem;
}
.dv-step-btn {
  display: flex; align-items: center; gap: .55rem;
  font-family: var(--font-body); font-size: var(--fs-meta); letter-spacing: .05em;
  background: none; border: 0; color: var(--dv-ink-faint);
  padding: .4rem 0; cursor: pointer; transition: var(--transition); text-align: left;
}
.dv-step-next { text-align: right; }
.dv-step-btn:hover { color: var(--dv-accent); }
.dv-step-arrow { color: var(--dv-accent-dim); }
.dv-step-btn:hover .dv-step-arrow { color: var(--dv-accent); }

/* ── Narrow: the stack ───────────────────────────────────────── */
/* The stack is its own tree, rendered instead of the room below 860px —
   these rules only ever meet elements that exist there. */
.dv-stack-group + .dv-stack-group { margin-top: 2.6rem; }
.dv-stack-head {
  font-family: var(--font-body); font-weight: 400;
  font-size: var(--fs-meta); letter-spacing: .16em; color: var(--dv-accent);
  padding-bottom: .7rem; margin: 0 0 .2rem;
  border-bottom: 1px solid var(--dv-rule-firm);
}

.dv-fold { border-bottom: 1px solid var(--dv-rule); }
.dv-fold-head {
  display: flex; align-items: center; gap: .8rem; width: 100%;
  font-family: var(--font-body); background: none; border: 0; cursor: pointer;
  padding: 1rem .2rem; text-align: left;
  transition: var(--transition);
}
.dv-fold.is-open .dv-fold-head { background: var(--dv-accent-wash); }
.dv-fold-icon {
  flex: none; width: 30px; height: 30px; display: grid; place-items: center;
}
.dv-fold-icon img { width: 28px; height: 28px; object-fit: contain; }
.dv-fold-mark {
  flex: none; min-width: 2.6em;
  font-size: var(--fs-micro); letter-spacing: .08em; color: var(--dv-ink-faint);
}
.dv-fold.is-open .dv-fold-mark { color: var(--dv-accent); }
.dv-fold-title {
  flex: 1; min-width: 0;
  font-size: var(--fs-body); color: var(--dv-ink); letter-spacing: .03em;
}
.dv-fold-title small {
  display: block; margin-top: .2rem;
  font-size: var(--fs-micro); color: var(--dv-ink-faint); letter-spacing: .04em;
}
.dv-fold-caret {
  flex: none; width: 8px; height: 8px;
  border-right: 1px solid var(--dv-ink-faint); border-bottom: 1px solid var(--dv-ink-faint);
  transform: rotate(45deg) translateY(-2px);
  transition: transform 180ms var(--ease);
}
.dv-fold.is-open .dv-fold-caret {
  transform: rotate(-135deg) translateY(-2px); border-color: var(--dv-accent);
}
.dv-fold-body:empty { display: none; }
.dv-fold-body { padding: .2rem 0 1.6rem; }

@media (max-width: 860px) {
  /* Fallback for the wide DOM at narrow width. divergent.mjs re-renders
     into the stacked tree when this breakpoint is crossed, so normally
     .dv-room never exists down here. If that listener ever fails to fire
     — the two layouts are different trees, not one tree restyled — the
     reader would otherwise be left with a 274px index column beside a
     ~60px column of text. Collapsing to one column and dropping the rail
     degrades that into something still readable until the next load.
     Costs nothing when the re-render works: the selectors match nothing. */
  .dv-room { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .dv-rail { display: none; }

  /* No stone fill at phone width — the filled panel read as a grey box
     at this size. A double rule frames the text instead, over a wash a
     couple of percent off the page: enough to separate the reading area,
     not enough to become a block of its own. On dark the page carries a
     flame image rather than a flat colour, so its wash is opaque enough
     to settle the text on something. */
  .dv-stele {
    padding: 1.9rem 1.45rem 2rem;
    background: var(--dv-wash);
    border-color: var(--dv-rule-firm);
    box-shadow: none;
  }
  /* Brackets shorten and lighten with the fill gone. */
  .dv-stele::before { inset: 8px; --arm: 12px; --b: var(--dv-rule-firm); }
  .dv-ornament { margin-bottom: 1.5rem; }
  .dv-ornament > span { max-width: 60px; }
  .dv-closer { margin-top: 1.9rem; }
  /* Divider rules inside the plate were drawn against the stone. */
  .dv-verse-en, .dv-prose-en { border-top-color: var(--dv-rule); }
  .dv-effect { margin-top: 1.6rem; padding-top: 1.1rem; border-top-color: var(--dv-rule); }
  .dv-effect-text { font-size: .8125rem; line-height: 1.8; }
  .dv-bless-row { border-bottom-color: var(--dv-rule); }
  .dv-bless-row:first-child { border-top-color: var(--dv-rule); }

  /* Down from 17px: at this measure 17px holds ~17 characters a line,
     which reads as choppy. 15px holds ~21 and the paragraph settles. */
  .dv-line {
    font-size: .875rem; line-height: 1.95; margin-bottom: 1.4em;
    text-align: left;   /* justify tears holes in a 20-character line */
  }
  .dv-choice { margin: 1.9rem 0; gap: .5rem; }
  .dv-choice-opt { padding-left: .7rem; }

  .dv-verse { font-size: .875rem; line-height: 1.95; }
  .dv-prose { font-size: .875rem; line-height: 1.9; text-align: left; }

  .dv-curio { grid-template-columns: 72px minmax(0, 1fr); gap: 1.1rem; }
  .dv-curio-fig { width: 72px; height: 72px; }

  .dv-bless-row { gap: 1rem; padding: 1.1rem 0; }
  .dv-bless-items { gap: 1.1rem; }
  .dv-bless-name { font-size: .875rem; }
  .dv-bless-effect { font-size: .8125rem; line-height: 1.8; margin-top: .4rem; }

  .dv-fold-head { padding: .85rem .2rem; gap: .7rem; }
  .dv-fold-title { font-size: .9375rem; }
  .dv-fold-body { padding: .2rem 0 1.3rem; }
  .dv-stack-group + .dv-stack-group { margin-top: 2.2rem; }
}
