/* viewer.css — single-screen 3-panel drill workspace.
 * Layout: fixed-viewport grid (topnav · ticker bar · 3 panels · dock). Each panel
 * scrolls internally; the page never scrolls. Tokens mirror the design handoff. */

:root {
  --bg-app: #0a0a0a;
  --bg-panel: #0b0b0b;
  --bg-bar: #0c0c0c;
  --bg-raised: #161616;
  --hair: #161616;          /* in-panel hairline */
  --hair-bar: #1c1c1c;      /* between bars/panels */
  --border: #2a2a2a;
  --text: #ece8e1;
  --text-val: #cfc9bf;
  --text-mut: #8a847a;
  --text-mono-mut: #6f6a61;
  --text-dim: #5c5851;
  --text-dim2: #4f4b44;
  --gold: var(--accent);    /* THE interactive gold — single source is lite.css :root --accent */
  --commodity: #f5c518;
  --pos: #8bc34a;
  --mono: 'IBM Plex Mono', ui-monospace, monospace;
  --bg-card: #0d0d0d;
  --bg-input: #141414;
  --bg-hover: #1e1e1e;
  --border-2: #242424;
  --border-3: #333333;
  --text-strong: #ffffff;
  --accent-border: #5a4f1a;
  --accent-fill: #4a3a10;
}
/* ── LIGHT THEME — token overrides under <html data-theme="light">. Mirrors the
   global light area in lite.css: PURE WHITE surfaces (not cream), neutral cool-grey
   lines, and the interactive accent = LOGO BLUE (via --gold: var(--accent), which
   lite.css sets to #3f68ac in light mode). The 3D scene itself stays dark (its
   background is set in viewer_3d.js, not here). Chef, 2026-07-27. */
:root[data-theme="light"] {
  --bg-app: #ffffff; --bg-panel: #ffffff; --bg-bar: #ffffff; --bg-card: #ffffff;
  --bg-input: #ffffff; --bg-raised: #f1f3f7; --bg-hover: #e8ecf3;
  --hair: #eef0f3; --hair-bar: #e4e7ec; --border: #d6dae1; --border-2: #e7eaef; --border-3: #c7ccd6;
  --text: #1a1c22; --text-val: #363a44; --text-mut: #626873; --text-mono-mut: #767c88;
  --text-dim: #8b919d; --text-dim2: #a6acb7; --text-strong: #0f1117;
  --commodity: #a9781a; --pos: #2e7d32;
  /* interactive-at-rest fills, now blue-tinted to match the blue accent */
  --accent-border: #b9cbe8; --accent-fill: #e5edf8;
}


/* ── Shell ───────────────────────────────────────────────────────────────── */
.viewer-shell {
  position: fixed; inset: 0;
  display: grid;
  grid-template-rows: 50px 1fr 38px;   /* topnav (+ mine dropdown / view switcher) · panels · dock */
  background: var(--bg-app); color: var(--text);
  font-family: 'IBM Plex Sans', system-ui, sans-serif;
  overflow: hidden;
  /* --key-w-base = the panel's natural width (also the width of its inner wrapper, so the
     panel slides + clips cleanly on collapse rather than reflowing).
     --key-w      = its CURRENT width: the base, or 0 when collapsed.
     Splitting them is what lets the panel get NARROWER on small screens (media query at
     the end of this file) while the collapse animation still works. */
  --key-w-base: 306px;
  --key-w: var(--key-w-base);
}
/* ── The dock OVERLAYS; it does not resize the panels (2026-07-14) ──────────────
   Opening the dock used to grow this grid row (38px → 226px), which shrank the panels —
   forcing the WebGL canvas to reallocate and Leaflet to re-request tiles on every toggle.
   That's the stutter. Now the rows NEVER change: the dock's table slides up OVER the
   panels, so the 3D scene and the map keep their exact size and are never re-rendered.

   --dock-lift = how far the bottom-anchored furniture (3D toolbar, grade key, map layer
   control, map key, clear-highlight chip) must rise to stay above the open dock. Every one
   of them reads this var, so they travel with it. */
.viewer-shell { --dock-lift: 0px; }
.viewer-shell.dock-open { --dock-lift: 188px; }   /* = the table's height */
.viewer-shell.key-collapsed { --key-w: 0px; }
.viewer-main {
  display: grid;
  grid-template-columns: var(--key-w) 1fr;   /* left key-info · everything-else (PDF overlays) */
  min-height: 0;
  position: relative;                         /* anchors the PDF overlay + the drag divider */
  transition: grid-template-columns .18s ease;
  /* --pdf-w = current width of the PDF overlay, and the ONE number the whole split reads:
     the PDF panel's width, the divider's position, and every right-edge furniture inset.
     Default = today's 50/50 split of the non-key area, so nothing moves until you drag.
     The drag divider rewrites --pdf-w-both; the modes below override --pdf-w itself. */
  --pdf-w-both: calc((100% - var(--key-w)) / 2);
  --pdf-w: var(--pdf-w-both);
}
.viewer-main > * { min-height: 0; min-width: 0; }

/* Collapse tab — rides the panel's right edge; click to hide/show the left panel. */
.key-toggle {
  /* z-index above Leaflet's map panes (200–1000) so the tab isn't hidden when it
     sits over the map; still below the hole panel (3000) and lightbox (10000). */
  position: absolute; left: var(--key-w); top: 50%; transform: translateY(-50%);
  z-index: 1200; width: 16px; height: 50px; padding: 0;
  background: var(--bg-raised); border: 1px solid var(--border); border-left: none;
  border-radius: 0 6px 6px 0; color: var(--gold); cursor: pointer;
  display: flex; align-items: center; justify-content: center; font-weight: 600;
  box-shadow: 2px 0 8px rgba(0,0,0,.35);
  transition: left .18s ease, background .15s, border-color .15s;
}
.key-toggle:hover { background: var(--bg-hover); border-color: var(--gold); }
.key-toggle::before { content: '‹'; font-size: 15px; }
.key-collapsed .key-toggle::before { content: '›'; }
/* Pin each panel to its column so hiding one (display:none in map/doc mode)
   doesn't let the others auto-shift — that used to slide the doc panel into the
   0-width column in Document mode and render it blank. */
.panel-key { grid-column: 1; }
.panel-map { grid-column: 2; }
/* PDF is an OVERLAY (2026-07-16), no longer a grid column. The middle stage renders at full
   width UNDERNEATH it, so dragging the divider just REVEALS more of the already-rendered
   middle — no reflow, no canvas realloc, no tile re-request. Only --pdf-w moves.
   • Both     → --pdf-w = the dragged width (default = the old 50/50 split)
   • Map      → --pdf-w = 0  (PDF hidden; middle already full-width, so NOTHING re-renders)
   • Document → --pdf-w = the whole non-key area (PDF fills it, as before) */
.panel-doc {
  position: absolute; top: 0; right: 0; bottom: 0;
  width: var(--pdf-w); z-index: 50;
  transition: width .18s ease;
}
.viewer-main.dragging .panel-doc { transition: none; }   /* follow the cursor with no lag */
.viewer-main.mode-map { --pdf-w: 0px; }
.viewer-main.mode-map .panel-doc { display: none; }
.viewer-main.mode-doc { --pdf-w: calc(100% - var(--key-w)); }

/* The drag divider — sits on the seam (the PDF's left edge) and moves --pdf-w-both.
   Only meaningful in Both mode; hidden when one panel is collapsed. */
.pdf-divider {
  position: absolute; top: 0; bottom: 0; right: var(--pdf-w);
  width: 9px; transform: translateX(4px);        /* straddle the seam */
  z-index: 60; cursor: col-resize;
  transition: right .18s ease;
}
.viewer-main.dragging .pdf-divider { transition: none; }
.pdf-divider::before {                            /* invisible at rest; reveals in gold on hover/drag */
  content: ''; position: absolute; top: 0; bottom: 0; left: 4px; width: 1px;
  background: transparent; transition: background .12s, width .12s;
}
.pdf-divider:hover::before,
.viewer-main.dragging .pdf-divider::before { background: var(--gold); left: 3px; width: 3px; }
.viewer-main.mode-map .pdf-divider,
.viewer-main.mode-doc .pdf-divider { display: none; }
/* An iframe swallows pointer events, so mid-drag the parent stops getting pointermove the
   moment the cursor crosses onto the PDF. Switch it off for the duration of the drag. */
.viewer-main.dragging .panel-doc iframe { pointer-events: none; }

.mono { font-family: var(--mono); }

/* ── Row 1 · top nav ─────────────────────────────────────────────────────── */
.vw-topnav {
  display: flex; align-items: center; gap: 22px;
  background: var(--bg-bar); border-bottom: 1px solid var(--hair-bar); padding: 0 18px;
}
.vw-brand { display: flex; align-items: center; gap: 8px; }
.vw-brand .diamond { color: var(--gold); font-size: 15px; }
.vw-brand .name { font-weight: 600; letter-spacing: .16em; font-size: 13px; }
.vw-navlinks { display: flex; gap: 22px; }
.vw-navlinks a { font-size: 13px; color: var(--text-mut); text-decoration: none; padding: 4px 0; }
.vw-navlinks a.active { color: var(--text-strong); border-bottom: 2px solid var(--gold); }
.vw-navlinks a:hover { color: var(--text-strong); }
/* Account link — top-right, mirrors the main-site nav (Log in · username · Log out). */
.vw-auth-link { font-size: 13px; color: var(--text-mut); text-decoration: none; white-space: nowrap; }
.vw-auth-link:hover { color: var(--gold); }
.vw-user { font-size: 13px; color: var(--text-val); font-weight: 500; text-decoration: none; white-space: nowrap; }
.vw-user:hover { color: var(--gold); }
.vw-topnav .spacer { flex: 1; }

/* Watch (save to watchlist) button */
.watch-btn { font-size: 12px; color: var(--text-mut); background: var(--bg-input);
  border: 1px solid var(--border); border-radius: 7px; padding: 5px 11px; cursor: pointer;
  font-family: 'IBM Plex Sans', system-ui, sans-serif; white-space: nowrap; }
.watch-btn:hover { border-color: var(--gold); color: var(--gold); }
.watch-btn.on { color: var(--gold); border-color: var(--accent-border); background: var(--accent-soft); }

.vw-auth { display: flex; align-items: center; }
.vw-auth-link { font-size: 12px; color: var(--text-mut); text-decoration: none; }
.vw-auth-link:hover { color: var(--gold); }

/* Header quick-search — 1 type + Enter to jump to another ticker/company */
.vw-search { position: relative; }
#hdr-search {
  width: 210px; background: var(--bg-input); border: 1px solid var(--border);
  border-radius: 7px; color: var(--text); font-size: 12.5px; padding: 5px 10px 5px 28px;
  font-family: 'IBM Plex Sans', system-ui, sans-serif;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13' height='13' viewBox='0 0 24 24' fill='none' stroke='%238a847a' stroke-width='2.2'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M21 21l-4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: 9px center;
}
#hdr-search::placeholder { color: var(--text-dim); }
#hdr-search:focus { border-color: var(--gold); outline: none; }
.vw-search-results {
  position: absolute; left: 0; right: 0; top: calc(100% + 5px); min-width: 250px;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px;
  overflow: hidden; z-index: 1300; display: none; box-shadow: 0 12px 30px rgba(0, 0, 0, .55);
}
.vw-sr-row { display: flex; justify-content: space-between; align-items: center;
  gap: 10px; padding: 7px 11px; cursor: pointer; }
.vw-sr-row:hover, .vw-sr-row.active { background: var(--bg-raised); }
.vw-sr-row .tk { font-family: var(--mono); color: var(--text); font-weight: 600; font-size: 12px; }
.vw-sr-row .nm { color: var(--text-mut); font-size: 11px; text-align: right;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vw-sr-empty { padding: 8px 11px; color: var(--text-dim); font-size: 11px; }
.vw-ghost-btn { font-size: 12px; color: var(--text-mut); border: 1px solid var(--border);
  background: none; padding: 6px 11px; border-radius: 7px; cursor: pointer; }
.vw-ghost-btn:hover { color: var(--text); border-color: var(--border-3); }
.vw-avatar { width: 30px; height: 30px; border-radius: 50%; background: var(--hair-bar);
  border: 1px solid var(--border-3); color: var(--gold); display: flex; align-items: center;
  justify-content: center; font-size: 13px; }

/* ── Row 2 · ticker bar ──────────────────────────────────────────────────── */
.vw-tickerbar {
  display: flex; align-items: center; gap: 18px;
  background: var(--bg-bar); border-bottom: 1px solid var(--hair-bar); padding: 0 18px;
}
.vw-back { color: var(--text-mut); font-size: 20px; text-decoration: none; }
.vw-tk { font-size: 22px; font-weight: 600; }
.vw-company { font-size: 13px; color: var(--text-mut); }
.vw-vdiv { width: 1px; height: 26px; background: var(--border-2); }
.vw-asx { font-family: var(--mono); font-size: 12px; color: var(--text-mono-mut); }
.vw-price { font-family: var(--mono); font-size: 16px; font-weight: 500; }
.vw-change { font-family: var(--mono); font-size: 12.5px; color: var(--pos); }

/* ── Company card (top of the left panel) ────────────────────────────────── */
.cc { padding: 14px 18px 12px; border-bottom: 1px solid var(--hair); }
.cc-tk { font-size: 21px; font-weight: 600; letter-spacing: .02em; }
.cc-name { font-size: 11px; color: var(--text-mut); margin-top: 1px; }
.cc-quote { display: flex; align-items: baseline; gap: 10px; margin-top: 9px; }
.cc-price { font-family: var(--mono); font-size: 22px; font-weight: 500; color: var(--text-strong); }
/* Daily change is deliberately COLOURLESS — the ▲/▼ glyph already carries direction, so
   red/green here was pure noise (the whole card is being calmed down). Grey in both
   directions; the .neg toggle stays in the markup but no longer changes the colour. */
.cc-change,
.cc-change.neg { font-family: var(--mono); font-size: 12.5px; color: var(--text-muted); }
#cc-spark { width: 100%; height: 54px; display: block; margin-top: 8px; }
.cc-meta { display: flex; justify-content: space-between; font-family: var(--mono);
  font-size: 10px; color: var(--text-mono-mut); margin-top: 5px; }

/* Chart timeframe tabs */
.cc-tf { display: flex; gap: 2px; margin: 9px 0 4px; background: var(--bg-input); border: 1px solid var(--bg-hover);
  border-radius: 7px; padding: 2px; width: fit-content; }
.cc-tf button { background: none; border: none; color: var(--text-mut); font-size: 10.5px; padding: 2px 9px;
  border-radius: 5px; cursor: pointer; font-family: var(--mono); }
.cc-tf button.active { background: var(--gold); color: var(--bg-app); }

/* 52-week range bar */
.fin-range { margin: 11px 0 2px; }
.fin-range .fr-head { display: flex; justify-content: space-between; font-size: 9px;
  color: var(--text-mut); text-transform: uppercase; letter-spacing: .08em; margin-bottom: 5px; }
.fin-range .fr-head .fr-cur { font-family: var(--mono); color: var(--text-val); letter-spacing: 0; }
.fin-range .fr-bar { position: relative; height: 5px; background: var(--hair-bar); border-radius: 3px; }
.fin-range .fr-dot { position: absolute; top: 50%; width: 10px; height: 10px; border-radius: 50%;
  background: var(--gold); border: 2px solid var(--bg-app); transform: translate(-50%, -50%); }
.fin-range .fr-labels { display: flex; justify-content: space-between; font-family: var(--mono);
  font-size: 9px; color: var(--text-dim); margin-top: 4px; }

/* "sample data" tag on preview sections */
.sample-tag { font-family: var(--mono); font-size: 8.5px; text-transform: uppercase; letter-spacing: .1em;
  color: var(--gold); border: 1px solid var(--accent-fill); background: rgba(224,160,48,.08); border-radius: 4px;
  padding: 1px 5px; margin-left: 6px; font-weight: 400; vertical-align: middle; }
[data-sample] { position: relative; }

/* ════════════════════════════════════════════════════════════════════════
   Full-width Financials view (map-variant "finance")
   ════════════════════════════════════════════════════════════════════════ */
/* right: var(--pdf-w) → the plot occupies only the VISIBLE width, never under the PDF overlay. */
.map-stage #finance { position: absolute; top: 0; left: 0; bottom: 0; right: var(--pdf-w); overflow: hidden; background: var(--bg-app); }
.fin-scroll { position: absolute; inset: 0; overflow-y: auto; padding: 16px 18px 24px; }
.fin-banner { font-size: 11px; color: var(--gold); background: rgba(224,160,48,.07);
  border: 1px solid var(--accent-fill); border-radius: 7px; padding: 7px 11px; margin-bottom: 14px; }
.fin-banner b { color: var(--gold); }

.fin-hero { display: flex; justify-content: space-between; align-items: flex-start;
  gap: 20px; flex-wrap: wrap; margin-bottom: 14px; }
.fin-co { font-size: 15px; font-weight: 600; color: var(--text); }
.fin-price-row { display: flex; align-items: baseline; gap: 12px; margin-top: 5px; flex-wrap: wrap; }
.fin-price { font-family: var(--mono); font-size: 30px; font-weight: 500; color: var(--text-strong); }
.fin-chg { font-family: var(--mono); font-size: 13px; color: var(--pos); }
.fin-chg.neg { color: var(--error); }
.fin-asx { font-family: var(--mono); font-size: 11px; color: var(--text-mono-mut); }
.fin-hero-r { display: flex; gap: 22px; flex-wrap: wrap; }
.fin-kpi { display: flex; flex-direction: column; }
.fin-kpi span { font-size: 9px; text-transform: uppercase; letter-spacing: .08em; color: var(--text-mut); }
.fin-kpi b { font-family: var(--mono); font-size: 17px; font-weight: 500; color: var(--text); margin-top: 2px; }

.fin-card { background: var(--bg-card); border: 1px solid var(--hair-bar);
  border-radius: 10px; padding: 13px 15px; }
.fin-card-h { display: flex; align-items: center; justify-content: space-between;
  font-size: 11px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase;
  color: var(--text-mut); margin-bottom: 9px; }
.fin-note { font-family: var(--mono); font-size: 10px; color: var(--text-mono-mut);
  font-weight: 400; text-transform: none; letter-spacing: 0; }
.fin-foot { color: var(--text-dim); font-size: 11px; margin-top: 16px; }
/* per-prospect resources/reserves/production table (scaffold) */
.fin-profile { font-size: 11px; color: var(--text-mut); margin: 2px 0 10px; }
.fin-profile b { color: var(--text-val); font-family: var(--mono); font-weight: 500; }
.fin-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.fin-table th, .fin-table td { padding: 6px 10px; text-align: right; border-bottom: 1px solid var(--hair); white-space: nowrap; }
.fin-table thead th { color: var(--text-mut); font-family: var(--mono); font-size: 10px;
  text-transform: uppercase; letter-spacing: .05em; font-weight: 600; border-bottom-color: var(--hair-bar); }
.fin-table th:first-child, .fin-table td:first-child { text-align: left; }
.fin-table tbody td:first-child { color: var(--text-mut); }
.fin-table tbody td { font-family: var(--mono); color: var(--text-val); }
.fin-table tr.ft-group td { text-align: left; color: var(--text); font-family: var(--sans);
  font-weight: 600; font-size: 10px; text-transform: uppercase; letter-spacing: .06em;
  padding-top: 13px; border-bottom: none; }
.fin-table tbody tr:last-child td { border-bottom: none; }
/* green / red for change + performance values */
.fin-row .fr-v.pos, .fin-kpi b.pos { color: var(--pos); }
.fin-row .fr-v.neg, .fin-kpi b.neg { color: var(--error); }
.fin-chart-card { margin-bottom: 14px; }
#fin-chart-canvas { width: 100%; height: 170px; display: block; }
.fin-vol { display: flex; align-items: flex-end; gap: 2px; height: 34px; margin-top: 4px; }
.fin-vol i { flex: 1; background: var(--border); border-radius: 1px 1px 0 0; }
.fin-range.big { margin-top: 12px; }

.fin-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 14px; }
.fin-card-wide { grid-column: 1 / -1; }
.fin-two { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; }
@media (max-width: 720px) { .fin-two { grid-template-columns: 1fr; } }

/* Cash-runway pips */
.fin-runway { margin-top: 11px; }
.runway-bar { display: flex; gap: 4px; margin-top: 6px; }
.runway-bar i { flex: 1; height: 8px; border-radius: 2px; background: var(--pos); }
.runway-bar i.half { background: linear-gradient(90deg, var(--pos) 50%, var(--border) 50%); }

/* Peer EV/oz comparison bars */
.fin-peer { display: flex; flex-direction: column; gap: 6px; }
.peer-row { display: grid; grid-template-columns: 56px 1fr 44px; align-items: center; gap: 8px; font-size: 11px; }
.peer-row > span { color: var(--text-mut); }
.peer-row > b { font-family: var(--mono); color: var(--text-val); text-align: right; font-weight: 500; }
.peer-bar { height: 7px; background: var(--hair-bar); border-radius: 3px; overflow: hidden; }
.peer-bar i { display: block; height: 100%; background: linear-gradient(90deg, var(--accent-dim), var(--gold)); }

/* Explorer fundamentals — key / value / source rows */
.fin-rows { display: flex; flex-direction: column; }
.fin-row { display: flex; align-items: baseline; gap: 8px; padding: 5px 0;
  border-bottom: 1px solid var(--hair); font-size: 12px; }
.fin-row:last-child { border-bottom: none; }
.fin-row .fr-k { color: var(--text-mut); flex: 1; }
.fin-row .fr-v { font-family: var(--mono); color: var(--text-val); }
.fin-row .fr-src { font-family: var(--mono); font-size: 8px; color: var(--text-dim);
  text-transform: uppercase; letter-spacing: .06em; border: 1px solid var(--hair-bar);
  border-radius: 3px; padding: 1px 4px; }
/* flat commodity label — no gold box (style guide §3 + light-mode consistency) */
.vw-commodity { font-size: 11px; color: var(--commodity); padding: 3px 0; letter-spacing: .04em; }
.vw-tickerbar .spacer { flex: 1; }
.vw-project { text-align: right; }
.vw-project .pname { font-size: 13px; color: var(--text-val); }
.vw-project .pmeta { font-family: var(--mono); font-size: 11px; color: var(--text-mono-mut); }

/* view switcher (segmented) */
.vw-switcher { display: flex; background: var(--bg-input); padding: 3px; border-radius: 8px;
  border: 1px solid var(--bg-hover); gap: 2px; }
.vw-switcher button { padding: 5px 13px; border-radius: 6px; font-size: 12.5px; font-weight: 500;
  color: var(--text-mut); background: none; border: none; cursor: pointer;
  white-space: nowrap; }   /* else "3D Intercepts" breaks onto two lines when space is tight */
.vw-switcher button.active { color: var(--bg-app); background: var(--gold); }

/* mine/deposit dropdown — now in the topnav; reset the base .deposit-toggle
   margins/border so it sits vertically centred with the view-switcher buttons. */
#deposit-toggle { display: flex; align-items: center; gap: 4px;
  margin: 0; padding: 0; border: none; max-width: 360px; }

/* ── Panels (shared) ─────────────────────────────────────────────────────── */
.vw-panel { overflow-y: auto; background: var(--bg-panel); }
/* overflow-y:auto is LOAD-BEARING. Without it the panel had no scroll at all, so on a
   short screen (e.g. 1366x768) its content simply ran past the bottom of the grid row and
   was CLIPPED by the shell's overflow:hidden — Best Intercepts and most of Project Details
   became unreachable, not just cramped. A sidebar taller than the viewport must scroll;
   the alternative is hiding data. (2026-07-14) */
.panel-key { width: 100%; border-right: 1px solid var(--hair-bar);
  overflow-x: hidden; overflow-y: auto; }
.panel-key-inner { width: var(--key-w-base); }   /* matches the panel → slides + clips (no reflow) on collapse */
/* position is set to absolute in the overlay block above (2026-07-16) — do NOT re-set it here
   or the PDF stops overlaying and falls back into flow. Just the look + flex layout. */
/* No left border — the seam between the map and the PDF is unlined (chef, 2026-07-17). The
   drag divider still lives here; it's invisible at rest and reveals in gold on hover. */
.panel-doc { display: flex; flex-direction: column; }

/* Section locator overlay — satellite map covering the doc panel */
/* Section locator + 3D locator — same overlay treatment, so "locate" looks and behaves
   identically wherever you press it. Both cover the document panel. */
#locator-overlay,
#tdloc-overlay { position: absolute; inset: 0; z-index: 30; background: var(--bg-app);
  display: flex; flex-direction: column; }
.loc-bar { height: 44px; flex-shrink: 0; background: var(--bg-bar); border-bottom: 1px solid var(--hair-bar);
  display: flex; align-items: center; justify-content: space-between; padding: 0 14px; }
.loc-title { font-size: 12px; font-weight: 600; color: var(--text-val); }
.loc-sub { font-family: var(--mono); font-size: 10px; color: var(--text-mono-mut); font-weight: 400; margin-left: 6px; }
.loc-close { cursor: pointer; font-size: 15px; color: var(--text-mut); line-height: 1; }
.loc-close:hover { color: var(--text-strong); }
#locator-map,
#tdloc-map { flex: 1; min-height: 0; background: var(--bg-app); }
#locator-map .leaflet-control-zoom a,
#tdloc-map .leaflet-control-zoom a { background: rgba(13,13,13,.95); color: var(--text-mut); border-color: var(--border-2); }
#locator-map .leaflet-control-zoom a:hover,
#tdloc-map .leaflet-control-zoom a:hover { color: var(--gold); }
/* position+z-index makes this a stacking CONTEXT below the PDF overlay (z-index 50). Without
   it, Leaflet's map panes and controls (z-index up to ~1000) render straight over the PDF —
   the satellite/tenements map appears on top of the doc. Containing panel-map keeps all of
   its high-z descendants beneath the overlay, so the PDF covers the map as intended. The 3D
   canvas is a single element so it never showed the bug; only Leaflet did. (2026-07-16) */
.panel-map { display: flex; flex-direction: column; background: var(--bg-app); overflow: hidden;
  position: relative; z-index: 1; }

/* No divider rule between left-panel sections (2026-07-14). Each border was a line the
   eye had to process and dismiss; the uppercase labels + whitespace already separate the
   sections perfectly well. Fewer lines = less noise, same structure. */
.vw-section { padding: 14px 18px; }
.vw-label { font-size: 11px; color: var(--text-mut); font-weight: 600; letter-spacing: .13em;
  text-transform: uppercase; display: flex; justify-content: space-between; align-items: center; }
.vw-hint { font-family: var(--mono); font-size: 10px; color: var(--text-dim); text-transform: none; letter-spacing: 0; }

/* ── About (left panel) ───────────────────────────────────────────────────────
   Clamped to 3 lines + a "More" toggle. The clamp is the point: the summary was a
   ~10-line wall eating a third of the panel, which is why it FELT small (it was
   12.48px — barely below the 12.5px verdict beside it). Cutting the footprint is
   what lets the type grow to a comfortable 13px/1.6.
   Tokens only — the old inline #a8a49b (text) and #6f8f6f (link) were hardcoded hex
   that bypassed the palette and, in the link's case, added a green that meant nothing.
   The link is now --accent gold because it is INTERACTIVE, which is exactly what that
   token is reserved for. */
/* Chip row under the About heading: Gold · Active exploration · … then the summary. */
.viewer-shell .about-chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;                       /* wider gap now the pills are gone — the space IS the separator */
  margin-top: 8px;
}
.viewer-shell .about-chips:empty { display: none; }

/* Chips — NO pill, NO border (2026-07-14). Two reasons:
   1. A bordered pill reads as a BUTTON. These aren't clickable, so the border was
      lying about what they are — and that lie is louder in gold.
   2. Every chip used to carry its own hardcoded hex (gold/green/brown/grey), which is
      four colours doing one job: "here is a fact about this project".
   They're now flat labels. Gold = the project's headline facts; grey = caveats. */
.viewer-shell .chip {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .06em;
  white-space: nowrap;
}
.viewer-shell .chip-commodity,
.viewer-shell .chip-activity { color: var(--accent); }

/* Caveats stay deliberately quiet and neutral — they are NOT headline facts, and
   colouring them would make a footnote shout. */
.viewer-shell .chip-note,
.viewer-shell .chip-warn {
  color: var(--text-mut);          /* viewer.css's own token name — it has a light override */
  white-space: normal;             /* the "not graphed yet" note is a sentence, let it wrap */
}

.viewer-shell .about-text {
  margin-top: 6px;
  font-size: 13px;
  line-height: 1.6;
  color: var(--text-val);
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
}
.viewer-shell .about-text.is-open {
  -webkit-line-clamp: unset;
  overflow: visible;
}
/* The chevron. Deliberately the SAME visual language as .key-toggle (the tab that
   collapses the whole left panel): raised surface, hairline border, gold chevron —
   so "this expands/collapses a thing" is ONE learned pattern on this page, not two.
   Horizontal there (‹ ›) because the panel slides sideways; vertical here (⌄) because
   the text opens downward. */
/* Same tab as .key-toggle (16 x 50px), transposed to 50 x 16px because this one opens
   DOWNWARD rather than sideways. Same surface, border, radius and gold chevron — one
   learned "expand" pattern, not two. Left-aligned to the panel's text column. */
.viewer-shell .about-more {
  display: flex;                   /* flex centring — no magic pixel nudges */
  align-items: center;
  justify-content: center;
  width: 50px;
  height: 16px;
  margin: 7px 0 0;                 /* left-aligned in the container */
  padding: 0;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: 0 0 6px 6px;      /* rounded on the side it opens toward */
  border-top: none;
  color: var(--gold);
  cursor: pointer;
  transition: background .15s, border-color .15s;
}
/* display:block is LOAD-BEARING — `transform` is ignored on non-replaced INLINE
   elements, so without it the chevron silently renders unrotated (i.e. pointing left).
   Reusing .key-toggle's '‹' glyph keeps the two controls one family. */
.viewer-shell .about-more::before {
  content: '‹';
  display: block;
  font-size: 15px;
  font-weight: 600;
  line-height: 1;
  transform: rotate(-90deg);       /* ‹ → points DOWN (collapsed) */
  transition: transform .18s ease;
}
.viewer-shell .about-more:hover { background: var(--bg-hover); border-color: var(--gold); }
.viewer-shell .about-more[aria-expanded="true"]::before {
  transform: rotate(90deg);        /* ‹ → points UP (expanded) */
}

/* Detail revealed only on expand — the website link lives here. */
.viewer-shell .about-extra { display: none; }
.viewer-shell .about-extra.is-open { display: block; }
.viewer-shell .about-link {
  display: inline-block;
  margin-top: 8px;
  font-size: 12px;
  text-decoration: none;
  color: var(--accent);
}
.viewer-shell .about-link:hover { text-decoration: underline; }

/* "top 10 of 483" caption beside the Best Intercepts label */
.viewer-shell .ic-count {
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--text-dim);
}

/* best-intercept rows (left panel) + cross-highlight */
.bi-row { display: grid; grid-template-columns: 9px 1fr auto; align-items: center;
  gap: 9px; padding: 6px 0; cursor: pointer; transition: background .14s; }
.bi-dot { width: 9px; height: 9px; border-radius: 50%; }
.bi-call { font-family: var(--mono); font-size: 12.5px; }
.bi-call .dim { color: var(--text-mut); }
.bi-id { font-family: var(--mono); font-size: 10.5px; color: var(--text-mono-mut); text-align: right; }
.bi-depth { font-family: var(--mono); font-size: 10px; color: var(--text-dim2); text-align: right; }

/* ── Cross-highlight active states ───────────────────────────────────────── */
[data-hole].is-active { background: rgba(200,169,110,.12); }
.bi-row.is-active { box-shadow: inset 2px 0 0 var(--gold); }
.hl-hole { background: rgba(245,197,24,.16); cursor: pointer; border-radius: 2px; padding: 0 2px;
  color: var(--bg-input); text-decoration: underline; text-decoration-color: var(--accent-dim);
  text-underline-offset: 2px; font-weight: 600; }
.hl-hole.is-active { background: rgba(245,197,24,.5); }
tr[data-hole].is-active { background: rgba(200,169,110,.10); }

/* ── Centre map panel ────────────────────────────────────────────────────── */
.map-header { height: 44px; flex-shrink: 0; background: var(--bg-bar); border-bottom: 1px solid var(--hair-bar);
  display: flex; align-items: center; justify-content: flex-end; gap: 10px; padding: 0 14px; }
.grade-legend { display: flex; align-items: center; gap: 7px; font-family: var(--mono);
  font-size: 9.5px; color: var(--text-dim); }
.grade-legend .bar { width: 84px; height: 7px; border-radius: 2px;
  /* the shared grade scale (grade_colors.js): blue→green→yellow→orange→red→white */
  background: linear-gradient(90deg,#2244cc 0%,#44cc44 17%,#ffee00 33%,#ff8800 67%,#ff2200 99%,var(--text-strong) 100%); }
.map-stage { flex: 1; position: relative; min-height: 0; }
/* The 3D scene and the satellite map fill the WHOLE stage (full width, under the PDF overlay).
   The stage itself is always full width, so these never resize when the PDF width changes —
   dragging just uncovers more of them. This is what makes Map/Both switching free of any
   re-render. (2026-07-16) */
.map-stage #viewer-container, .map-stage #sat-map {
  position: absolute; inset: 0; width: 100%; height: 100%; border: none; border-radius: 0; margin: 0; }
/* Sections + Financials are width-FITTED plots, not spatial scenes — a full-width plot with
   its right half hidden under the PDF would just lose data. They occupy the VISIBLE width
   (inset by the PDF) and re-fit on drag-release. This is the one place the split behaves
   differently by tab, exactly as intended.
   NB: the inset lives ON the #sections / #finance rules themselves (search `right: var(--pdf-w)`),
   NOT here — later `inset:0` rules would otherwise override a separate rule placed above them. */

/* ── The ONE loading indicator ────────────────────────────────────────────────
   A centred spinner + label, shown over the view panel while any tab's data loads —
   silent loading reads as "broken". Uniform everywhere via window.stageLoader() (viewer_page).
   Inset by --pdf-w so it centres in the VISIBLE area, not under the PDF. It sits inside
   .map-stage (a z-1 stacking context), so it can never cover the PDF overlay. (2026-07-16) */
.ds-loader {
  position: absolute; top: 0; left: 0; bottom: 0; right: var(--pdf-w);
  z-index: 1500; display: none;
  flex-direction: column; align-items: center; justify-content: center; gap: 14px;
  background: color-mix(in srgb, var(--bg-app) 72%, transparent);
  pointer-events: none;   /* never blocks a click meant for the content behind it */
}
.ds-loader.on { display: flex; }
.ds-spinner {
  width: 34px; height: 34px; border-radius: 50%;
  border: 3px solid var(--border-2);
  border-top-color: var(--accent);        /* the moving gold arc */
  animation: ds-spin .8s linear infinite;
}
@keyframes ds-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .ds-spinner { animation-duration: 2.4s; } }
.ds-loader-label {
  font-family: var(--mono); font-size: 12px; letter-spacing: .05em; color: var(--text-mut);
}
/* Honest failure: no spinner (nothing is still happening), label in the error colour. */
.ds-loader.error .ds-spinner { display: none; }
.ds-loader.error .ds-loader-label { color: var(--error); }

/* ── Right announcement panel ────────────────────────────────────────────── */
.doc-toolbar { height: 44px; flex-shrink: 0; background: var(--bg-bar); border-bottom: 1px solid var(--hair-bar);
  display: flex; align-items: center; gap: 10px; padding: 0 14px; font-family: var(--mono);
  font-size: 11px; color: var(--text-mut); }
/* Gold label pointing at the PDF dropdown — makes it obvious the selector is for source PDFs. */
.doc-pdf-label { flex: 0 0 auto; white-space: nowrap; font-family: var(--mono); font-size: 12px;
  font-weight: 600; letter-spacing: .02em; color: var(--gold); }
.doc-scroll { flex: 1; overflow-y: auto; background: var(--bg-bar); padding: 16px; }
.doc-page { background: #fbfaf7; color: var(--hair-bar); border-radius: 3px; box-shadow: 0 2px 18px rgba(0,0,0,.5);
  padding: 0 0 22px; }
.doc-letterhead { background: var(--bg-input); color: var(--text-strong); display: flex; justify-content: space-between;
  align-items: center; padding: 12px 18px; }
.doc-letterhead .lh-name { font-weight: 700; letter-spacing: .12em; font-size: 12px; }
.doc-letterhead .lh-tag { color: var(--gold); font-size: 10px; letter-spacing: .14em; text-align: right; }
.doc-body { padding: 20px 22px; }
.doc-eyebrow { text-align: center; font-size: 10px; color: var(--accent-dim); font-weight: 600; letter-spacing: .1em; }
.doc-h1 { text-align: center; font-size: 19px; font-weight: 700; color: var(--bg-input); margin: 8px 0; }
.doc-hr { height: 1px; background: #ddd6c8; margin: 14px 0; }
.doc-intercepts li { margin: 8px 0; font-size: 13px; line-height: 1.5; color: var(--border); }

/* ── Row 4 · dock ────────────────────────────────────────────────────────── */
.vw-dockbar { display: flex; align-items: center; gap: 14px; background: var(--bg-bar);
  border-top: 1px solid var(--hair-bar); padding: 0 18px; cursor: pointer; }
.vw-dockbar .tab { font-size: 12px; font-weight: 500; }
.vw-dockbar .tab .dock-n { color: var(--text-mut); }
.vw-dockbar .muted { color: var(--text-mono-mut); }
.vw-dockbar .spacer { flex: 1; }
.vw-dockbar .stamp { font-family: var(--mono); font-size: 10.5px; color: var(--text-mono-mut); }
.vw-dockbar .chev { color: var(--text-mut); transition: transform .2s; }
.dock-open .vw-dockbar .chev { transform: rotate(180deg); }

/* Slides up OVER the panels — absolutely positioned, so nothing below it resizes.
   Parked below the dock bar (translateY(100%)) and clipped by the shell's overflow:hidden
   until opened. */
.dock-table-wrap {
  position: absolute; left: 0; right: 0; bottom: 38px;   /* 38px = the dock bar */
  height: 188px; overflow-y: auto;
  background: var(--bg-panel);
  border-top: 1px solid var(--hair-bar);
  box-shadow: 0 -8px 24px rgba(0,0,0,.45);
  z-index: 1400;                       /* over the panels + Leaflet, under modals */
  transform: translateY(100%);
  transition: transform .18s ease;
  pointer-events: none;
}
.dock-open .dock-table-wrap { transform: translateY(0); pointer-events: auto; }
/* The bar itself stays put and stays on top — the table parks behind it when closed. */
.vw-dockbar { position: relative; z-index: 1500; }
.dock-table { width: 100%; border-collapse: collapse; }
.dock-table th { font-family: var(--mono); font-size: 10px; color: var(--text-dim); letter-spacing: .08em;
  text-transform: uppercase; text-align: left; background: var(--bg-app); padding: 6px 12px;
  position: sticky; top: 0; }
.dock-table td { font-size: 12px; padding: 6px 12px; border-bottom: 1px solid var(--hair); }
.dock-table td.hid { font-family: var(--mono); color: var(--gold); }
.dock-table td.m { font-family: var(--mono); color: var(--text-val); }
.dock-table td.assays { font-family: var(--mono); color: var(--pos); }
/* Company vs Historic origin pill — matches the map's grade-layer ring colours. */
.dock-origin { font-family: var(--mono); font-size: 10px; letter-spacing: .04em; padding: 1px 7px;
  border-radius: 999px; border: 1px solid; white-space: nowrap; }
.dock-origin.is-company  { color: #7aa0d8; border-color: #24406e; background: rgba(11,27,58,.35); }
.dock-origin.is-historic { color: #e6a52e; border-color: #7a5410; background: rgba(230,165,46,.10); }
.dock-table tr { cursor: pointer; transition: background .14s; }
.dock-table tbody tr:hover { background: rgba(200,169,110,.08); }
.dock-table th:hover { color: var(--text-mut); }
.dock-table th.sort-asc, .dock-table th.sort-desc { color: var(--gold); }
.dock-table th.sort-asc::after { content: ' ▲'; font-size: 8px; }
.dock-table th.sort-desc::after { content: ' ▼'; font-size: 8px; }

/* Dock filter input (in the always-visible dock bar) */
.dock-filter {
  background: var(--bg-input); border: 1px solid var(--border); border-radius: 6px;
  color: var(--text); font-size: 11px; font-family: 'IBM Plex Sans', system-ui, sans-serif;
  padding: 3px 9px; width: 150px;
}
.dock-filter::placeholder { color: var(--text-dim); }
.dock-filter:focus { outline: none; border-color: var(--gold); }

/* ── Right panel: announcement list + embedded PDF ───────────────────────── */
.ann-list { flex-shrink: 0; max-height: 168px; overflow-y: auto;
  border-bottom: 1px solid var(--hair-bar); background: var(--bg-panel); }
.ann-item { padding: 8px 14px; border-bottom: 1px solid var(--hair); cursor: pointer; transition: background .14s; }
.ann-item:hover { background: var(--bg-input); }
.ann-item.active { background: rgba(200,169,110,.10); box-shadow: inset 3px 0 0 var(--gold); }
.ann-date { font-family: var(--mono); font-size: 10px; color: var(--text-mono-mut); }
.ann-head { font-size: 12px; color: var(--text-val); margin: 2px 0; line-height: 1.3; }
.ann-holes { font-family: var(--mono); font-size: 10px; color: var(--pos); }
.ann-empty { padding: 18px 14px; color: var(--text-dim); font-size: 12px; line-height: 1.5; }
.doc-pdf-wrap { flex: 1; position: relative; min-height: 0; background: var(--bg-bar); }
#doc-pdf { width: 100%; height: 100%; border: none; }
/* NB: you CANNOT restyle the background behind the PDF page from here. The browser's native PDF
   viewer fills this iframe and paints its own letterbox; `color-scheme` does NOT reach it (A/B
   tested 2026-07-17 — dark vs light produced identical output). The only way to control that
   background is to render PDFs with PDF.js instead of the native viewer. */
.doc-empty { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  text-align: center; color: var(--text-dim); font-size: 12.5px; line-height: 1.7; padding: 20px; }

/* Notepad — an overlay over the PDF area (so it never disturbs the iframe underneath). */
.doc-notes { position: absolute; inset: 0; z-index: 5; display: flex; flex-direction: column;
  background: var(--bg-app); }
.doc-notes textarea {
  flex: 1; width: 100%; resize: none; border: none; outline: none;
  background: var(--bg-app); color: var(--text-val);
  font-family: var(--mono); font-size: 13px; line-height: 1.6; padding: 14px 16px;
}
.doc-notes textarea::placeholder { color: var(--text-dim); }
.notes-status {
  flex: 0 0 auto; height: 24px; display: flex; align-items: center; padding: 0 16px;
  font-family: var(--mono); font-size: 11px; color: var(--text-mut);
  border-top: 1px solid var(--hair-bar); background: var(--bg-bar);
}
.notes-status.ok   { color: var(--pos); }
.notes-status.warn { color: var(--accent); }   /* "sign in to save" — a nudge, not an error red */
#doc-mode-toggle.active { background: var(--accent-soft); border-color: var(--accent); color: var(--text-strong); }

/* ════════════════════════════════════════════════════════════════════════
   Stage-2 polish — restyle the reused components to the design tokens.
   All scoped under .viewer-shell so other pages keep lite.css styling.
   ════════════════════════════════════════════════════════════════════════ */

/* Mine-info → quiet header, not a green box */
.viewer-shell .mine-info { background: transparent !important; padding: 13px 18px !important; }
.viewer-shell .mine-info h3 { color: var(--text); font-size: 13px; font-weight: 600; margin: 0 0 7px; }
.viewer-shell .mine-chip { background: var(--bg-raised); border: 1px solid var(--border-2); color: var(--text-mut); font-size: 9.5px; }
/* commodity-hint mine chip — colour the text only; keep the neutral base box (no gold fill) */
.viewer-shell .mine-chip.gold { color: var(--commodity); }
.viewer-shell .mine-meta { font-size: 11px; color: var(--text-mut); line-height: 1.6; }
.viewer-shell .mine-wiki { font-size: 10.5px; color: var(--text-dim); border-top-color: var(--hair); }

/* Key Findings (scorecard) */
/* Key Findings — DAMPENED so the interactive gold up top wins the eye hierarchy.
   Keeps a DAMP-gold accent stripe (same hue, quieter). Grade swatches are muted
   below — the vivid grade colours belong on the map/3D, not shouting in a corner. */
.viewer-shell .scorecard { font-size: 12px; border-left-color: var(--accent-quiet); background: transparent; }
.viewer-shell .panel-key .sc-tierbar,
.viewer-shell .panel-key .sc-chip i,
.viewer-shell .panel-key .bi-dot { filter: saturate(0.62) brightness(0.72); }
.viewer-shell .sc-verdict { color: var(--text-mut); font-size: 12.5px; line-height: 1.6; margin-bottom: 11px; }
.viewer-shell .sc-stats { display: grid; grid-template-columns: 1fr 1fr; gap: 9px 10px; margin-bottom: 11px; }
.viewer-shell .sc-stat b { font-family: var(--mono); color: var(--text-val); font-size: 14px; font-weight: 500; display: block; }
.viewer-shell .sc-stat span { color: var(--text-mut); font-size: 9px; text-transform: uppercase; letter-spacing: .08em; }
.viewer-shell .sc-stat.sc-best { grid-column: 1 / -1; }
.viewer-shell .sc-stat.sc-best b { color: var(--text-val); font-size: 12.5px; }
.viewer-shell .sc-tierbar { display: flex; height: 6px; border-radius: 3px; overflow: hidden; margin-bottom: 7px; }
.viewer-shell .sc-tierbar span { display: block; }
.viewer-shell .sc-legend { display: flex; flex-wrap: wrap; gap: 9px; }
.viewer-shell .sc-chip { font-size: 9.5px; color: var(--text-mut); display: flex; align-items: center; gap: 4px; }
.viewer-shell .sc-chip i { width: 8px; height: 8px; border-radius: 2px; display: inline-block; }

/* Project Details (stats grid) → 2-col label/value */
.viewer-shell .stats-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 14px; }
.viewer-shell .stat-box .sb-val { font-family: var(--mono); color: var(--text-val); font-size: 13.5px; }
.viewer-shell .stat-box .sb-label { color: var(--text-dim); font-size: 9px; text-transform: uppercase;
  letter-spacing: .1em; margin-top: 3px; }

/* Best-intercept call-outs (left panel) */
.viewer-shell .bi-call { line-height: 1.3; }
.viewer-shell .table-expand { background: none; border: none; color: var(--gold); font-size: 11px;
  cursor: pointer; padding: 4px 0; }

/* 3D controls strip → compact, on-token */
/* Map interaction controls — brightened labels so the toggles read as clickable. */
/* Cutoff / Size / Opacity / Elev labels.
   These are flex ITEMS in the toolbar, and a flex item SHRINKS by default (flex-shrink:1).
   Once the bar ran out of room they were squeezed narrower than their contents, so the
   inline text wrapped INSIDE the label — "Cutoff" ended up above or below its slider.
   inline-flex + nowrap + flex:0 0 auto pins each label to its natural width: the label and
   its slider stay on one line, side by side, and the BAR scrolls instead of the label
   breaking. (2026-07-14) */
.viewer-shell .viewer-controls label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;          /* never shrink — scroll the bar, don't mangle the label */
  white-space: nowrap;
  font-size: 12px;
  color: var(--text-val);
}
.viewer-shell .viewer-controls input[type="range"] { flex: 0 0 auto; }
.viewer-shell .viewer-controls .checkbox-label { color: var(--text-val); }
.viewer-shell .viewer-controls select { background: var(--bg-input); border: 1px solid var(--border-2); color: var(--text-val);
  font-size: 0.72rem; padding: 0.15rem 0.3rem; }
.viewer-shell .viewer-controls input[type="range"] { accent-color: var(--gold); }
/* The 3D control bar — same bar as the sections' .sec-controls: same height, background,
   border, padding and gap. Previously it was styled by inline hex in the template
   (#0c0c0c / #1c1c1c) with different padding, so the two toolbars read as different
   components even though they do the same job in the same place. (2026-07-14) */
/* THE toolbar. Both bars are this: #threed-controls and #sections-controls, siblings of
   .map-stage. One rule — it was split across three separate blocks as this session went on,
   which is how a component quietly grows two personalities.
   padding-left 6px (was 12): chef wanted the first button sitting closer to the edge. Both
   bars share it, so they stay consistent by construction. */
.viewer-shell .viewer-controls {
  height: 40px;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 12px 0 6px;
  background: var(--bg-bar);
  border-top: 1px solid var(--hair-bar);
  flex-shrink: 0;
  /* Never scroll VERTICALLY: overflow-x on its own would force overflow-y from `visible` to
     `auto` (CSS spec), and a 40px bar with 28px buttons would then sprout both scrollbars. */
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
  /* Rides up with the open drill-hole dock (translate → no reflow, so nothing re-renders). */
  transform: translateY(calc(-1 * var(--dock-lift)));
  transition: transform .18s ease;
  position: relative;
  z-index: 900;
  /* Stop the bar (and its horizontal button scroll) at the PDF's left edge, so the buttons
     never hide behind the PDF overlay — the toolbar "knows" the PDF width. (2026-07-16) */
  margin-right: var(--pdf-w);
}
/* Was an undefined class → an invisible empty span. Now matches .sec-sep. */
.viewer-shell .control-sep {
  width: 1px; height: 20px; background: var(--border-2); margin: 0 4px; flex: 0 0 auto;
}

/* 3D control buttons — deliberately IDENTICAL to the sections' .sec-btn (2026-07-14).
   Both bars sit in the same place doing the same job, so a button should not look like a
   different species depending on which tab you're on. Values copied from .sec-btn: same
   height, padding, radius, type size, and the same hover/active behaviour. */
.viewer-shell .nav-btn {
  background: var(--bg-input); border: 1px solid var(--border-2); color: var(--text-mut);
  font-size: 12px; height: 28px; padding: 0 12px; border-radius: 6px; cursor: pointer;
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  line-height: 1; white-space: nowrap;
}
.viewer-shell .nav-btn:hover { border-color: var(--gold); color: var(--text); }
.viewer-shell .nav-btn.active { background: var(--gold); color: var(--bg-app); border-color: var(--gold); }

/* 3D "Locate" — same gold treatment as the sections' Locate, since it's the same action. */
.viewer-shell #td-locate { border-color: var(--gold); background: var(--accent-soft); color: var(--gold); font-weight: 600; }
.viewer-shell #td-locate:hover { background: var(--accent-soft); color: var(--text-strong); }
.viewer-shell #td-locate.active { background: var(--gold); color: var(--bg-app); }

/* deposit toggle tabs in the ticker bar */
.viewer-shell .deposit-tab { background: var(--bg-input); border: 1px solid var(--bg-hover); color: var(--text-mut);
  font-size: 11.5px; padding: 4px 10px; border-radius: 6px; cursor: pointer; white-space: nowrap; }
.viewer-shell .deposit-tab:hover { border-color: var(--gold); color: var(--text); }
.viewer-shell .deposit-tab.active { background: var(--gold); color: var(--bg-app); border-color: var(--gold); }

/* scrollbars — slim + dark to match */
.viewer-shell .vw-panel::-webkit-scrollbar, .viewer-shell .ann-list::-webkit-scrollbar,
.viewer-shell .dock-table-wrap::-webkit-scrollbar { width: 8px; height: 8px; }
.viewer-shell ::-webkit-scrollbar-thumb { background: var(--border-2); border-radius: 4px; }
.viewer-shell ::-webkit-scrollbar-track { background: transparent; }

/* Dropdowns (mine selector + announcement picker) */
.vw-select { background: var(--bg-input); color: var(--text-val); border: 1px solid var(--border-2); border-radius: 7px;
  padding: 5px 28px 5px 10px; font-size: 12.5px; font-family: 'IBM Plex Sans', system-ui, sans-serif;
  cursor: pointer; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%238a847a' stroke-width='1.5' fill='none'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center; }
.vw-select:hover, .vw-select:focus { border-color: var(--gold); outline: none; }
.vw-select option { background: var(--bg-input); color: var(--text-val); }

/* Mine/deposit dropdown — TOP of the interaction hierarchy: gold border + soft
   gold fill AT REST (not only on hover) so the eye lands on it immediately. */
#deposit-toggle .vw-select {
  border-color: var(--gold); background-color: var(--accent-soft); color: var(--text); font-weight: 500;
}
#deposit-toggle .vw-select:hover, #deposit-toggle .vw-select:focus {
  background-color: rgba(240, 180, 43, 0.2);
}

/* ── Hole-detail panel (click a hole on the map or in 3D) ──────────────────── */
#hole-panel .hp-head { display:flex; justify-content:space-between; align-items:center;
  font-size:13px; font-weight:600; color:var(--text);
  cursor: grab; user-select: none; touch-action: none; }
#hole-panel .hp-head:active { cursor: grabbing; }
#hole-panel .hp-close { cursor:pointer; color:var(--text-mut); font-size:14px; line-height:1; }
#hole-panel .hp-close:hover { color:var(--text-strong); }
#hole-panel .hp-meta { font-family:var(--mono); font-size:10px; color:var(--text-mut);
  line-height:1.6; margin:6px 0 10px; }
#hole-panel .hp-body { display:flex; gap:10px; }
/* downhole strip log */
#hole-panel .hp-rail { position:relative; width:24px; height:240px; background:var(--bg-app);
  border:1px solid var(--border-2); border-radius:3px; flex-shrink:0; }
#hole-panel .hp-seg { position:absolute; left:0; right:0; min-height:1px; }
#hole-panel .hp-seg.hl { outline:2px solid var(--text-strong); outline-offset:-1px; z-index:3; }
#hole-panel .hp-d0, #hole-panel .hp-d1 { position:absolute; left:28px; font-family:var(--mono);
  font-size:9px; color:var(--text-dim); white-space:nowrap; }
#hole-panel .hp-d0 { top:-3px; } #hole-panel .hp-d1 { bottom:-3px; }
/* interval numbers */
#hole-panel .hp-ivs { flex:1; overflow-y:auto; max-height:240px; }
#hole-panel .hp-iv { font-size:11px; color:var(--text-val); padding:3px 0;
  border-bottom:1px solid var(--hair); }
#hole-panel .hp-iv.hl { background:rgba(245,197,24,.14); }
#hole-panel .hp-iv b { color:var(--text-strong); }
#hole-panel .hp-dot { display:inline-block; width:8px; height:8px; border-radius:2px;
  margin-right:5px; vertical-align:middle; }
#hole-panel .hp-depth { display:block; color:var(--text-mono-mut); font-family:var(--mono);
  font-size:9.5px; margin-left:13px; }
#hole-panel .hp-empty { font-size:11px; color:var(--text-dim); padding:8px 0; }
#hole-panel .hp-src { width:100%; margin:0 0 10px; padding:6px 10px; font-size:11px;
  font-family:'IBM Plex Sans',system-ui,sans-serif; color:var(--gold);
  background:rgba(200,169,110,.08); border:1px solid var(--border); border-radius:6px; cursor:pointer; }
#hole-panel .hp-src:hover { background:rgba(200,169,110,.16); border-color:var(--gold); color:var(--text-strong); }
#hole-panel .hp-src:disabled { color:var(--text-dim); border-color:var(--border); background:none; cursor:default; }

/* ── Leaflet controls, restyled to the dark theme ─────────────────────────── */
.viewer-shell .leaflet-control-layers {
  background: rgba(13,13,13,.85);        /* translucent — the map reads through it */
  border: 1px solid var(--border); border-radius: 8px;
  color: var(--text-val); box-shadow: 0 4px 18px rgba(0,0,0,.55);
}
.viewer-shell .leaflet-control-layers-expanded {
  padding: 8px 12px; font: 12px 'IBM Plex Sans', system-ui, sans-serif;
}
/* Lay the toggles out in COLUMNS, not one tall stack (2026-07-14). Seven overlays in a
   single column made a tall thin tower up the side of the map; two columns give a squat,
   horizontal box that sits along the bottom edge and covers far less of the drilling.
   (The Satellite/Topo radios are gone entirely, which took out two more rows + separator.) */
.viewer-shell .leaflet-control-layers-overlays {
  display: grid;
  grid-template-columns: repeat(2, minmax(150px, auto));
  column-gap: 18px;
  row-gap: 0;
}
.viewer-shell .leaflet-control-layers label {
  display: flex; align-items: center; gap: 7px; margin: 2px 0;
  color: var(--text-mut); cursor: pointer; white-space: nowrap;
}
/* Historic is a cross-view toggle (3D / map / sections), not a map layer — give it a
   hairline above so it reads as its own thing rather than another overlay. */
.viewer-shell .leaflet-control-layers .lc-historic {
  grid-column: 1 / -1;
  margin-top: 5px; padding-top: 5px;
  border-top: 1px solid var(--border-2);
}
/* No base layers any more → Leaflet still emits an empty separator div. Hide it. */
.viewer-shell .leaflet-control-layers-separator { display: none; }
.viewer-shell .leaflet-control-layers label:hover { color: var(--text-strong); }
.viewer-shell .leaflet-control-layers input[type="radio"],
.viewer-shell .leaflet-control-layers input[type="checkbox"] {
  accent-color: var(--gold); cursor: pointer; margin: 0;
}
.viewer-shell .leaflet-control-layers-separator {
  border-top: 1px solid var(--border-2); margin: 7px -12px;
}
.viewer-shell .leaflet-bar { border: none; box-shadow: 0 4px 18px rgba(0,0,0,.55); }
.viewer-shell .leaflet-bar a {
  background: rgba(13,13,13,.95); color: var(--text-mut); border-bottom: 1px solid var(--border-2);
}
.viewer-shell .leaflet-bar a:first-child { border-radius: 8px 8px 0 0; }
.viewer-shell .leaflet-bar a:last-child { border-radius: 0 0 8px 8px; border-bottom: none; }
.viewer-shell .leaflet-bar a:hover { background: var(--hair-bar); color: var(--gold); }

/* ── Map key (bottom-RIGHT of the map while a layer is on) ─────────────────────
   Moved from bottom-left 2026-07-14 so it doesn't collide with the layer control,
   which now sits bottom-left. The two bracket the map: toggles left, key right. */
/* Inset locator minimap — top-left of the satellite/tenements map. A small "you are here"
   world view. Non-interactive (Leaflet handlers are off); pointer-events:none also lets a
   click in that corner fall through to the main map. (2026-07-16) */
.map-minimap {
  position: absolute; top: 10px; left: 10px; width: 156px; height: 116px;
  z-index: 1000; border: 1px solid var(--border); border-radius: 6px;
  overflow: hidden; box-shadow: 0 2px 10px rgba(0,0,0,.45); pointer-events: none;
}
.map-minimap .leaflet-container { background: #14181d; }

/* Other-company markers on the tenements map — a small ticker pill, one per site ticker.
   Deliberately NOT collar-coloured (blue/bronze) so it never reads as a drill hole. (2026-07-16) */
.tk-marker {
  display: inline-block; padding: 2px 7px; border-radius: 10px;
  background: rgba(20,16,6,.9); color: var(--accent); text-decoration: none;
  border: 1px solid var(--accent); box-shadow: 0 1px 4px rgba(0,0,0,.5);
  font: 600 11px var(--mono); letter-spacing: .04em; white-space: nowrap; cursor: pointer;
  transform: translate(-50%, -50%);   /* centre the pill on its coordinate */
}
.tk-marker:hover { background: var(--accent); color: #1a1406; }
.tk-pop { min-width: 150px; font-family: var(--mono); }
.tk-pop-name { font-weight: 600; font-size: 13px; color: var(--text-strong); margin-bottom: 2px; }
.tk-pop-meta { font-size: 11px; color: var(--text-mut); margin-bottom: 8px; }
.tk-pop-open {
  display: block; width: 100%; padding: 6px 10px; margin-bottom: 6px; box-sizing: border-box;
  background: var(--accent); color: #1a1406; border: none; border-radius: 6px;
  font: 600 12px var(--mono); cursor: pointer; text-align: center; text-decoration: none;
}
.tk-pop-open:hover { filter: brightness(1.08); }
.tk-pop-hint { font-size: 10px; color: var(--text-dim); }

/* Box-select tool button (top-right Leaflet control). Gold when active — same language as the
   3D/sections toggle buttons: gold = on. (2026-07-16) */
.map-tool-btn {
  width: 34px; height: 34px; display: flex; align-items: center; justify-content: center;
  background: rgba(13,13,13,.85); color: var(--text-mut); cursor: pointer;
  border: 1px solid var(--border); border-radius: 6px; font-size: 15px; line-height: 1;
  box-shadow: 0 2px 8px rgba(0,0,0,.4);
}
.map-tool-btn:hover { color: var(--text-strong); border-color: var(--accent); }
.map-tool-btn.active { background: var(--accent); color: #1a1406; border-color: var(--accent); }
/* The box tool is a top-RIGHT Leaflet control, so it sits at the full-width map's right edge —
   under the PDF overlay. Inset the right control column by the PDF width so it rides with the
   other furniture. The layer control is bottom-LEFT, so it's unaffected. (2026-07-16) */
.viewer-shell .leaflet-right { right: var(--pdf-w); transition: right .18s ease; }

.geo-legend {
  /* right inset includes --pdf-w so the key stays clear of the PDF overlay (2026-07-16) */
  position: absolute; right: calc(10px + var(--pdf-w)); bottom: 10px; z-index: 1000;
  background: rgba(13,13,13,.85);        /* translucent, matching the layer control */
  border: 1px solid var(--border); border-radius: 8px;
  padding: 9px 11px; max-width: 250px; max-height: 42%; overflow-y: auto;
}
/* Force-hidden off the sat/tenements tabs (viewer_shell). Overrides the inline display that
   syncLegend() sets from content, so leaving the map tabs hides the key without erasing it —
   coming back restores whatever layers were on. */
.geo-legend.tab-hidden { display: none !important; }
.geo-legend .gl-title {
  font-family: var(--mono); font-size: 9.5px; font-weight: 600; letter-spacing: .12em;
  color: var(--text-mut); text-transform: uppercase; margin-bottom: 6px;
}
.geo-legend .gl-row {
  display: flex; gap: 7px; align-items: flex-start; margin: 4px 0;
  font-size: 11px; color: var(--text-val); line-height: 1.25;
}
.geo-legend .gl-swatch {
  width: 12px; height: 12px; border-radius: 3px; flex: 0 0 auto; margin-top: 1px;
  border: 1px solid rgba(255,255,255,.25);
}
.geo-legend .gl-age { display: block; font-family: var(--mono); font-size: 9px; color: var(--text-mono-mut); }
.geo-legend .gl-note { font-size: 9px; color: var(--text-dim); margin-top: 6px; }
.geo-legend .gl-sec { margin-bottom: 9px; }
.geo-legend .gl-sec:last-child { margin-bottom: 0; }
.geo-legend .gl-img {
  display: block; max-width: 100%; margin-top: 3px;
  background: #f2f0ea; border-radius: 4px; padding: 3px;
}

/* ── Tenement click popup (dark, matches the theme) ───────────────────────── */
.ten-popup .leaflet-popup-content-wrapper { background:var(--bg-card); color:var(--text);
  border:1px solid var(--border-3); border-radius:8px; box-shadow:0 4px 18px rgba(0,0,0,.6); }
.ten-popup .leaflet-popup-tip { background:var(--bg-card); border:1px solid var(--border-3); }
.ten-popup .leaflet-popup-content { margin:10px 12px; font-family:'IBM Plex Sans',system-ui,sans-serif; }
.ten-popup .leaflet-popup-close-button { color:var(--text-mut); }
.ten-pop .ten-id { font-size:15px; font-weight:600; color:var(--gold); }
.ten-pop .ten-holder { font-size:11px; color:var(--text-mut); margin:2px 0 8px; line-height:1.3; }
.ten-pop .ten-row { display:flex; justify-content:space-between; gap:14px; font-size:12px;
  padding:3px 0; border-top:1px solid var(--hair); }
.ten-pop .ten-row span:first-child { color:var(--text-dim); }
.ten-pop .ten-row span:last-child { color:var(--text-val); text-align:right; }

/* ── Sections view (cross-section PNGs in the centre stage) ────────────────── */
.map-stage #sections { position:absolute; top:0; left:0; bottom:0; right:var(--pdf-w); overflow-y:auto; background:var(--bg-app); padding:14px; }
.map-stage #sections .sec-empty { color:var(--text-dim); font-size:12px; padding:20px; text-align:center; }
.sections-grid > div { margin:0 auto 16px; max-width:820px; background:var(--bg-card); border:1px solid var(--hair-bar);
  border-radius:8px; overflow:hidden; }
.sections-grid img { width:100%; display:block; cursor:zoom-in; background:var(--text-strong); }
.sections-grid .section-label { font-family:var(--mono); font-size:11px; color:var(--text-mut); padding:7px 11px; }

/* ── Interactive sections (Plotly) — overrides the old PNG-grid styling above ── */
.map-stage #sections { position:absolute; top:0; left:0; bottom:0; right:var(--pdf-w); background:var(--bg-app); overflow:hidden; padding:0; }
/* Controls sit at the BOTTOM of the panel (2026-07-14), matching the 3D view's control
   bar — every centre view now has its toolbar in the same place. */
/* The Sections toolbar is now a SIBLING of .map-stage (id #sections-controls in _map.html),
   exactly like the 3D bar — so it's styled entirely by .viewer-controls and needs no
   positioning of its own. It used to be `position:absolute` INSIDE the stage, which is what
   made the shared grade key sit lower here than on the 3D tab: same `bottom:10px`, but a
   different amount of stage underneath it. Structural fix, not a CSS offset. (2026-07-15)
   The old z-index:6 (to beat the Y slider) is gone too — the bar is no longer over the plot. */
.sec-btn { background:var(--bg-input); border:1px solid var(--border-2); color:var(--text-mut); font-size:12px;
  height:28px; padding:0 12px; border-radius:6px; cursor:pointer; flex:0 0 auto;
  display:inline-flex; align-items:center; justify-content:center; line-height:1; white-space:nowrap; }
.sec-btn:hover { border-color:var(--gold); color:var(--text); }
.sec-btn.active { background:var(--gold); color:var(--bg-app); border-color:var(--gold); }

/* Locate button — gold so it clearly reads as clickable; solid gold when the
   locator is open (toggle state). */
#sec-locate { border-color:var(--gold); background:var(--accent-soft); color:var(--gold); font-weight:600; }
#sec-locate:hover { background:var(--accent-soft); color:var(--text-strong); }
#sec-locate.active { background:var(--gold); color:var(--bg-app); }

/* Pin-slice button + saved-pins dropdown (login-gated) */
#sec-pin.sec-btn:hover { border-color:var(--gold); color:var(--gold); }
.sec-pins-wrap { position:relative; flex:0 0 auto; }
#sec-pins-btn.on { color:var(--gold); border-color:var(--accent-border); background:var(--accent-soft); }
/* Fixed (not absolute) so the controls bar's overflow-x:auto can't clip it, and above
   the Plotly graph. Its top/left are set in JS from the Pins button's position. */
.sec-pins-pop { position:fixed; z-index:3000; min-width:210px; max-height:60vh; overflow-y:auto;
  background:var(--bg-card); border:1px solid var(--border); border-radius:8px;
  box-shadow:0 10px 26px rgba(0,0,0,.55); }
.sec-pin-row { display:flex; align-items:center; justify-content:space-between; gap:8px;
  padding:7px 11px; cursor:pointer; font-size:11.5px; }
.sec-pin-row:hover { background:var(--bg-raised); }
.sec-pin-row .pin-lbl { font-family:var(--mono); color:var(--text-val); flex:1; }
.sec-pin-row:hover .pin-lbl { color:var(--gold); }
.sec-pin-row .pin-del { color:var(--text-dim); font-size:11px; padding:0 2px; }
.sec-pin-row .pin-del:hover { color:var(--error); }
.sec-pin-empty { padding:9px 11px; color:var(--text-dim); font-size:10.5px; line-height:1.5; }

/* ◀ ▶ slice-step buttons */
.sec-step { background:var(--bg-input); border:1px solid var(--border-2); color:var(--text-val); font-size:11px;
  border-radius:5px; padding:2px 7px; cursor:pointer; flex:0 0 auto; }
.sec-step:hover:not(:disabled) { border-color:var(--gold); color:var(--gold); }
.sec-step:disabled { opacity:.4; cursor:default; }

/* Vertical Y-axis (RL/depth) range slider — the y-axis counterpart to Plotly's
   built-in x range slider, matching its look: a neutral track, the region OUTSIDE
   the window dimmed, and yellow grab bars marking the window edges. On the LEFT,
   sized to the plot's data area by JS. Drag window = pan, handles = zoom. */
.sec-yslider { position:absolute; left:6px; width:16px; z-index:4; }
.sec-yslider .ys-track { position:absolute; left:3px; right:3px; top:0; bottom:0;
  background:var(--bg-input); border:1px solid var(--border-2); border-radius:2px; }
/* dimmed masks above/below the window (like Plotly's rangeslider mask) */
.sec-yslider .ys-mask { position:absolute; left:3px; right:3px; background:rgba(8,8,8,.6); }
.sec-yslider .ys-sel { position:absolute; left:1px; right:1px; border:1px solid var(--border-3);
  border-radius:2px; cursor:grab; }
.sec-yslider .ys-sel:active { cursor:grabbing; }
/* the position bars — YELLOW (only these, not the whole window) */
.sec-yslider .ys-h { position:absolute; left:-2px; right:-2px; height:5px; background:var(--gold);
  border-radius:2px; cursor:ns-resize; touch-action:none; box-shadow:0 0 0 1px rgba(0,0,0,.45); }
.sec-yslider .ys-top { top:-3px; }
.sec-yslider .ys-bot { bottom:-3px; }
.sec-hint { margin-left:auto; font-size:10px; color:var(--text-dim); font-family:var(--mono); }

/* Horizontal X-axis range slider — the EXACT MIRROR of the Y slider above, transposed.
   Same parts, same look, same interaction: a neutral track, the region OUTSIDE the window
   dimmed, gold grab bars on the window edges. Sits ABOVE the plot (in the reserved top
   margin), which is why Plotly's built-in one had to go — it can only render below.
   Sized to the plot's data area by JS. Drag the window = pan, drag a handle = zoom.
   (2026-07-15) */
.sec-xslider { position:absolute; height:16px; z-index:4; }
.sec-xslider .xs-track { position:absolute; top:3px; bottom:3px; left:0; right:0;
  background:var(--bg-input); border:1px solid var(--border-2); border-radius:2px; }
/* dimmed regions left/right of the window — shows how much deposit you're NOT looking at */
.sec-xslider .xs-mask { position:absolute; top:3px; bottom:3px; background:rgba(8,8,8,.6); }
.sec-xslider .xs-sel { position:absolute; top:1px; bottom:1px; border:1px solid var(--border-3);
  border-radius:2px; cursor:grab; }
.sec-xslider .xs-sel:active { cursor:grabbing; }
/* the position bars — GOLD (only these, not the whole window) */
.sec-xslider .xs-h { position:absolute; top:-2px; bottom:-2px; width:5px; background:var(--gold);
  border-radius:2px; cursor:ew-resize; touch-action:none; box-shadow:0 0 0 1px rgba(0,0,0,.45); }
.sec-xslider .xs-left { left:-3px; }
.sec-xslider .xs-right { right:-3px; }

.sec-plot { position:absolute; inset:0; }   /* the toolbar left the stage — the plot fills it */
.sec-empty { padding:24px; color:var(--text-dim); font-size:12px; text-align:center; }

/* ── Section slice controls ───────────────────────────────────────────────── */
/* A 40px toolbar must NEVER scroll vertically.
   Gotcha: per the CSS spec, setting overflow-x to anything other than `visible` forces
   overflow-y from `visible` to `auto`. So the lone `overflow-x:auto` here was silently
   giving us a vertical scrollbar too — and then a feedback loop:
     40px bar, 28px buttons → h-scrollbar appears, steals ~15px of height
     → only ~25px left for 28px buttons → v-scrollbar appears, steals width
     → more horizontal overflow → …
   Two scrollbars inside a toolbar. Only bites when the bar is tight, which is why it
   showed up on the smaller screen. Pin overflow-y explicitly, and make the horizontal
   scrollbar THIN (6px) so it fits alongside the 28px buttons instead of squeezing them.
   (2026-07-14) */
.sec-controls,

.sec-controls::-webkit-scrollbar,
.viewer-shell .viewer-controls::-webkit-scrollbar { height: 6px; }
.sec-controls::-webkit-scrollbar-track,
.viewer-shell .viewer-controls::-webkit-scrollbar-track { background: transparent; }
.sec-controls::-webkit-scrollbar-thumb,
.viewer-shell .viewer-controls::-webkit-scrollbar-thumb {
  background: var(--border-3); border-radius: 3px;
}
.sec-sep { width:1px; height:20px; background:var(--border-2); margin:0 4px; flex:0 0 auto; }
.sec-lbl { display:flex; align-items:center; gap:5px; font-size:11px; color:var(--text-mut); flex:0 0 auto; white-space:nowrap; }
/* Sits straight after the Pins button now that the divider before it is gone — pull it in
   so the space reads as "these belong together", not as a gap where a line used to be. */
.sec-lbl-slice { margin-left: -2px; }
.sec-lbl select { background:var(--bg-input); border:1px solid var(--border-2); color:var(--text-val); font-size:11px; border-radius:5px; padding:2px 4px; }
.sec-lbl input[type=range] { accent-color:var(--gold); }
.sec-posval { font-family:var(--mono); font-size:10px; color:var(--gold); flex:0 0 auto; white-space:nowrap; }

/* Editable slice-line coordinate box */
.sec-posnum { width:88px; background:var(--bg-input); border:1px solid var(--border-2); color:var(--gold);
  font-family:var(--mono); font-size:11px; border-radius:5px; padding:2px 5px; flex:0 0 auto; }
.sec-posnum:focus { outline:none; border-color:var(--gold); }

/* ══════════════════════════════════════════════════════════════════════════════
   RESPONSIVE — smaller screens
   ──────────────────────────────────────────────────────────────────────────────
   The goal (chef, 2026-07-14): the layout should get a little SMALLER, never scroll
   sideways and never clip. Nothing is hidden or removed — the same information, in
   less space.

   The shell is already fluid (grid: key · 1fr · 1fr, with min-width:0 on the panels),
   so only the fixed-size furniture needs to yield:
     • the left panel's width          (--key-w-base)
     • the view-switcher buttons       (padding/type)
     • the top nav's search box + gaps
     • the dock's open height          (it eats the map's vertical space)
   ══════════════════════════════════════════════════════════════════════════════ */

/* Laptops — 1600px and below. */
@media (max-width: 1600px) {
  .viewer-shell { --key-w-base: 280px; }
  .viewer-shell .vw-switcher button { padding: 5px 10px; font-size: 12px; }
  .viewer-shell .vw-topnav { gap: 16px; }
  .viewer-shell #hdr-search { width: 170px; }
}

/* Small laptops — 1366x768 and similar. Tighten harder; the map is the thing that
   must survive, so the dock gives back some height too. */
@media (max-width: 1400px) {
  .viewer-shell { --key-w-base: 258px; }
  /* Shorter dock on a short screen — it OVERLAYS now, so this is the lift + the table's
     height, never a grid-row resize (that was the whole point of the change). */
  .viewer-shell.dock-open { --dock-lift: 150px; }
  .dock-table-wrap { height: 150px; }
  .viewer-shell .vw-switcher button { padding: 5px 8px; font-size: 11.5px; }
  .viewer-shell .vw-topnav { gap: 12px; padding: 0 12px; }
  .viewer-shell #hdr-search { width: 132px; }
  .map-header { gap: 6px; padding: 0 10px; }
  /* Keep the layer control at TWO columns here — a single column is narrower but twice as
     tall, and on a short screen the map's scarce dimension is HEIGHT. Just tighten it. */
  .viewer-shell .leaflet-control-layers-expanded { padding: 7px 10px; font-size: 11.5px; }
  .viewer-shell .leaflet-control-layers-overlays { grid-template-columns: repeat(2, minmax(138px, auto)); column-gap: 12px; }
  .viewer-shell .leaflet-control-layers label { margin: 1px 0; }
}

/* Very narrow. Keep all three panels — the map+document pairing is the point of the
   viewer, and hiding the PDF here would throw away the "read the announcement, see where
   it drilled" workflow. Just keep tightening the chrome. If this ever stops being usable,
   the right move is to collapse the SIDEBAR (it already has a collapse tab built for it),
   not to drop the document. */
@media (max-width: 1150px) {
  .viewer-shell { --key-w-base: 240px; }
}

/* ══════════════════════════════════════════════════════════════════════════════
   DOCK LIFT — bottom-anchored furniture rides up with the open dock
   ──────────────────────────────────────────────────────────────────────────────
   The dock now OVERLAYS the panels (it no longer resizes them — see --dock-lift at the
   top of this file). That means anything anchored to the bottom of a panel would be
   buried underneath it. These all read --dock-lift so they rise by exactly the dock's
   height and stay visible above it — and, crucially, none of this resizes the 3D canvas
   or the Leaflet map, so neither ever re-renders. (2026-07-14)
   ══════════════════════════════════════════════════════════════════════════════ */

/* 3D toolbar + Sections toolbar. The 3D bar is in normal flow at the foot of the panel,
   so it's TRANSLATED up (translate doesn't reflow → no resize). The sections bar is
   already absolute, so its `bottom` just moves. */

/* (.sec-controls is a sibling of the stage now — it rides the dock lift via the shared
   .viewer-controls rule above, not its own `bottom`.) */

/* Map furniture: Leaflet's bottom controls (the layer box), the map key, and the
   clear-highlight chip. */
.viewer-shell .leaflet-bottom {
  bottom: var(--dock-lift);
  transition: bottom .18s ease;
}
.geo-legend {
  bottom: calc(10px + var(--dock-lift));
  transition: bottom .18s ease;
}
.sel-clear-chip {
  bottom: calc(16px + var(--dock-lift));
  transition: bottom .18s ease;
}

/* The 3D grade key (built in viewer_3d.js _updateLegend). Styles live here now so it can
   read --dock-lift; the JS only sets the class. */
.td-grade-key {
  /* BOTTOM-right (chef, 2026-07-15). The x range slider that used to live under the plot is
     gone, so this corner is clear again.
     ⚠️ KNOWN, NOT YET FIXED: it still sits slightly lower on Sections than on 3D. Same
     element, same `bottom`, but the two toolbars have different PARENTS — the 3D bar
     (.viewer-controls) is a sibling of .map-stage, OUTSIDE it, while the Sections bar
     (.sec-controls) is INSIDE it — so this coordinate lands in clear space on 3D and inside
     the toolbar band on Sections. The real fix is to move the Sections bar out of the stage
     so both are siblings; that's the next step, not a CSS offset. */
  position: absolute;
  right: calc(10px + var(--pdf-w));   /* clear of the PDF overlay (2026-07-16) */
  bottom: calc(10px + var(--dock-lift));
  transition: bottom .18s ease;
  /* Translucent everywhere — the scene / plot reads through it. */
  background: rgba(13, 13, 13, .75);
  border: 1px solid var(--border-2);
  border-radius: 6px;
  padding: 10px 14px;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-mut);
  pointer-events: none;
  min-width: 140px;
  z-index: 900;
}

/* ── Logistics card (bottom-right of the map) ─────────────────────────────────
   Was styled by inline hex in viewer_page.js with five off-palette colours: a near-gold
   heading (#e8b34b — neither --accent nor the selected gold), a stray green for "toll"
   (#6f8f6f — the same one we removed from the About link), a brown for status, and two
   ad-hoc greys. All tokens now. Rides --dock-lift so the drill-hole dock can't bury it.
   (2026-07-14) */
.logi-card {
  position: absolute; right: calc(10px + var(--pdf-w)); bottom: calc(10px + var(--dock-lift));
  transition: bottom .18s ease;
  z-index: 800; max-width: 280px;
  background: rgba(13,13,13,.85);
  backdrop-filter: blur(4px);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 12px;
  color: var(--text-val);
}
.logi-card .lc-title {
  font-weight: 600; margin-bottom: 6px;
  color: var(--text);          /* a heading, not a button — NOT gold */
}
.logi-card .lc-row { display: flex; gap: 6px; margin: 2px 0; align-items: baseline; }
.logi-card .lc-name { flex: 1; }
.logi-card .lc-toll { color: var(--pos); }          /* toll-treating = a genuine positive */
.logi-card .lc-status { color: var(--text-mut); }   /* a caveat — quiet, like the chips */
.logi-card .lc-note { margin-top: 6px; color: var(--text-dim); font-size: 11px; }

/* ── 3D grade key (.td-grade-key) — internals ─────────────────────────────────
   Includes the grade-SCHEME picker. The ramp is switchable because the default
   (blue→green→yellow→orange→red "jet") is least readable exactly where it matters most:
   its high-grade end runs yellow→orange→red, the range a red-green colour-blind reader
   (~8% of men) cannot separate. Viridis / Cividis / Mono are safe alternatives.
   The scale is SHARED (grade_colors.js), so this picker repaints the 3D scene, the
   sections, the map's grade layer and the intercept list together. (2026-07-15) */
.td-grade-key .gk-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin-bottom: 6px; color: var(--text); font-weight: 600;
  cursor: pointer; user-select: none;
}
.td-grade-key .gk-caret { color: var(--text-mut); font-size: 10px; transition: transform .15s ease; }
/* Collapsed: caret points right, body gone, no bottom margin under the lone header. */
.td-grade-key.collapsed .gk-head { margin-bottom: 0; }
.td-grade-key.collapsed .gk-caret { transform: rotate(-90deg); }
.td-grade-key.collapsed .gk-body { display: none; }
.td-grade-key .gk-row { display: flex; align-items: center; gap: 6px; margin-bottom: 3px; }
.td-grade-key .gk-sw { width: 14px; height: 12px; border-radius: 2px; display: inline-block; }
.td-grade-key .gk-dot { width: 12px; height: 12px; border-radius: 50%; display: inline-block; }
.td-grade-key .gk-line { width: 12px; height: 2px; background: var(--border-3); display: inline-block; }
.td-grade-key .gk-ramp { display: flex; gap: 6px; height: 104px; margin: 5px 0 6px; }
.td-grade-key .gk-bar { width: 14px; height: 100%; border-radius: 2px; }
.td-grade-key .gk-labels { position: relative; height: 100%; width: 26px; color: var(--text-mut); }
.td-grade-key .gk-sep { border-top: 1px solid var(--border-2); margin: 6px 0; }
.td-grade-key .gk-floor { margin-top: 2px; }

/* SECTIONS ONLY — an opaque strip along the key's bottom edge.
   On the Sections view the key's lower edge overlaps the plot's x-axis TICK LABELS.
   Covering them is fine (chef: you don't need the last couple of northings) — but letting
   them GHOST THROUGH a translucent panel is just noise. A see-through panel can't be
   see-through over the one thing you don't want to see.
   Hard-stop gradient: opaque below --gk-solid, .75 above it. The class is toggled per-view
   in viewer_shell.js, because the key is ONE element shared by 3D and Sections — the 3D
   scene has nothing behind the key to hide, so it stays uniformly translucent there.
   (2026-07-15) */
.td-grade-key.on-sections:not(.collapsed) {
  --gk-solid: 64px;                      /* height of the opaque strip — raise if labels peek */
  background: linear-gradient(
    to top,
    rgba(13, 13, 13, 1) 0, rgba(13, 13, 13, 1) var(--gk-solid),
    rgba(13, 13, 13, .75) var(--gk-solid), rgba(13, 13, 13, .75) 100%
  );
}
/* Collapsed = just the header, sitting nowhere near the x-axis labels, so the opaque strip
   isn't needed and would only look like a stray block. Back to the plain translucent panel. */

/* Range mode: the bands listed with their grade ranges, instead of a gradient bar. */
.td-grade-key .gk-bands { margin: 5px 0 2px; }
.td-grade-key .gk-bands .gk-row { margin-bottom: 2px; }
.td-grade-key .gk-scheme { margin: 4px 0 2px; }
.td-grade-key .gk-ctl { display: flex; align-items: center; gap: 6px; margin-bottom: 4px; }
.td-grade-key .gk-ctl > span { width: 44px; flex: 0 0 auto; color: var(--text-mut); }
.td-grade-key .gk-scheme select {
  flex: 1; min-width: 0;
  background: var(--bg-input); border: 1px solid var(--border-2); color: var(--text-val);
  font-family: var(--mono); font-size: 11px; border-radius: 5px; padding: 3px 5px;
  cursor: pointer;
}
.td-grade-key .gk-scheme select:hover { border-color: var(--gold); }
.td-grade-key .gk-note { margin-top: 3px; font-size: 10px; color: var(--text-dim); line-height: 1.3; }

/* ── North compass (3D view) ──────────────────────────────────────────────────
   A dial with an "N" that orbits as the camera swings. An HTML overlay, not a 3D object:
   a mesh in the scene would be occluded by terrain, scale with zoom, and disappear when you
   fly underground — and a compass has to stay readable from everywhere. Built + driven by
   viewer_3d.js (_initCompass / _updateCompass). (2026-07-15) */
.nav-compass {
  position: absolute;
  top: 12px;
  left: 12px;
  width: 46px;
  height: 46px;
  z-index: 900;
  pointer-events: none;          /* never eats a click meant for the scene */
}
.nav-compass .nc-dial {
  position: absolute; inset: 0;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: rgba(13, 13, 13, .55);
}
/* A tick at the dial's centre, so "N" reads as a bearing FROM somewhere. */
.nav-compass .nc-dial::after {
  content: '';
  position: absolute; top: 50%; left: 50%;
  width: 3px; height: 3px; margin: -1.5px 0 0 -1.5px;
  border-radius: 50%;
  background: var(--text-dim);
}
.nav-compass .nc-n {
  position: absolute;
  top: 50%; left: 50%;
  width: 14px; height: 14px;
  margin: -7px 0 0 -7px;         /* centre it, so the transform orbits about the middle */
  display: flex; align-items: center; justify-content: center;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  color: var(--gold);
  line-height: 1;
}
