/* ==========================================================================
   THE BOARD — the virtual tabletop, drawn in the same ink and parchment as
   the sheet. The map is SVG so it stays crisp at any zoom and so a room is a
   real hit target rather than a pixel guess.

   Two readings of the same document:
     DM      — every room drawn, unrevealed ones under a dark veil whose
               opacity is yours to set. The INK sits ABOVE the veil so the
               layout stays legible no matter how dark you make it.
     Player  — unrevealed rooms are not in the payload at all, so the void
               here is simply the stage's own dark ground. There is nothing
               beneath it to reveal.
   ========================================================================== */

.vtt {
  position: fixed;
  top: var(--cbar-h, 0px);
  left: 0; right: 0; bottom: 0;
  display: grid;
  /* the bar lives OUTSIDE .vtt now (one campaign bar); the stage is the grid */
  grid-template-rows: 1fr;
  background: var(--bg-1);
}

/* ---------- the bar ---------- */
/* The seat line inherits .cbar-sub's scribal voice — one header, one voice. */
.vtt-seat[data-seat="dm"] { color: var(--gold-deep); }
/* tools moved to the .rail (2026-08-05) */
.vtt-bar-tools {
  display: flex;
  gap: var(--s2);
  flex-wrap: wrap;
}

/* ---------- the stage ---------- */
.vtt-stage {
  position: relative;
  overflow: hidden;
  /* The void. A player's unrevealed dungeon is not a black rectangle drawn
     over the map — it is this, showing through where no room was ever sent. */
  background:
    radial-gradient(120% 100% at 50% 40%, #1b1611 0%, #100d0a 70%, #0a0806 100%);
  touch-action: none; /* we drive pan and pinch ourselves */
  cursor: grab;
}
.vtt-stage.is-panning { cursor: grabbing; }
.vtt-stage.is-dragging-token { cursor: grabbing; }
.vtt-svg { width: 100%; height: 100%; display: block; }

/* ---------- parchment floors ---------- */
.vtt-floor {
  fill: var(--panel);
  stroke: none;
}

/* ---------- the grid ---------- */
.vtt-grid-line {
  stroke: var(--rule-soft);
  stroke-width: .6;
  opacity: .5;
  fill: none;
  vector-effect: non-scaling-stroke;
}

/* ---------- walls + doors, in ink ---------- */
.vtt-wall {
  fill: none;
  stroke: var(--ink);
  stroke-width: 2.2;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.vtt-door {
  stroke: var(--ink);
  stroke-width: 3;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}
/* A secret door is only ever drawn on the DM's board — the server strips it
   from a player's payload, so this style has no player-facing counterpart. */
.vtt-door--secret {
  stroke: var(--rubric);
  stroke-dasharray: 4 3;
}

/* ---------- room numerals ---------- */
.vtt-number {
  font-family: var(--font-display);
  font-weight: 700;
  fill: var(--ink-soft);
  text-anchor: middle;
  dominant-baseline: central;
  pointer-events: none;
  user-select: none;
}

/* ---------- the veil (DM only) ---------- */
.vtt-veil {
  fill: #0d0a07;
  /* Set live from the desk slider; Tim's stated default is 80%. */
  opacity: var(--vtt-veil, .8);
  pointer-events: none;
}
/* Hover affordance so the DM can see which room a tap will reveal. */
.vtt-hit {
  fill: transparent;
  cursor: pointer;
}
.vtt-hit:hover ~ .vtt-veil,
.vtt-hit:focus-visible ~ .vtt-veil { opacity: calc(var(--vtt-veil, .8) * .55); }
.vtt-hit:focus,
.vtt-hit:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: -2px;
}

/* Lit rooms on the DM's board carry a faint gold wash so "revealed" reads at
   a glance without having to compare against the veil. */
.vtt-lit-mark {
  fill: var(--gold-hi);
  opacity: .1;
  pointer-events: none;
}

/* ---------- tokens ---------- */
.vtt-token { cursor: grab; }
.vtt-token[data-movable="0"] { cursor: default; }
.vtt-token-disc {
  stroke: var(--ink);
  stroke-width: 1.6;
  vector-effect: non-scaling-stroke;
}
.vtt-token--character .vtt-token-disc { stroke: var(--gold-deep); stroke-width: 2.2; }
.vtt-token--monster .vtt-token-disc { stroke: var(--rubric-deep); stroke-width: 2.2; }
.vtt-token-initial {
  font-family: var(--font-display);
  font-weight: 700;
  fill: var(--rubric-ink);
  text-anchor: middle;
  dominant-baseline: central;
  pointer-events: none;
  user-select: none;
}
.vtt-token-name {
  font-family: var(--font-body);
  /* font-size and stroke-width are set inline by rescaleLabels() so names keep
     a constant SCREEN size at any zoom; these are only the pre-paint fallback. */
  font-size: 12px;
  fill: var(--rubric-ink);
  paint-order: stroke;
  stroke: #0d0a07;
  stroke-width: 3;
  stroke-linejoin: round;
  text-anchor: middle;
  pointer-events: none;
  user-select: none;
}
.vtt-token-portrait-clip circle { fill: #fff; }

/* ---------- the measuring line ---------- */
.vtt-measure-line {
  stroke: var(--gold);
  stroke-width: 2;
  stroke-dasharray: 6 4;
  vector-effect: non-scaling-stroke;
  fill: none;
}
.vtt-measure-ghost {
  fill: var(--gold);
  opacity: .22;
}
.vtt-measure-readout {
  position: absolute;
  left: 50%;
  bottom: var(--s5);
  transform: translateX(-50%);
  margin: 0;
  padding: var(--s2) var(--s4);
  border-radius: 999px;
  border: 1px solid var(--rule);
  background: var(--panel);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: .95rem;
  letter-spacing: .04em;
  box-shadow: 0 6px 24px rgba(0, 0, 0, .35);
  pointer-events: none;
  z-index: 3;
}

.vtt-empty {
  font-family: var(--font-scribal);
  font-size: 1.1rem;
  /* This copy sits on .vtt-stage's void, which is a HARD-CODED dark gradient
     (#1b1611 -> #0a0806) and does not follow the theme. --rule-soft does follow
     the theme, so in candlelight it turned #4c3a20 on near-black: 1.65:1.
     --gold-hi is light in both themes, so it reads on the void either way. */
  color: var(--gold-hi);
  /* merged from the second, later-cascade definition (audit D3) */
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: var(--s4);
  margin: 0;
  padding: var(--s5);
  text-align: center;
  pointer-events: none; /* the stage still pans behind it */
}

/* ---------- the DM's desk ---------- */
.vtt-desk {
  position: absolute;
  right: var(--s4);
  bottom: var(--s4);
  width: min(300px, calc(100vw - var(--s5)));
  display: grid;
  gap: var(--s3);
  padding: var(--pad);
  z-index: 3;
  max-height: min(60vh, 520px);
  overflow-y: auto;
}
.vtt-desk-title {
  font-family: var(--label-font);
  font-size: var(--label-size);
  font-weight: var(--label-weight);
  letter-spacing: var(--label-track);
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0;
}
.vtt-desk-row { display: flex; gap: var(--s2); flex-wrap: wrap; }
.vtt-desk-toggle,
.vtt-desk-slider {
  display: grid;
  gap: var(--s1);
  font-family: var(--font-body);
  font-size: .92rem;
  color: var(--ink-soft);
}
.vtt-desk-toggle {
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: var(--s2);
  min-height: var(--field);
}
.vtt-desk-slider input { width: 100%; }
.vtt-desk-hint {
  margin: 0;
  font-family: var(--font-scribal);
  font-size: .88rem;
  color: var(--ink-faint);
  line-height: 1.45;
}

/* ---------- display mode: the shared screen ----------
   Every control gone, board edge to edge. What the table looks at. */
.vtt.is-display #vtt-bar,
.vtt.is-display .vtt-desk { display: none; }
.vtt.is-display { grid-template-rows: 1fr; }
.vtt-display-exit {
  position: absolute;
  top: var(--s3);
  right: var(--s3);
  z-index: 4;
  opacity: .25;
  transition: opacity .2s ease;
}
.vtt-display-exit:hover,
.vtt-display-exit:focus-visible { opacity: 1; }

/* ---------- phones ---------- */
@media (max-width: 640px) {



  .vtt-desk {
    right: var(--s2);
    left: var(--s2);
    bottom: var(--s2);
    width: auto;
    max-height: 45vh;
  }
  .vtt-measure-readout { bottom: calc(45vh + var(--s3)); }
}

@media (prefers-reduced-motion: reduce) {
  .vtt-display-exit { transition: none; }
}

/* ==========================================================================
   LAY A MAP — upload + calibration.
   The canvas shows the picture with our grid drawn over it, so lining the two
   up is a thing you SEE rather than a number you guess.
   ========================================================================== */
.vtt-upload-dialog .rules-inner { max-width: none; }
/* the calibration dialog is the one place bigger IS clearer (Tim, pass 7):
   twice the window, and the picture may stand taller too */
#vtt-upload-dialog{width:min(60rem,calc(100vw - 1.4rem))}
#vtt-upload-dialog .vtt-up-canvas{max-height:62vh}

.vtt-up-file {
  display: grid;
  gap: var(--s1);
  margin-block: var(--s4) var(--s3);
}
.vtt-up-file input { font-family: var(--font-body); color: var(--ink-soft); }

.vtt-up-stage {
  border: 1px solid var(--rule);
  border-radius: var(--s1);
  background: var(--bg-1);
  padding: var(--s2);
  margin-bottom: var(--s3);
}
.vtt-up-canvas {
  display: block;
  width: 100%;
  height: auto;
  max-height: 46vh;
  object-fit: contain;
  image-rendering: auto;
}
.vtt-up-meta {
  margin: var(--s2) 0 0;
  font-family: var(--label-font);
  font-size: .68rem;
  letter-spacing: var(--label-track);
  text-transform: uppercase;
  color: var(--ink-faint);
  text-align: center;
}

.vtt-up-controls {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s3);
  margin-bottom: var(--s3);
}
.vtt-up-field { display: grid; gap: var(--s1); }
.vtt-up-field--wide { grid-column: 1 / -1; }
.vtt-up-field input[type="number"],
.vtt-up-field input[type="text"] {
  min-height: var(--field);
  font-family: var(--font-body);
  font-size: 1rem;
  padding: 0 var(--s2);
  border: 1px solid var(--rule);
  border-radius: var(--s1);
  background: var(--panel);
  color: var(--ink);
}
.vtt-up-field input[type="range"] { min-height: var(--field); }

.vtt-up-actions {
  display: flex;
  gap: var(--s2);
  justify-content: flex-end;
  margin-top: var(--s4);
}

@media (max-width: 640px) {
  .vtt-up-controls { grid-template-columns: 1fr; }
  .vtt-up-canvas { max-height: 34vh; }
}

/* ---------- the fog brush ---------- */
/* While brushing, the stage must not also pan under the finger. */
.vtt-stage.is-brushing { cursor: crosshair; }
.vtt-stage.is-brushing .vtt-token { pointer-events: none; }

/* A tile that the server refused simply never arrives; nothing is drawn in its
   place, so the void shows through exactly as it does for a drawn map. */
.vtt-tile { image-rendering: auto; }

/* The opaque cover a PLAYER sees over unrevealed cells of an uploaded map.
   Cosmetic only — the pixels past the served tiles were never sent — but it
   makes the frontier land exactly where the brush put it instead of on a tile
   boundary. Matches the stage's own ground so the two are indistinguishable. */
.vtt-void {
  fill: #100d0a;
  pointer-events: none;
}

/* ---------- the fog tools ---------- */
.vtt-tool-row { display: grid; gap: var(--s2); }
.vtt-tool { display: inline-flex; align-items: center; gap: var(--s1); }
.vtt-tool kbd {
  font-family: var(--font-display);
  font-size: .7em;
  padding: 1px 5px;
  border: 1px solid currentColor;
  border-radius: 3px;
  opacity: .65;
}
.vtt-tool[aria-pressed="true"] {
  background: var(--gold);
  color: var(--rubric-ink);
  border-color: var(--gold-deep);
}
.vtt-tool[aria-pressed="true"] kbd { opacity: .85; }
.vtt-tool-readout {
  margin: 0;
  font-family: var(--label-font);
  font-size: .62rem;
  letter-spacing: var(--label-track);
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* The brush ring — Photoshop's circle, in world units so it shows how much
   GROUND the stroke covers rather than how big the cursor is. */
.vtt-brush-ring {
  fill: none;
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
  pointer-events: none;
}
.vtt-brush-ring--fog { stroke: var(--rubric); }
.vtt-brush-ring--erase { stroke: var(--gold-hi); }

/* ---------- the empty table ----------
   This is the FIRST thing a DM sees on a new campaign, so the two ways to put
   a map down live here rather than only in the bar. An empty state that just
   states the emptiness is a dead end. */

.vtt-empty-line {
  margin: 0;
  font-family: var(--font-scribal);
  font-size: 1.25rem;
  /* on the stage void, not on a panel — see .vtt-empty above */
  color: var(--gold-hi);
}
.vtt-empty-actions {
  display: flex;
  gap: var(--s3);
  flex-wrap: wrap;
  justify-content: center;
  pointer-events: auto; /* but the buttons are real */
}
.vtt-empty-hint {
  margin: 0;
  font-family: var(--label-font);
  font-size: .68rem;
  letter-spacing: var(--label-track);
  text-transform: uppercase;
  /* same trap as .vtt-empty above: this sits on the void, not on a panel, so
     --ink-faint measured 2.89:1 in daylight. --gold keeps the hint recessive
     under the --gold-hi line while clearing AA in both themes. */
  color: var(--gold);
}

/* ---------- the map drawer ---------- */
.vtt-maps-list {
  list-style: none;
  margin: var(--s4) 0 0;
  padding: 0;
  display: grid;
  gap: var(--s2);
  max-height: 58vh;   /* the chest is now a place you browse, not a short list */
  overflow-y: auto;
}
.vtt-map-row[data-active="1"] { border-color: var(--gold); background: var(--panel-2); }
.vtt-map-name {
  flex: 1;
  font-family: var(--font-body);
  font-size: 1rem;
  color: var(--ink);
  text-align: left;
}
.vtt-map-badge {
  font-family: var(--label-font);
  font-size: .6rem;
  letter-spacing: var(--label-track);
  text-transform: uppercase;
  color: var(--gold-deep);
}

/* ---------- the filing cabinet ----------
   A place is a heading, not a box: no border, a rule underneath, and its maps
   sit indented beneath it. Depth is one custom property so any nesting level
   indents by the same step without a rule per level. */
/* The chest is a list of things with names, so it gets more width than the
   forms this dialog class was built for. */
#vtt-maps-dialog { max-width: min(680px, 94vw); width: min(680px, 94vw); }

/* One line per place. The tools are deliberately small and fixed-width: given
   a whole row of their own they read as the loudest thing in the chest, when
   the list of places is what the DM came to look at. */
.vtt-loc-row {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--s2);
  padding: var(--s2) var(--s1) calc(var(--s1) / 2);
  border-bottom: 1px solid var(--rule);
  margin-top: var(--s3);
  margin-left: calc(var(--depth, 0) * var(--s4));
}
.vtt-loc-row:first-child { margin-top: 0; }
.vtt-loc-name {
  font-family: var(--font-display, var(--font-body));
  font-size: .95rem;
  color: var(--ink);
  letter-spacing: .01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.vtt-loc-kind {
  font-family: var(--label-font);
  font-size: .55rem;
  letter-spacing: var(--label-track);
  text-transform: uppercase;
  color: var(--ink-faint);
}
.vtt-loc-count { font-size: .7rem; color: var(--ink-faint); margin-left: auto; white-space: nowrap; }
.vtt-loc-tools { display: flex; align-items: center; gap: var(--s1); flex: 0 0 auto; }
.vtt-loc-tools .btn-quiet {
  flex: 0 0 auto;
  font-size: .65rem;
  padding: 2px var(--s2);
  min-height: 0;
  white-space: nowrap;
}
.vtt-loc-tools .vtt-map-file { flex: 0 0 16ch; max-width: 16ch; }

/* A map hanging in a place is indented one step past its heading. Its name is
   the only thing allowed to give up space; everything else is fixed, so the
   controls stay on one line however deep the indent goes. */
.vtt-map-row {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s2) var(--s3);
  border: 1px solid var(--rule);
  border-radius: var(--s1);
  background: var(--panel);
  min-height: var(--field);

  margin-left: calc((var(--depth, 0) + 1) * var(--s4));
  flex-wrap: wrap;
  row-gap: var(--s1);
  gap: var(--s2);
}
.vtt-map-row .vtt-map-name {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
  font-size: .85rem;
}
.vtt-map-row > .btn-quiet:not(.vtt-map-name) {
  flex: 0 0 auto;
  font-size: .65rem;
  padding: 2px var(--s2);
  min-height: 0;
  white-space: nowrap;
}
.vtt-map-row--loose { margin-left: 0; }
.vtt-map-level {
  width: 5.5ch;
  font-size: .8rem;
  padding: 2px var(--s1);
  text-align: center;
}
.vtt-map-file { flex: 0 0 15ch; max-width: 15ch; font-size: .75rem; padding: 2px var(--s1); }
.vtt-map-floor {
  font-family: var(--label-font);
  font-size: .55rem;
  letter-spacing: var(--label-track);
  text-transform: uppercase;
  color: var(--ink-faint);
  white-space: nowrap;
}
.vtt-newplace { margin-top: var(--s4); border-top: 1px solid var(--rule); padding-top: var(--s3); }
.vtt-newplace > summary {
  cursor: pointer;
  font-family: var(--label-font);
  font-size: .65rem;
  letter-spacing: var(--label-track);
  text-transform: uppercase;
  color: var(--ink-faint);
}
.vtt-newplace > summary:hover { color: var(--ink); }
/* The board's title line: which place this map is, above its own name. */
.vtt-place-line {
  font-family: var(--label-font);
  font-size: .6rem;
  letter-spacing: var(--label-track);
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0;
}
.vtt-place-line[hidden] { display: none; }

/* On a narrow screen the indent shrinks and rows wrap rather than dropping any
   control — filing a map is exactly what you do on the phone between sessions. */
@media (max-width: 640px) {
  .vtt-loc-row, .vtt-map-row { margin-left: calc(var(--depth, 0) * var(--s2)); }
  .vtt-map-row { flex-wrap: wrap; row-gap: var(--s1); }
  .vtt-map-name { flex-basis: 100%; }
  .vtt-map-file { max-width: none; flex: 1; }
}

/* Three kinds of space, three floors. A cavern reads as rough natural rock, a
   corridor as connective tissue, a room as worked stone. */
.vtt-floor--room { fill: var(--panel); }
.vtt-floor--corridor { fill: var(--panel-2); }
.vtt-floor--cavern { fill: var(--bg-1); }

/* ==========================================================================
   THE TABLE PANEL — the Live Table, dissolved into the Map (2026-08-05).
   Party vitals, initiative, the dice log, and the DM screen. Pass 5 moved it
   to the LEFT edge under its own corner tab (Tim: "slide-out sidebar buttons
   at the top left and top right"); the top padding leaves the corner tabs a
   clear landing. Hidden entirely in Player View casting (is-display).
   ========================================================================== */
.table-panel{
  position:absolute;
  top:0;left:0;bottom:0;
  width:min(380px, 92vw);
  z-index:30;
  overflow-y:auto;
  padding:calc(var(--s3) + 52px) var(--s4) var(--s5);
  background:var(--panel);
  border-right:1px solid var(--rule);
  box-shadow:var(--shadow);
  display:flex;
  flex-direction:column;
  gap:var(--s3);
  transform:translateX(0);
  transition:transform .2s ease;
}
.table-panel[hidden]{display:none}
/* The Table OVERLAYS the tools (Tim: the offset looked weird, and the tools
   are not for mid-table use) — the rail simply steps aside while it is out. */
.vtt.is-table-open .rail-shell{display:none}
.table-panel .live-party{display:flex;flex-direction:column;gap:var(--s2)}
.live-section-title{
  margin:0 0 var(--s1);
  font-family:var(--font-display);
  font-size:var(--fs-label);
  font-weight:700;
  letter-spacing:.1em;
  text-transform:uppercase;
  color:var(--gold-deep);
}
.vtt.is-display .table-panel,
.vtt.is-display .dungeon-panel,
.vtt.is-display .rail-shell{display:none}

/* ==========================================================================
   THE DUNGEON BOOK — the Draftsmith's panel, now a right-hand mirror of the
   table panel (pass 5): the DM's reading copy, under its own corner tab.
   ========================================================================== */
.dungeon-panel{
  position:absolute;
  top:0;right:0;bottom:0;
  width:min(420px, 92vw);
  z-index:30;
  overflow-y:auto;
  padding:calc(var(--s3) + 52px) var(--s4) var(--s5);
  background:var(--panel);
  border-left:1px solid var(--rule);
  box-shadow:var(--shadow);
}
.dungeon-panel[hidden]{display:none}

/* ==========================================================================
   THE CORNER TABS — Open Map, Table, Book. Square, labeled, one reach from
   the board on every viewport; z-35 keeps each tab reachable above the panel
   it toggles (z-30), so the door that opened a drawer can always close it.
   ========================================================================== */
.vtt-corner{
  position:absolute;
  top:var(--s3);
  z-index:35;
  display:flex;
  gap:var(--s2);
}
.vtt-corner--tl{left:var(--s3)}
.vtt-corner--tr{right:var(--s3)}
.corner-btn{
  min-width:44px;
  min-height:44px;
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  gap:2px;
  padding:var(--s1) var(--s2);
  background:var(--panel);
  border:1px solid var(--rule);
  border-radius:var(--r-sm);
  box-shadow:var(--shadow);
  color:var(--ink);
  cursor:pointer;
}
.corner-btn .tool-ic{width:20px;height:20px}
.corner-label{
  font-size:var(--fs-micro);
  font-weight:700;
  letter-spacing:.06em;
  text-transform:uppercase;
  color:var(--gold-deep);
  white-space:nowrap;
}
.corner-btn[aria-pressed="true"]{
  background:linear-gradient(180deg,var(--gold-btn-a),var(--gold-btn-b));
  border-color:var(--gold-deep);
  color:var(--on-gold);
}
.corner-btn[aria-pressed="true"] .corner-label{color:var(--on-gold)}
.corner-btn[hidden]{display:none}
.vtt.is-display .vtt-corner{display:none}
.db-head{display:grid;gap:var(--s2);margin-bottom:var(--s3)}
.db-kicker{margin:0;color:var(--gold-deep)}
.db-title{margin:0;font-family:var(--font-scribal);font-weight:400;font-size:var(--fs-xl);color:var(--ink)}
.db-stake{margin:0;font-family:var(--font-scribal);font-style:italic;color:var(--ink-soft)}
.db-empty{margin:0;color:var(--ink-faint);font-style:italic}
.db-brief summary{cursor:pointer;color:var(--gold-deep)}
.db-brief textarea{margin-top:var(--s1)}
.db-clock{margin:var(--s1) 0 0;padding-left:1.4em;display:grid;gap:4px;color:var(--ink-soft)}
.db-clock li::marker{font-family:var(--font-display);font-weight:700;color:var(--gold-deep)}
.db-rooms{display:grid;gap:var(--s2)}
.db-room{
  border:1px solid var(--rule);
  border-radius:var(--r-sm);
  background:var(--panel-2);
}
.db-room summary{
  display:flex;
  align-items:center;
  gap:var(--s2);
  min-height:40px;
  padding:var(--s1) var(--s2);
  cursor:pointer;
  list-style:none;
}
.db-room summary::-webkit-details-marker{display:none}
.db-room[open] summary{border-bottom:1px solid var(--rule-soft)}
.db-num{
  flex:none;
  width:28px;height:28px;
  display:flex;align-items:center;justify-content:center;
  border:1px solid var(--rule);
  border-radius:var(--r-sm);
  background:var(--panel);
  font-family:var(--font-display);
  font-weight:700;
}
.db-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--font-scribal);font-size:var(--fs-lg);color:var(--ink)}
.db-show{
  flex:none;
  width:30px;height:30px;
  display:flex;align-items:center;justify-content:center;
  border:1px solid var(--rule);
  border-radius:var(--r-sm);
  background:var(--panel);
  color:var(--gold-deep);
}
.db-show .tool-ic{width:16px;height:16px}
.db-fields{display:grid;gap:var(--s2);padding:var(--s2)}
.db-field{display:grid;gap:4px}
.db-name-in{
  min-height:var(--field-compact);
  padding:0 var(--s2);
  border:1px solid var(--rule);
  border-radius:var(--r-sm);
  background:var(--panel);
  color:var(--ink);
  font-family:var(--font-scribal);
  font-size:var(--fs-lg);
}
/* the boxed text — what the DM performs. Styled as the box it will be read from. */
.db-read-in{
  width:100%;
  resize:vertical;
  padding:var(--s2) var(--s3);
  border:1px solid color-mix(in srgb, var(--gold) 45%, var(--rule));
  border-left:3px solid var(--gold-deep);
  border-radius:var(--r-sm);
  background:color-mix(in srgb, var(--gold) 6%, var(--panel));
  color:var(--ink);
  font-family:var(--font-body);
  font-size:var(--fs-small);
  line-height:1.55;
}
.db-notes-in{
  width:100%;
  resize:vertical;
  padding:var(--s2) var(--s3);
  border:1px solid var(--rule);
  border-radius:var(--r-sm);
  background:var(--panel);
  color:var(--ink-soft);
  font-family:var(--font-body);
  font-size:var(--fs-small);
  line-height:1.55;
}
.db-read-in:focus-visible,.db-notes-in:focus-visible,.db-name-in:focus-visible{outline:2px solid var(--gold-deep);outline-offset:1px}

/* the flash when the book points at the map */
.vtt-room-flash{
  fill:color-mix(in srgb, var(--gold) 18%, transparent);
  stroke:var(--gold-deep);
  stroke-width:2.5;
  pointer-events:none;
  animation:db-flash 1.4s ease forwards;
}
@keyframes db-flash{
  0%{opacity:0}
  15%{opacity:1}
  70%{opacity:1}
  100%{opacity:0}
}
/* with the book open, room numbers become bookmarks */
.vtt.is-book-open .vtt-number{pointer-events:auto;cursor:pointer}

/* ==========================================================================
   BROWSE MODE — the Open Map tree as a file system: folders and leaves, one
   tap each, none of Manage's editing weight. (Pass 5, Tim's chair.)
   ========================================================================== */
.vtt-map-row--browse{border:0;background:transparent;padding:0}
.vtt-map-row--browse[data-active="1"]{background:transparent}
.vtt-map-row--browse .vtt-map-name{
  min-height:44px;
  flex:1;
  text-align:left;
  justify-content:flex-start;
  font-size:var(--fs-body);
}
.vtt-map-row--browse[data-active="1"] .vtt-map-name{border-color:var(--gold);background:var(--panel-2)}
.vtt-loc-row--browse{opacity:.9}

/* ==========================================================================
   THE AI PEN'S ROWS — a directive line in the book head, a touch-up line per
   room. Visible only when the server says a pen exists; every stroke costs
   real cents and confirms first.
   ========================================================================== */
.db-scribe{display:grid;gap:var(--s1);margin-top:var(--s2);padding-top:var(--s2);border-top:1px solid var(--rule)}
.db-scribe-title{margin:0;color:var(--gold-deep)}
.db-scribe-row{display:flex;gap:var(--s1);align-items:stretch}
.db-scribe-row--room{margin-top:var(--s1)}
.db-scribe-in{flex:1;min-height:44px}
.db-scribe-go{min-height:44px;white-space:nowrap}
.db-scribe-meter{margin:0}

/* Where this map hangs — the place line, top-center over the stage. A reading
   chip like the measure readout, not an interactive control. */
.vtt-place{
  position:absolute;
  left:50%;
  top:var(--s3);
  transform:translateX(-50%);
  margin:0;
  padding:var(--s1) var(--s3);
  border-radius:999px;
  border:1px solid var(--rule);
  background:var(--panel);
  color:var(--ink-soft);
  font-family:var(--font-scribal);
  font-size:.88rem;
  letter-spacing:.02em;
  pointer-events:none;
  z-index:3;
  max-width:min(60vw, 480px);
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}
.vtt-place[hidden]{display:none}
.vtt.is-display .vtt-place{display:none}
/* narrow phones: the corner tabs own the top edges; the chip stays between them */
@media (max-width:640px){
  .vtt-place{max-width:36vw}
}
/* range sliders in the map dialogs keep the house gold, not browser blue */
.vtt-upload-dialog input[type="range"]{accent-color:var(--gold-deep)}

/* ==========================================================================
   NEW MAP — the bottom-left door and its three tiles. The corner sits BELOW
   the panels (z-25 < 30): an open Table simply covers it, which is right —
   you are reading the table, not founding new lands.
   ========================================================================== */
.vtt-corner--bl{
  top:auto;
  bottom:var(--s3);
  left:var(--s3);
  z-index:25;
}
.nm-tiles{display:grid;gap:var(--s2);margin:var(--s3) 0}
.nm-tile{
  display:grid;
  grid-template-columns:28px 1fr;
  grid-template-rows:auto auto;
  column-gap:var(--s3);
  align-items:center;
  text-align:left;
  min-height:56px;
  padding:var(--s2) var(--s3);
  background:var(--panel);
  border:1px solid var(--rule);
  border-radius:var(--r-sm);
  color:var(--ink);
  cursor:pointer;
}
.nm-tile:hover{border-color:var(--gold-deep);background:var(--panel-2)}
.nm-tile .tool-ic{grid-row:1 / span 2;width:24px;height:24px;color:var(--gold-deep)}
.nm-name{font-family:var(--font-display);font-weight:700;letter-spacing:.03em}
.nm-line{font-family:var(--font-scribal);font-size:.88rem;color:var(--ink-faint)}

/* the delve dialog's folded dials, in the newplace details voice */
.vtt-adv{margin-top:var(--s3);border-top:1px solid var(--rule);padding-top:var(--s3)}
.vtt-adv > summary{
  cursor:pointer;
  font-family:var(--label-font);
  font-size:var(--label-size);
  font-weight:var(--label-weight);
  letter-spacing:var(--label-track);
  text-transform:uppercase;
  color:var(--ink-faint);
}
.vtt-adv > summary:hover{color:var(--ink)}
.vtt-adv[open] > summary{margin-bottom:var(--s3)}

/* the Maps dialog carries the whole workbench — give it more table */
#vtt-maps-dialog{width:min(46rem,calc(100vw - 1.4rem))}
