/* ═══════════════════════════════════════════════════════════════════
   Filter page — staged Dig pipeline. Colours come from cave.scss.
   ═══════════════════════════════════════════════════════════════════ */

/* ── Masthead ─────────────────────────────────────────────────
   No title here: _layouts/page.html drops the theme's page heading, and the
   header nav already names the room. The hero opens with the lede. */
.dig-hero {
  margin: 0 0 2rem;
}

.dig-lede {
  font-size: 1.2rem;
  line-height: 1.55;
  color: var(--text);
  margin: 0 0 1.4rem;
  max-width: 44em;
}

/* The four stages, stated once up front. Same names, same numbers as the
   fieldsets below, so the page reads as a map of itself. */
.dig-steps {
  list-style: none;
  margin: 0 0 1.1rem;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 0.6rem;
  counter-reset: none;
}
.dig-steps li {
  position: relative;
  padding: 0.7rem 0.85rem;
  background: var(--rock-deep);
  border: 1px solid var(--rock-edge);
  border-radius: 8px;
}
.dig-step-n {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 50%;
  background: var(--rock);
  border: 1px solid var(--rock-lit);
  color: var(--lamp);
  font-size: 0.9rem;
  font-weight: 700;
  margin-bottom: 0.4rem;
}
.dig-step-name {
  display: block;
  font-size: 1.02rem;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 0.15rem;
}
.dig-step-say {
  display: block;
  font-size: 0.92rem;
  line-height: 1.45;
  color: var(--text-dim);
}

.dig-privacy {
  font-size: 0.95rem;
  color: var(--text-dim);
  margin: 0;
  padding-top: 0.9rem;
  border-top: 1px solid var(--rock-edge);
}

/* ── Claim bar ───────────────────────────────────────────────── */
.claim-bar {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
  padding: 0.5rem 0.75rem;
  margin-bottom: 0.4rem;
  background: var(--rock-deep);
  border: 1px solid var(--rock-edge);
  border-radius: 8px;
}
.claim-pick {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.9rem;
  color: var(--text-dim);
}
.claim-pick select {
  min-width: 12rem;
  max-width: 100%;
  padding: 0.35rem 0.5rem;
  font-size: 0.92rem;
  border: 1px solid var(--rock-edge);
  border-radius: 4px;
  background: var(--rock);
  color: var(--text);
}
.claim-btn {
  background: none;
  border: 1px solid var(--rock-lit);
  color: var(--text-dim);
  padding: 0.35rem 0.8rem;
  border-radius: 4px;
  font-size: 0.9rem;
  cursor: pointer;
}
.claim-btn:hover:not(:disabled) {
  border-color: var(--lamp);
  color: var(--lamp);
}
.claim-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.claim-btn-danger:hover:not(:disabled) {
  border-color: var(--ember);
  color: var(--ember);
}
.claim-status {
  font-size: 0.88rem;
  color: var(--moss);
  margin-left: auto;
}
.claim-hint {
  margin-bottom: 1.25rem;
}

/* ── Shared fieldset chrome ──────────────────────────────────── */
fieldset {
  border: 1px solid var(--rock-edge);
  border-radius: 8px;
  padding: 1rem 1.25rem;
  margin-bottom: 1.5rem;
  background: var(--rock-deep);
  /* Fieldsets default to min-width:auto (min-content), which stretches the
     box to fit unshrinkable content like the assay grid instead of letting
     .assay-scroll's overflow-x:auto contain it. */
  min-width: 0;
}

fieldset legend {
  font-weight: 700;
  font-size: 1.2rem;
  color: var(--text);
  padding: 0 0.4rem;
}

.hint {
  font-size: 0.95rem;
  color: var(--text-faint);
  line-height: 1.5;
  margin: 0 0 0.5rem;
}
.hint code {
  font-size: 0.95em;
  background: var(--rock);
  border: 1px solid var(--rock-edge);
  padding: 0.05em 0.35em;
  border-radius: 3px;
  color: var(--text-dim);
}

.wip {
  color: var(--pyrite);
  font-size: 0.8rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.sub {
  font-size: 0.88rem;
  color: var(--text-faint);
  font-weight: 400;
}

/* ── Button bar ───────────────────────────────────────────────── */
.button-bar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0.5rem 0;
}

.button-bar button {
  padding: 0.65rem 1.4rem;
  font-size: 1.02rem;
  font-weight: 600;
  background: var(--rock);
  color: var(--text);
  border: 1px solid var(--rock-lit);
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}

.button-bar button:hover:not(:disabled) {
  background: var(--rock-lit);
}

/* Whichever stage button is live is the one thing to press next, so it
   carries the ore colour and the others stay rock. */
#haul-btn:not(:disabled) {
  background: var(--gold);
  color: #221a00;
  border-color: var(--gold);
  box-shadow: 0 0 0 1px rgba(245, 179, 1, 0.35),
              0 6px 22px -8px rgba(245, 179, 1, 0.55);
}
#haul-btn:not(:disabled):hover {
  background: #ffc730;
}

/* Already hauled: still clickable (the scout can change under it), but it is
   no longer the next thing to press, so it drops back out of the ore colour. */
#haul-btn.is-done {
  background: var(--rock);
  color: var(--moss);
  border-color: var(--moss);
  box-shadow: none;
}
#haul-btn.is-done:hover {
  background: var(--rock-lit);
}

.button-bar button:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* ── Progress ─────────────────────────────────────────────────── */
.progress-wrap {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0.5rem 0;
}

progress {
  flex: 0 0 260px;
  height: 8px;
  border-radius: 4px;
  overflow: hidden;
  accent-color: var(--lamp);
  border: none;
  background: var(--rock);
}
progress::-webkit-progress-bar {
  background: var(--rock);
  border-radius: 4px;
}
progress::-webkit-progress-value {
  background: var(--lamp);
  border-radius: 4px;
}
progress::-moz-progress-bar {
  background: var(--lamp);
  border-radius: 4px;
}

.progress-label {
  font-size: 0.82rem;
  color: var(--text-dim);
}

/* ── The haul train ───────────────────────────────────────────────
   Stage 1 replaces the bar with a pixel-art mine train (drawn in
   filter.js). It stacks: track above, count below. The canvas is sized
   by the script in whole art pixels, so it only needs the width of the
   column to measure against and a promise not to smooth it. */
.train-wrap {
  flex-direction: column;
  align-items: flex-start;
  gap: 0.3rem;
}

.haul-train {
  width: 100%;      /* measured before the script fixes a pixel-exact width */
  max-width: 100%;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
}

/* ── Stage status ─────────────────────────────────────────────── */
.stage-status {
  font-size: 0.85rem;
  color: var(--text-dim);
}

.stage-done {
  font-size: 0.85rem;
  color: var(--moss);
  padding: 0.4rem 0;
}
.stage-done code {
  font-size: 0.95em;
  background: var(--rock);
  border: 1px solid var(--rock-edge);
  padding: 0.05em 0.35em;
  border-radius: 3px;
  color: var(--text-dim);
}

/* ── Scout settings, inside stage 1 ───────────────────────────── */
.scout-block {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  padding: 0.85rem 1rem;
  margin-bottom: 1rem;
  background: var(--rock);
  border: 1px solid var(--rock-edge);
  border-radius: 6px;
}

.field-label {
  display: block;
  font-size: 0.92rem;
  color: var(--text-dim);
  margin-bottom: 0.4rem;
}

/* Category chips: the list you are scouting, one removable chip each. */
.cat-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 0.5rem;
}
.cat-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.25rem 0.35rem 0.25rem 0.6rem;
  font-size: 0.92rem;
  color: var(--text);
  background: var(--rock-deep);
  border: 1px solid var(--rock-lit);
  border-radius: 999px;
}
.cat-chip-code {
  font-variant-numeric: tabular-nums;
}
.cat-chip-x {
  background: none;
  border: none;
  color: var(--text-faint);
  font-size: 1.05rem;
  line-height: 1;
  padding: 0 0.15rem;
  cursor: pointer;
}
.cat-chip-x:hover {
  color: var(--ember);
}
.cat-empty {
  font-size: 0.92rem;
  color: var(--text-faint);
  font-style: italic;
}

.cat-add {
  max-width: 26rem;
  width: 100%;
  padding: 0.45rem 0.6rem;
  font-size: 0.95rem;
  border: 1px dashed var(--rock-lit);
  border-radius: 4px;
  background: var(--rock-deep);
  color: var(--text-dim);
  cursor: pointer;
}
.cat-add:hover {
  border-color: var(--lamp);
  color: var(--lamp);
}

/* ── Scout grid ───────────────────────────────────────────────── */
.role-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 0.75rem;
}
/* Lookback + max results are the small pair under the categories. */
.scout-grid {
  grid-template-columns: repeat(auto-fit, minmax(160px, 220px));
}
.role-grid label {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-size: 0.92rem;
  color: var(--text-dim);
}
.role-grid input,
.role-grid select {
  padding: 0.5rem 0.65rem;
  font-size: 0.98rem;
  border: 1px solid var(--rock-edge);
  border-radius: 4px;
  background: var(--rock);
  color: var(--text);
}
.role-grid input[type="number"] {
  max-width: 8em;
}

/* ── Stage 2: Touchstones & core samples ──────────────────────── */
.group-label {
  font-weight: 700;
  font-size: 1.02rem;
  color: var(--text);
  margin-bottom: 0.5rem;
}

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

/* Touchstone / core sample row */
.touchstone-row,
.core-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0;
}

.touchstone-row input[type="text"],
.core-row input[type="text"] {
  flex: 1 1 auto;
  padding: 0.45rem 0.6rem;
  font-size: 0.98rem;
  border: 1px solid var(--rock-edge);
  border-radius: 4px;
  background: var(--rock);
  color: var(--text);
}

.touchstone-row .row-remove,
.core-row .row-remove {
  flex: 0 0 auto;
  background: none;
  border: none;
  color: var(--text-faint);
  cursor: pointer;
  font-size: 1.1rem;
  padding: 0 0.3rem;
}
.touchstone-row .row-remove:hover,
.core-row .row-remove:hover {
  color: var(--ember);
}

.core-row .row-status {
  flex: 0 0 auto;
  font-size: 0.85rem;
  color: var(--text-faint);
  font-style: italic;
  max-width: 12em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.add-row-btn {
  background: none;
  border: 1px dashed var(--rock-lit);
  color: var(--text-dim);
  padding: 0.35rem 0.8rem;
  border-radius: 4px;
  font-size: 0.9rem;
  cursor: pointer;
  margin-top: 0.25rem;
}
.add-row-btn:hover:not(:disabled) {
  border-color: var(--lamp);
  color: var(--lamp);
}
.add-row-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* The rush (inactive) */
.inactive-group {
  opacity: 0.5;
}
.inactive-group .group-label {
  color: var(--pyrite);
}
.rush-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.4rem 0.75rem;
  background: var(--rock);
  border: 1px solid var(--rock-edge);
  border-radius: 4px;
}
.rush-name {
  flex: 1 1 auto;
  font-size: 0.9rem;
  color: var(--text-dim);
}
.rush-unavailable {
  font-size: 0.78rem;
  color: var(--pyrite-dim);
  font-style: italic;
}
.rush-weight {
  font-size: 0.85rem;
  color: var(--text-faint);
}

/* ── The train ─────────────────────────────────────────────────── */
#wagon-panel {
  margin-top: 0.75rem;
}

.wagon-header {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
  margin-bottom: 0.5rem;
}

.wagon-title {
  font-weight: 700;
  font-size: 1.02rem;
  color: var(--text);
}

/* Grows into spare room but yields it first — the controls to its right
   must never be squeezed off the row. */
.wagon-stats {
  font-size: 0.88rem;
  color: var(--text-faint);
  flex: 1 1 auto;
  min-width: 0;
  white-space: nowrap;
}
.wagon-stats strong {
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

.wagon-expand-btn {
  background: none;
  border: 1px solid var(--rock-edge);
  color: var(--text-dim);
  padding: 0.25rem 0.65rem;
  border-radius: 4px;
  font-size: 0.88rem;
  cursor: pointer;
}
.wagon-expand-btn:hover {
  border-color: var(--lamp);
  color: var(--lamp);
}

/* Same shape as Expand — it sits beside it and does the same kind of job,
   one press for one result, so it should not look like a bigger commitment
   than it is. */
.wagon-name-btn {
  background: none;
  border: 1px solid var(--rock-edge);
  color: var(--text-dim);
  padding: 0.25rem 0.65rem;
  border-radius: 4px;
  font-size: 0.88rem;
  cursor: pointer;
}
.wagon-name-btn:hover:not(:disabled) {
  border-color: var(--lamp);
  color: var(--lamp);
}
.wagon-name-btn:disabled {
  opacity: 0.55;
  cursor: progress;
}

/* Empty until something is worth saying, and it takes no room when empty —
   a permanently reserved status line reads as a permanent warning. */
.wagon-name-status {
  font-size: 0.82rem;
  color: var(--text-faint);
  margin: -0.2rem 0 0.45rem;
}
.wagon-name-status:empty {
  display: none;
}
.wagon-name-status.is-error {
  color: var(--warn, #c08a5a);
}

.toggle-label {
  font-size: 0.88rem;
  color: var(--text-dim);
  display: flex;
  align-items: center;
  gap: 0.3rem;
  cursor: pointer;
}
.toggle-label input[type="checkbox"] {
  accent-color: var(--lamp);
}

.wagon-thresh-label {
  font-size: 0.88rem;
  color: var(--text-dim);
  display: flex;
  align-items: center;
  gap: 0.35rem;
  flex: none;
}
.wagon-thresh-label input[type="range"] {
  accent-color: var(--lamp);
  width: 90px;
}
.wagon-thresh-label #wagon-thresh-value {
  font-variant-numeric: tabular-nums;
  color: var(--text-faint);
  min-width: 2.5em;
}

/* ── Train strip ──────────────────────────────────────────────────
   Wagon width is flex-grow = its stone count against a zero basis, so the
   row reads as the real ratio between wagons and re-forms as the
   threshold moves. Nothing here may set a min-width: one wide wagon
   crowding a thin one is the point. */
.train-strip {
  display: flex;
  align-items: stretch;
  gap: 2px;
  height: 26px;
  margin-bottom: 0.6rem;
  border: 1px solid var(--rock-edge);
  border-radius: 4px;
  background: var(--rock);
  padding: 3px;
  overflow: hidden;
}
.train-strip:empty {
  display: none;
}

/* The engine at the head — fixed width, so it never eats a wagon's share. */
.train-loco {
  flex: 0 0 14px;
  border-radius: 2px 0 0 2px;
  background:
    linear-gradient(to bottom, var(--rock-edge) 0 4px, transparent 4px 100%) 3px 0 / 5px 100% no-repeat,
    var(--text-faint);
  opacity: 0.65;
}

.train-wagon {
  flex: 1 1 0;
  min-width: 0;
  border: none;
  border-radius: 2px;
  padding: 0;
  cursor: pointer;
  overflow: hidden;
  font: inherit;
  color: var(--rock);
  display: flex;
  align-items: center;
  justify-content: center;
}
.train-wagon:hover {
  outline: 1px solid var(--lamp);
  outline-offset: -1px;
}
/* Stones that joined no wagon ride a flatcar: same scale, less claim. */
.train-wagon.is-lone {
  opacity: 0.5;
}

.train-wagon-n {
  font-size: 0.72rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  /* Clipped rather than ellipsised — a wagon too thin for its own count
     shows nothing, which is honest, instead of a lone "…". */
  overflow: hidden;
}

.wagon-tooltip .tt-central {
  color: var(--text-faint);
  font-size: 0.78rem;
}

/* Above the central title and lighter than the counts: the gloss explains the
   name, the central title is evidence for it. */
.wagon-tooltip .tt-gloss {
  color: var(--text-dim);
  font-size: 0.8rem;
}

.wagon-canvas-wrap {
  display: inline-block;
  max-width: 100%;
  overflow-x: auto;
  border: 1px solid var(--rock-edge);
  border-radius: 4px;
  background: var(--rock);
  vertical-align: top;
}

.wagon-canvas-wrap canvas {
  image-rendering: pixelated;
  image-rendering: crisp-edges;
  display: block;
}

/* ── Matrix ↔ graph switch ────────────────────────────────────── */
.wagon-view-switch {
  display: inline-flex;
  border: 1px solid var(--rock-edge);
  border-radius: 4px;
  overflow: hidden;
  flex: none;
}

.wagon-view-btn {
  background: none;
  border: none;
  color: var(--text-faint);
  font-size: 0.86rem;
  padding: 0.25rem 0.7rem;
  cursor: pointer;
}
.wagon-view-btn:hover {
  color: var(--lamp);
}
.wagon-view-btn.is-active {
  background: var(--rock);
  color: var(--gold);
}

/* ── Wagon graph ───────────────────────────────────────────────── */
.wagon-graph-wrap {
  border: 1px solid var(--rock-edge);
  border-radius: 4px;
  background: var(--rock);
  overflow: hidden;
}

.wagon-graph-wrap canvas {
  display: block;
  touch-action: none;
}

.wagon-graph-hint {
  font-size: 0.82rem;
  color: var(--text-faint);
  padding: 0.25rem 0.5rem;
  border-top: 1px solid var(--rock-edge);
}

.wagon-readout {
  padding: 0.3rem 0;
  font-size: 0.9rem;
  color: var(--text-dim);
  min-height: 1.3em;
}
.wagon-readout a,
.wagon-modal-readout a {
  color: var(--lamp);
}
.wagon-readout.pinned,
.wagon-modal-readout.pinned {
  border-left: 2px solid var(--gold);
  padding-left: 0.5rem;
}
.wagon-paydirt-tag {
  color: var(--gold);
  font-weight: 600;
}
.wagon-pin-hint {
  color: var(--text-faint);
  font-size: 0.82rem;
}

/* ── Wagon modal ───────────────────────────────────────────────── */
.wagon-modal {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
}

.wagon-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.7);
}

.wagon-modal-content {
  position: relative;
  background: var(--rock-deep);
  border: 1px solid var(--rock-lit);
  border-radius: 8px;
  padding: 1rem;
  max-width: 90vw;
  max-height: 90vh;
  overflow: auto;
}

.wagon-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.5rem;
}

.wagon-modal-close {
  background: none;
  border: none;
  color: var(--text-dim);
  font-size: 1.4rem;
  cursor: pointer;
  padding: 0 0.3rem;
}
.wagon-modal-close:hover {
  color: var(--ember);
}

.wagon-modal-content canvas {
  image-rendering: pixelated;
  image-rendering: crisp-edges;
  display: block;
}

/* The graph is drawn with real vectors — keep it smooth */
#wagon-modal-graph-canvas {
  image-rendering: auto;
  background: var(--rock);
  border-radius: 4px;
}

.wagon-modal-readout {
  margin-top: 0.5rem;
  font-size: 0.92rem;
  color: var(--text-dim);
  min-height: 1.3em;
}

/* ── Assay matrix ─────────────────────────────────────────────── */
.assay-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.5rem;
}

.assay-stats {
  font-size: 0.92rem;
  color: var(--text-dim);
}

.assay-controls {
  display: flex;
  align-items: center;
  gap: 1rem;
}
.assay-controls label {
  font-size: 0.92rem;
  color: var(--text-dim);
}
.assay-controls input[type="number"] {
  width: 4em;
  padding: 0.35rem 0.45rem;
  font-size: 0.92rem;
  border: 1px solid var(--rock-edge);
  border-radius: 4px;
  background: var(--rock);
  color: var(--text);
  text-align: right;
  font-variant-numeric: tabular-nums;
  margin-left: 0.25rem;
}

/* Matrix wrapper: rail + scrollable grid */
#assay-matrix-wrap {
  display: flex;
  border: 1px solid var(--rock-edge);
  border-radius: 4px;
  background: var(--rock);
  overflow: hidden;
}

.assay-rail {
  flex: 0 0 auto;
  min-width: 190px;
  max-width: 250px;
  border-right: 1px solid var(--rock-edge);
  background: var(--rock-deep);
}

.assay-scroll {
  flex: 1 1 auto;
  /* min-width:0 or the grid's intrinsic width blows the flex item past the
     fieldset instead of scrolling inside it */
  min-width: 0;
  overflow-x: auto;
  position: relative;
  /* Room for the horizontal scrollbar below the grid, so an overlay
     scrollbar (macOS/mobile) doesn't sit on top of the grade row. */
  padding-bottom: 14px;
}

#assay-column-titles {
  display: flex;
  width: max-content;
  border-bottom: 1px solid var(--rock-edge);
  background: var(--rock-deep);
}
#assay-column-titles .col-title {
  flex: 0 0 auto;
  padding: 0.25rem 0;
  font-size: 0.75rem;
  color: var(--text-faint);
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#assay-column-titles .col-title.paydirt {
  color: var(--text-dim);
  font-weight: 600;
}
/* The gate's edge: one line down the last column that would ship. Right side,
   because the columns run best-first — everything left of it is in. */
#assay-column-titles .col-title.gate-cut {
  border-right: 2px solid var(--lamp);
}

/* ── The gate ─────────────────────────────────────────────────────
   Sits between the assay's controls and the matrix, because it is a claim
   about the matrix below it: everything left of the cut line would ship. */
.gate-block {
  margin: 0.5rem 0 0.9rem;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--rock-edge);
  border-radius: 6px;
  background: var(--rock);
}
.gate-main {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  flex-wrap: wrap;
}
.gate-label {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.92rem;
  color: var(--text-dim);
  flex: none;
}
.gate-label input[type="range"] {
  accent-color: var(--lamp);
  width: 140px;
}
.gate-load-value {
  font-variant-numeric: tabular-nums;
  color: var(--text-faint);
  min-width: 5.5em;
}
/* The thin-night decision sits beside the load, not under Advanced: it is the
   other half of the same question, and it changes what arrives on the mornings
   a reader is most likely to give up on the feed. */
.gate-strict-label {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.88rem;
  color: var(--text-dim);
  flex: none;
}
.gate-strict-label input[type="checkbox"] {
  accent-color: var(--lamp);
}
.gate-readout {
  font-size: 0.9rem;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
/* An empty feed is a legitimate result, not a fault — dim, never red. */
.gate-readout.is-empty {
  color: var(--text-dim);
}
/* The three-stance pick: one row of small gems, not a stack of full-width
   rows. Each gem is the tier it picks — diamond strict, copper loose — with
   the name as a hover title rather than printed text, so it stays a row of
   controls the width of a slider handle, not a card. */
.gate-presets {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0.5rem 0;
}
.gate-preset {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.8rem;
  height: 1.8rem;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 50%;
  background: none;
  cursor: pointer;
}
.gate-preset:hover {
  border-color: var(--rock-edge);
  background: var(--rock-lit);
}
.gate-preset.is-active {
  border-color: var(--lamp);
  background: var(--rock-lit);
}
.gate-gem {
  flex: none;
  width: 8px;
  height: 8px;
  transform: rotate(45deg);
  border: 1px solid rgba(0, 0, 0, 0.35);
}
.gate-gem-diamond {
  background: linear-gradient(135deg, #eaf8ff, #9fd8ff);
  box-shadow: 0 0 4px rgba(159, 216, 255, 0.65);
}
.gate-gem-gold {
  background: linear-gradient(135deg, #fff2b8, #d4a017);
  box-shadow: 0 0 4px rgba(212, 160, 23, 0.55);
}
.gate-gem-copper {
  background: linear-gradient(135deg, #dd9a6c, #8a4b2c);
  box-shadow: 0 0 4px rgba(138, 75, 44, 0.5);
}

.assay-grid {
  --assay-cols: 1;
  display: grid;
  grid-template-columns: repeat(var(--assay-cols), 1fr);
  width: max-content;
}

/* Rail rows */
.rail-row {
  display: flex;
  align-items: center;
  padding: 0 0.5rem;
  font-size: 0.88rem;
  /* tight so a row still fits the forced cell height without clipping */
  line-height: 1;
  color: var(--text-dim);
  border-bottom: 1px solid var(--rock-edge);
  box-sizing: border-box;
  overflow: hidden;
}
/* Corner cell above the rail — mirrors the column-number bar */
.rail-row.rail-head-spacer {
  padding: 0;
  background: var(--rock-deep);
  border-bottom: 1px solid var(--rock-edge);
  box-sizing: border-box;
}
.rail-row.group-header {
  font-size: 0.76rem;
  color: var(--text-faint);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 600;
  padding: 0.3rem 0.5rem;
  background: var(--rock);
  border-bottom: 1px solid var(--rock-lit);
}
.rail-row .rail-label {
  flex: 1 1 auto;
  min-width: 3.5em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rail-row .rail-weight {
  flex: 0 0 auto;
  font-variant-numeric: tabular-nums;
  color: var(--text-faint);
  margin-left: 0.4rem;
  width: 1.8em;
  text-align: right;
}
.rail-row .rail-weight-slider {
  flex: 0 0 40px;
  width: 40px;
  max-width: 40px;
  box-sizing: border-box;
  margin-left: 0.3rem;
  height: 8px;
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
  cursor: pointer;
}
.rail-row .rail-weight-slider::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 2px;
  background: var(--rock-edge);
}
.rail-row .rail-weight-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 10px;
  height: 10px;
  margin-top: -3px;
  border-radius: 50%;
  background: var(--lamp);
  border: none;
}
.rail-row .rail-weight-slider::-moz-range-track {
  height: 4px;
  border-radius: 2px;
  background: var(--rock-edge);
}
.rail-row .rail-weight-slider::-moz-range-thumb {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--lamp);
  border: none;
}
.rail-row.grade-row {
  border-bottom: 3px solid var(--gold);
}
.rail-row.grade-row .rail-label {
  font-weight: 700;
  color: var(--text);
}
.rail-row.grade-row .rail-weight {
  color: var(--gold);
}

/* Matrix cells */
.matrix-row {
  display: contents;
}

.matrix-cell {
  aspect-ratio: 1;
  cursor: pointer;
  transition: box-shadow 0.15s;
  /* cell colour set via style attribute as --ore-N or --lamp-N */
  background: var(--rock-deep);
}
.matrix-cell.null-cell {
  background: var(--rock-deep);
  opacity: 0.3;
  cursor: default;
}
.matrix-cell:hover,
.matrix-cell:focus {
  box-shadow: inset 0 0 0 1px var(--rock-lit);
  z-index: 1;
  position: relative;
}
.matrix-cell.null-cell:hover {
  box-shadow: none;
}

/* Grade row cells use lamp ramp */
.matrix-cell.grade-cell {
  /* override background in JS via style */
}

/* Pay dirt column highlight — inset ring so inline background isn't overridden */
.matrix-cell.paydirt-col {
  box-shadow: inset 0 0 0 2px var(--gold);
}
.matrix-cell.paydirt-col:hover,
.matrix-cell.paydirt-col:focus {
  box-shadow: inset 0 0 0 1px var(--rock-lit), inset 0 0 0 3px var(--gold);
}

/* ── Cell tooltip ─────────────────────────────────────────────── */
.cell-tooltip {
  position: fixed;
  z-index: 500;
  background: var(--rock);
  border: 1px solid var(--rock-lit);
  border-radius: 6px;
  padding: 0.6rem 0.8rem;
  font-size: 0.9rem;
  color: var(--text-dim);
  pointer-events: none;
  max-width: 320px;
}
/* Pinned by a click — must take pointer events so the arXiv link is clickable */
.cell-tooltip.pinned {
  pointer-events: auto;
  border-color: var(--gold);
}
.cell-tooltip a {
  color: var(--lamp);
}
.cell-tooltip .tt-pin-hint {
  font-size: 0.78rem;
  color: var(--text-faint);
  margin-top: 0.2rem;
}
.cell-tooltip .tt-value {
  font-weight: 700;
  font-size: 1.2rem;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.cell-tooltip .tt-row {
  font-size: 0.82rem;
  color: var(--text-faint);
}
.cell-tooltip .tt-title {
  font-size: 0.88rem;
  color: var(--text-dim);
  margin-top: 0.25rem;
  line-height: 1.3;
}

.wagon-tooltip {
  max-width: 22rem;
}
.wagon-tooltip .tt-title a {
  color: var(--text-dim);
  text-decoration: none;
}
/* Only the pinned tooltip can be reached, so only it advertises the link. */
.wagon-tooltip.pinned {
  border-color: var(--gold);
}
.wagon-tooltip.pinned .tt-title a {
  color: var(--lamp);
  text-decoration: underline;
}
.wagon-tooltip .tt-authors {
  margin-top: 0.2rem;
  font-size: 0.76rem;
  line-height: 1.3;
  color: var(--text-faint);
}

.wagon-tooltip .tt-row {
  margin-top: 0.25rem;
  line-height: 1.35;
}

/* ── Wagon tables — one per wagon ────────────────────────────────── */
.wagon-table-block {
  margin-bottom: 1.1rem;
}

.wagon-table-head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.3rem;
}

.wagon-swatch {
  width: 0.75rem;
  height: 0.75rem;
  border-radius: 2px;
  flex: none;
}

.wagon-table-name {
  font-weight: 700;
  font-size: 0.94rem;
  color: var(--text);
}

.wagon-table-count {
  font-size: 0.84rem;
  color: var(--text-faint);
}

/* Takes the rest of the row and truncates rather than wrapping the heading
   onto a second line — the name and count must stay on one line with the
   swatch. */
.wagon-table-gloss {
  font-size: 0.82rem;
  color: var(--text-faint);
  font-style: italic;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.wagon-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.86rem;
}

.wagon-table th {
  text-align: left;
  font-weight: 600;
  color: var(--text-faint);
  border-bottom: 1px solid var(--rock-edge);
  padding: 0.25rem 0.5rem 0.25rem 0;
  white-space: nowrap;
}

.wagon-table td {
  color: var(--text-dim);
  border-bottom: 1px solid var(--rock-edge);
  padding: 0.3rem 0.5rem 0.3rem 0;
  vertical-align: top;
  line-height: 1.35;
}

.wagon-table td.num {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.wagon-table .wagon-td-cat {
  color: var(--text-faint);
  white-space: nowrap;
}

.wagon-table a {
  color: var(--lamp);
  white-space: nowrap;
}

/* Titles take the width that is left, one line each, clipped where they run
   out. The full title is in the link's tooltip. */
.wagon-table .wagon-td-title-cell {
  width: 55%;
  max-width: 0;   /* lets the percentage win over the text's own width */
}

.wagon-table a.wagon-td-title {
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 0.9rem;
  color: var(--text-dim);
  text-decoration: none;
}

/* Authors: one line, scrollable when a collaboration runs past the column.
   The cell only sizes the column — a td is a table-cell box and ignores
   overflow, so the scrolling happens in the div inside it. Full list in the
   cell's tooltip. */
.wagon-table .wagon-td-authors {
  width: 22%;
  max-width: 0;
  overflow: hidden;
  font-size: 0.8rem;
  color: var(--text-faint);
}
.wagon-table .wagon-authors-scroll {
  max-width: 100%;
  white-space: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
}
.wagon-table .wagon-authors-scroll::-webkit-scrollbar { height: 5px; }
.wagon-table .wagon-authors-scroll::-webkit-scrollbar-thumb {
  background: var(--rock-lit);
  border-radius: 3px;
}
.wagon-table a.wagon-td-title:hover {
  color: var(--lamp);
  text-decoration: underline;
}

.wagon-table-wrap {
  max-height: 30rem;
  overflow-y: auto;
}

/* ── Scale legends ────────────────────────────────────────────── */
.assay-legends {
  display: flex;
  gap: 2rem;
  margin-top: 0.75rem;
  padding: 0.5rem 0;
}

.scale-legend {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.88rem;
  color: var(--text-faint);
}

.scale-legend .legend-label {
  font-weight: 600;
  color: var(--text-dim);
  width: 6em;
}

.scale-bar {
  width: 120px;
  height: 10px;
  border-radius: 2px;
}

.ore-scale {
  background: linear-gradient(to right,
    var(--ore-0), var(--ore-1), var(--ore-2), var(--ore-3),
    var(--ore-4), var(--ore-5), var(--ore-6), var(--ore-7));
}

.lamp-scale {
  background: linear-gradient(to right,
    var(--lamp-0), var(--lamp-1), var(--lamp-2), var(--lamp-3),
    var(--lamp-4), var(--lamp-5), var(--lamp-6), var(--lamp-7),
    var(--lamp-8), var(--lamp-9), var(--lamp-10));
}

/* ── Table view ───────────────────────────────────────────────── */
#assay-table-wrap {
  margin-top: 1rem;
}

#assay-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.92rem;
  color: var(--text);
}

#assay-table th,
#assay-table td {
  padding: 0.35rem 0.5rem;
  border-bottom: 1px solid var(--rock-edge);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

#assay-table th:first-child,
#assay-table td:first-child {
  text-align: left;
}

#assay-table th {
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-faint);
  border-bottom: 2px solid var(--rock-lit);
}

#assay-table tr.paydirt-row td {
  background: rgba(245, 179, 1, 0.06);
}
/* Same edge as the matrix's, laid flat: rows run best-first, so the line goes
   under the last one that ships. */
#assay-table tr.gate-cut-row td {
  border-bottom: 2px solid var(--lamp);
}

/* ── Responsive ─────────────────────────────────────────────── */
@media (max-width: 768px) {
  .role-grid {
    grid-template-columns: 1fr 1fr;
  }
  .assay-rail {
    min-width: 100px;
    max-width: 130px;
  }
  .assay-legends {
    flex-direction: column;
    gap: 0.5rem;
  }
}

/* ── Cave walls ───────────────────────────────────────────────
   The gutter rock moved to assets/style.css, which every room loads,
   so Stockpile, Haul and Details get walls too — each pointing the
   same rules at its own tile via --cave-wall-art. What stays here is
   the one rule that is about this page and not about walls. */

/* The page content sits above the walls, so a mis-estimated gutter
   dims nothing and covers no text. */
#app {
  position: relative;
  z-index: 1;
}

/* Presets — solid where "+ Add touchstone" is dashed. The dashed border means
   "an empty row appears here"; a preset arrives already filled, so it reads as
   a thing you take rather than a slot you fill. */
.preset-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0.3rem 0 0.2rem;
}
/* One line each. The blurb lives in the hint below, so four chips read as one
   row of choices rather than four paragraphs. */
.preset-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.35rem 0.75rem;
  background: none;
  border: 1px solid var(--rock-lit);
  border-radius: 4px;
  color: var(--text-dim);
  font: inherit;
  font-size: 0.95rem;
  text-align: left;
  cursor: pointer;
}
.preset-btn:hover:not(:disabled) {
  border-color: var(--lamp);
  color: var(--lamp);
}
.preset-btn:disabled {
  opacity: 0.5;
  cursor: progress;
}
/* The selected chip is lit, not merely outlined — at a glance the question is
   "which one is on", and only a fill answers that from across the page. */
.preset-btn.is-active {
  border-color: var(--lamp);
  color: var(--lamp);
  background: color-mix(in srgb, var(--lamp) 12%, transparent);
}
.preset-name {
  font-size: inherit;
}
/* ✓ when clean, "edited" once a row loses the preset's provenance. Empty
   otherwise, and it holds no width then. */
.preset-state:empty {
  display: none;
}
.preset-state {
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  opacity: 0.85;
}
.preset-btn.is-edited .preset-state {
  font-style: italic;
}
/* Selected preset's blurb, printed once above the standing hint. */
.preset-blurb-line {
  color: var(--text-dim);
}

/* ── The feeds menu ────────────────────────────────────────────────────
   One control for the catalogue. Anchored to the group label so it cannot
   push the chip row around, whatever the catalogue grows to. */
.label-with-action {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
}
.feeds-wrap {
  position: relative;
  font-weight: 400;
}
.feeds-btn {
  padding: 0.4rem 0.9rem;
  background: none;
  border: 1px solid var(--rock-lit);
  border-radius: 4px;
  color: var(--text-dim);
  font: inherit;
  font-size: 1rem;
  letter-spacing: 0.04em;
  cursor: pointer;
}
.feeds-btn:hover,
.feeds-btn[aria-expanded="true"] {
  border-color: var(--lamp);
  color: var(--lamp);
}
.feeds-menu {
  position: absolute;
  top: calc(100% + 0.3rem);
  right: 0;
  z-index: 20;
  min-width: 16rem;
  padding: 0.25rem;
  background: var(--rock-deep);
  border: 1px solid var(--rock-lit);
  border-radius: 4px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45);
}
.feeds-item {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 0.35rem 0.5rem;
  border-radius: 3px;
  color: var(--text-dim);
  font-size: 0.9rem;
  text-decoration: none;
}
a.feeds-item:hover {
  background: var(--rock);
  color: var(--lamp);
}
/* A feed that has not been built yet is shown and not offered — the link that
   would 404 is the one that teaches people the feeds are broken. */
.feeds-item.is-pending {
  opacity: 0.55;
  cursor: default;
}
.feeds-note {
  font-size: 0.78rem;
  color: var(--text-faint);
  white-space: nowrap;
}

/* ── Setup, at the top of Stage 2 ─────────────────────────────────
   Loading a setup belongs to the same question the rows below it answer —
   what are we filtering for — so it sits inside Stage 2, above them.

   This was a two-column grid: sharpening the pick on the left, loading a setup
   on the right, side by side because the 32 MB download and the reading were
   independent and concurrent. The pick is hosted now, there is no download to
   read alongside, and one column is left. The rule and the grid stay rather
   than being unwound into plain flow, because the second column is the obvious
   place for whatever joins this next.

   Already inside a fieldset, so the columns are ruled, not boxed. A panel
   inside a panel is the thing that made this look bolted on. */
.setup-cols {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
  align-items: stretch;
}
.setup-col { min-width: 0; }
.setup-col + .setup-col {
  padding-left: 1.25rem;
  border-left: 1px solid var(--rock-edge);
}
.setup-group + .setup-group {
  margin-top: 0.9rem;
  padding-top: 0.8rem;
  border-top: 1px solid var(--rock-edge);
}
.setup-col .claim-bar {
  padding: 0;
  margin: 0;
  background: none;
  border: none;
}
.setup-col .claim-hint { margin-bottom: 0; }
.setup-col .claim-status {
  margin-left: 0;
  display: block;
  min-height: 1.2em;
}

/* The overflow. Delete, Export and Import are rare and Delete is destructive;
   six equal buttons in one row is what made the bar read as clutter. */
.claim-more { display: inline-block; position: relative; }
.claim-more > summary {
  list-style: none;
  cursor: pointer;
  border: 1px solid var(--rock-lit);
  color: var(--text-dim);
  padding: 0.4rem 0.8rem;
  border-radius: 4px;
  font-size: 0.9rem;
}
.claim-more > summary::-webkit-details-marker { display: none; }
.claim-more > summary:hover { border-color: var(--lamp); color: var(--lamp); }
.claim-more-menu {
  position: absolute;
  z-index: 20;
  top: calc(100% + 0.3rem);
  right: 0;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  padding: 0.4rem;
  background: var(--rock-deep);
  border: 1px solid var(--rock-edge);
  border-radius: 6px;
  box-shadow: 0 8px 24px -10px rgba(0, 0, 0, 0.8);
}
.claim-more-menu .claim-btn { white-space: nowrap; text-align: left; }

/* ── Bands ────────────────────────────────────────────────────────
   How sure the assay was. Deliberately a ramp rather than three unrelated
   colours: solid ore, ore outline, plain rock. Colour draining out down a list
   is confidence draining out. Same slugs as docs/feeds/feed.xsl, so a band
   reads the same on the page, in a report, and in a raw feed. */
.band {
  display: inline-block;
  vertical-align: baseline;
  border-radius: 3px;
  padding: 0.05rem 0.4rem;
  margin-right: 0.4rem;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.band-paydirt { background: var(--gold); color: #1b1f26; }
.band-look { border: 1px solid var(--gold-dim); color: var(--gold-dim); }
.band-longshot { border: 1px solid var(--rock-edge); color: var(--text-faint); }
/* A hand pick is the reader's opinion, not the assay's measurement, so it wears
   the lamp — the page's "you did this" colour — and never an ore chip. */
.band-picked { border: 1px solid var(--lamp-dim); color: var(--lamp); }

/* ── Hand-picking, in the table view ─────────────────────────────── */
.pick-col { width: 2rem; text-align: center; }
.pick-box { cursor: pointer; }

/* ── Papers list ──────────────────────────────────────────────────
   Full width, one row per stone in grade order — the matrix and table above
   are narrow and column-shaped, this is the plain read. A row expands in
   place on click, same idea as the train's own rows. */
.assay-list {
  margin-top: 1rem;
  border: 1px solid var(--rock-edge);
  border-radius: 8px;
  overflow: hidden;
}
.assay-list-row {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  padding: 0.45rem 0.7rem;
  cursor: pointer;
  border-top: 1px solid var(--rock-edge);
}
.assay-list-row:first-child { border-top: none; }
.assay-list-row:hover { background: var(--rock-lit); }
.assay-list-rank {
  flex: none;
  width: 1.8rem;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.assay-list-title {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
}
.assay-list-z {
  flex: none;
  width: 3.2rem;
  text-align: right;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}
.assay-list-caret {
  flex: none;
  width: 1rem;
  text-align: center;
  color: var(--text-faint);
}
.assay-list-row.is-open .assay-list-caret { transform: rotate(90deg); }
.assay-list-detail {
  display: none;
  padding: 0 0.7rem 0.7rem 3.4rem;
  color: var(--text-dim);
  font-size: 0.9rem;
  border-top: 1px solid var(--rock-edge);
}
.assay-list-row.is-open + .assay-list-detail { display: block; }
.assay-list-detail .assay-list-authors { color: var(--text-faint); margin: 0.3rem 0; }
.assay-list-detail .assay-list-match { color: var(--text-faint); font-style: italic; }
.assay-list-detail a { color: var(--lamp); }

/* ── The report bar ───────────────────────────────────────────────
   The report itself is a whole page and opens in its own tab; only its
   controls live here. */
.report-bar {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
  margin: 0.8rem 0 0.4rem;
}
.report-btn {
  padding: 0.4rem 0.9rem;
  border-radius: 4px;
  font-size: 0.92rem;
  font-weight: 600;
  cursor: pointer;
  border: 1px solid var(--gold);
  background: var(--gold);
  color: #221a00;
}
.report-btn:hover:not(:disabled) { background: #ffc730; }
.report-btn:disabled { opacity: 0.45; cursor: not-allowed; }
.report-note { font-size: 0.85rem; color: var(--text-faint); }

/* ── Narrow and touch ─────────────────────────────────────────────
   Controls grow to a 44px touch target and stop being a row of things too
   small and too close to hit with a thumb. The stacking rules below are inert
   while the setup grid has one column, and are kept for the same reason the
   grid is. */
@media (max-width: 720px) {
  .setup-cols { grid-template-columns: 1fr; gap: 1rem; }
  .setup-col + .setup-col {
    padding-left: 0;
    padding-top: 1rem;
    border-left: none;
    border-top: 1px solid var(--rock-edge);
  }
  .claim-bar { gap: 0.5rem; }
  .claim-pick { flex: 1 1 100%; }
  .claim-pick select { flex: 1; min-width: 0; }
  .claim-btn,
  .claim-more > summary,
  .report-btn {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
  .preset-buttons { gap: 0.45rem; }
  .preset-btn { min-height: 44px; }
  .report-bar { gap: 0.5rem; }
  .pick-col { width: 2.4rem; }
  .pick-box { width: 20px; height: 20px; }
}
}
