:root {
  /* Dark neutral stone + gold trim — the gold is an accent, never a wash.
     Surfaces are low-saturation graphite so nothing reads as an amber filter. */
  --bg:          #1a1a1b;   /* neutral graphite ground */
  --bg-card:     #242425;   /* stone panel */
  --bg-card-alt: #2f2f30;   /* lighter stone (inputs, headers) */
  --text:        #e8e7e3;   /* near-white */
  --text-dim:    #9a9890;   /* neutral gray */
  --accent:      #f4b53f;   /* OSRS gold (accent only) */
  --accent-dim:  #9c6a1e;   /* dim bronze-gold */
  --border:      #3a3a3c;   /* neutral hairline */
  --gold-edge:   #6f5524;   /* gold trim — for hero/accent panels only */
  --gold-hi:     rgba(244, 181, 63, 0.20);  /* bevel highlight */
  --good: #8cc06c;
  --warn: #e0a83f;
  --bad:  #d2705c;
  --font-display: "Cinzel", Georgia, "Times New Roman", serif;
  --font-body:    "Hanken Grotesk", system-ui, -apple-system, sans-serif;
  --font-mono:    "JetBrains Mono", ui-monospace, "Cascadia Mono", monospace;
}

* { box-sizing: border-box; }

/* Always reserve the viewport scrollbar's width. Without this, the page width
   jumps by the scrollbar's ~15px the moment content height crosses the
   viewport — and with the 3-up rec cards that 15px straddles the auto-fit
   column threshold, giving a bistable band where the layout flips 2+1 / 3-up
   depending on scroll history. `overflow-y: scroll` forces a permanent track
   (works everywhere); `scrollbar-gutter` is the modern equivalent where honoured. */
html {
  overflow-y: scroll;
  scrollbar-gutter: stable;
}

body {
  margin: 0;
  padding: 2rem 1rem;
  color: var(--text);
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.55;
  font-variant-numeric: tabular-nums;
  /* Atmosphere: a faint neutral sheen at the top for depth and a subtle film
     grain over the stone — no colour cast. Layered on the background (no
     overlay element) so the sticky stack's z-index is untouched. */
  background-color: var(--bg);
  background-image:
    radial-gradient(70% 40% at 50% -10%, rgba(255, 255, 255, 0.022), transparent 60%),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.2'/%3E%3C/svg%3E");
  background-repeat: no-repeat, repeat;
  background-size: auto, 160px 160px;
  background-attachment: fixed, fixed;
  background-blend-mode: normal, soft-light;
}

.container {
  /* Wide enough that the 10-column fish-cook table lays out without horizontal
     scroll on typical desktops, but capped so prose-style content (rec card,
     banners) stays readable. The extra ~12rem is the rail gutter that the
     non-home views consume; the rail sits inside it, so the actual content
     column still gets the original ~1280px. */
  max-width: calc(1280px + 12rem);
  margin: 0 auto;
}

header {
  margin-bottom: 1.5rem;
}

h1 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.9rem;
  letter-spacing: 0.6px;
  color: var(--accent);
  /* engraved-gold lift */
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.6), 0 0 18px rgba(244, 181, 63, 0.25);
}

h2, h3 {
  margin: 0 0 1rem 0;
  font-family: var(--font-display);
  font-size: 1.1rem;
  color: var(--accent);
  font-weight: 600;
  letter-spacing: 0.4px;
}
h3 { font-size: 1rem; }

.subtitle {
  margin: 0.25rem 0 0 0;
  color: var(--text-dim);
  font-size: 0.95rem;
}

.card {
  /* Neutral stone panel with a subtle top-light bevel — no gold here. */
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 1.25rem;
  margin-bottom: 1rem;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.04),
    0 2px 10px rgba(0, 0, 0, 0.35);
}

.inputs .input-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 0.75rem;
}

.inputs label {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-size: 0.85rem;
  color: var(--text-dim);
}

.inputs label span {
  text-transform: uppercase;
  letter-spacing: 0.5px;
  font-size: 0.75rem;
}

/* "In sync with hiscores": the level input's value still matches the XP pulled
   from the last hiscores lookup (toggled by updateSyncIndicators in core.js).
   A green check on the label name + a green field border; absence means the
   value was set manually / edited since, so XP is the level's estimated minimum. */
.inputs label.xp-synced > span::after {
  content: "✓";
  margin-left: 0.4rem;
  color: var(--good);
  font-weight: 700;
  font-size: 0.8rem;
}
.inputs label.xp-synced input[type="number"] {
  border-color: rgba(140, 192, 108, 0.55);
  box-shadow: inset 0 0 0 1px rgba(140, 192, 108, 0.25);
}

input[type="number"], select {
  background: var(--bg-card-alt);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.5rem 0.6rem;
  font-size: 0.95rem;
  font-family: inherit;
}

input[type="number"]:focus, select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(244, 181, 63, 0.15);
}

select option:disabled {
  color: var(--text-dim);
}

.hint {
  margin: 0.75rem 0 0 0;
  font-size: 0.8rem;
  color: var(--text-dim);
}

.import-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-top: 0.6rem;
  flex-wrap: wrap;
}

label.inline {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 0.5rem;
}

label.inline span {
  text-transform: uppercase;
  font-size: 0.72rem;
  letter-spacing: 0.5px;
  color: var(--text-dim);
}

input[type="text"] {
  background: var(--bg-card-alt);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.45rem 0.6rem;
  font-size: 0.9rem;
  font-family: inherit;
  min-width: 180px;
}
input[type="text"]:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(244, 181, 63, 0.15);
}

.btn {
  background: linear-gradient(180deg, #2d2417, #221a10);
  color: var(--accent);
  border: 1px solid var(--accent-dim);
  border-radius: 4px;
  padding: 0.5rem 0.95rem;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.9rem;
  letter-spacing: 0.3px;
  cursor: pointer;
  box-shadow: inset 0 1px 0 var(--gold-hi);
  transition: border-color 120ms, box-shadow 120ms, color 120ms;
}
.btn:hover {
  border-color: var(--accent);
  box-shadow: inset 0 1px 0 var(--gold-hi), 0 0 14px rgba(244, 181, 63, 0.20);
}
.btn:disabled { opacity: 0.5; cursor: not-allowed; box-shadow: none; }

.status {
  font-size: 0.85rem;
  color: var(--text-dim);
}
.status.loading { color: var(--text); }
.status.success { color: var(--good); }
.status.warn    { color: var(--warn); }
.status.error   { color: var(--bad); }

.warn-banner {
  background: rgba(214, 167, 84, 0.08);
  border: 1px solid var(--warn);
  border-radius: 6px;
  padding: 0.6rem 0.9rem;
  margin: 0.85rem 0 0 0;
  font-size: 0.85rem;
  color: var(--text);
  line-height: 1.5;
}

.hidden { display: none; }

.banner {
  background: rgba(244, 181, 63, 0.07);
  border: 1px solid var(--accent-dim);
  border-radius: 6px;
  padding: 0.75rem 1rem;
  margin-bottom: 1rem;
  font-size: 0.85rem;
  color: var(--text);
}

.banner a {
  color: var(--accent);
}

.recommendation {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.25rem;
  border-left: 4px solid var(--accent);
}

/* Two-column recommendation card: best-for-cooking + best-for-fishing
   side-by-side on wide viewports, stacked when narrow. */
.rec-pair {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1.25rem;
}
.rec-cell {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.3rem;
  padding: 0.95rem 1.05rem;
  border: 1px solid var(--gold-edge);
  border-radius: 5px;
  /* gilded reward panel */
  background:
    radial-gradient(130% 100% at 0% 0%, rgba(244, 181, 63, 0.06), transparent 70%),
    linear-gradient(180deg, #2a2a2b, #242425);
  box-shadow: inset 0 1px 0 var(--gold-hi), 0 1px 6px rgba(0, 0, 0, 0.35);
  animation: rec-rise 520ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
}
.rec-cell:nth-child(2) { animation-delay: 80ms; }
.rec-cell:nth-child(3) { animation-delay: 160ms; }

@keyframes rec-rise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .rec-cell { animation: none; }
}

.rec-label {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 1.2px;
  font-weight: 600;
  color: var(--accent-dim);
}

.rec-tree {
  font-family: var(--font-display);
  font-size: 1.45rem;
  font-weight: 700;
  line-height: 1.15;
  color: var(--accent);
  text-shadow: 0 0 16px rgba(244, 181, 63, 0.30), 0 1px 0 rgba(0, 0, 0, 0.5);
}

.rec-xp {
  font-family: var(--font-mono);
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--text);
}

.rec-detail {
  font-size: 0.9rem;
  color: var(--text-dim);
}

.rec-overtake {
  font-size: 0.85rem;
  color: var(--text);
  border-top: 1px dashed var(--border);
  padding-top: 0.5rem;
  margin-top: 0.25rem;
}
.rec-overtake:empty { display: none; }
.rec-overtake strong { color: var(--accent); font-weight: 600; }
.rec-overtake .ot-dim { color: var(--text-dim); }
td .ot-dim { color: var(--text-dim); }

/* The hint sits below the .rec-pair grid (a sibling, not a grid item) so it
   doesn't add a phantom column that defeats auto-fit's empty-track collapsing
   — that's what left dead space beside the cells at wide widths. */
.rec-card .rec-overtake-hint {
  margin: 1rem 0 0;
  padding-top: 0.75rem;
  border-top: 1px solid var(--border);
}

.table-wrap {
  /* No overflow by default — setting overflow-x: auto would implicitly
     promote overflow-y to auto and turn this into a scroll container,
     which traps the sticky thead inside the wrap. `is-scrolling` (toggled by
     wireStickyTheadRelease when the table overflows its column) and the
     narrow-width breakpoint re-enable horizontal scroll where the table can't
     fit; in both cases the thead is switched to static so nothing is trapped. */
}
.table-wrap.is-scrolling {
  overflow-x: auto;
  /* The visible bar is the floating .hscroll proxy (which stays in view); hide
     this native one to avoid a redundant second scrollbar at the table bottom.
     The wrap still scrolls via wheel/touch and stays synced to the proxy. */
  scrollbar-width: none;
}
.table-wrap.is-scrolling::-webkit-scrollbar { height: 0; }
.table-wrap.is-scrolling thead {
  position: static;
}

/* Floating horizontal scrollbar: a slim strip pinned to the viewport bottom
   that mirrors an overflowing table's horizontal scroll, so you can scroll
   sideways while the table is on screen instead of first scrolling to its
   bottom. Created and kept in sync by wireStickyTheadRelease in core.js;
   `overflow-x: scroll` keeps the track a consistent height across browsers. */
.hscroll {
  position: sticky;
  bottom: 0;
  z-index: 15;
  height: 14px;
  overflow-x: scroll;
  overflow-y: hidden;
  background: var(--bg-card);
  /* Force an always-visible themed bar regardless of OS scrollbar mode.
     Windows 11 Chrome defaults to auto-hiding overlay (Fluent) scrollbars,
     which take no layout space and vanish at rest — a bare native proxy would
     be invisible. Defining ::-webkit-scrollbar opts this element back into a
     classic, persistent, styled scrollbar. */
  scrollbar-width: thin;
  scrollbar-color: var(--accent-dim) transparent;
}
.hscroll > div { height: 1px; }
.hscroll::-webkit-scrollbar { height: 12px; }
.hscroll::-webkit-scrollbar-track { background: transparent; }
.hscroll::-webkit-scrollbar-thumb {
  background: var(--accent-dim);
  border-radius: 6px;
}
.hscroll::-webkit-scrollbar-thumb:hover { background: var(--accent); }

table {
  width: 100%;
  /* `separate` (instead of `collapse`) is required for sticky `thead` to
     release at the table's bottom edge — collapsed-border tables anchor
     sticky cells to the row, which never releases. */
  border-collapse: separate;
  border-spacing: 0;
  font-size: 0.9rem;
  /* Explicit containing block so the sticky thead releases at the table's
     bottom edge rather than walking off into the card's hint paragraph. */
  position: relative;
}

thead {
  /* Stick the whole thead row group (not individual cells). Browsers
     disagree on the containing block for `display: table-header-group`,
     so the release-at-table-bottom is enforced from JS — see
     `wireStickyTheadRelease` in core.js, which toggles `thead-released`
     once the tbody's bottom has scrolled past the sticky position. */
  position: sticky;
  /* Offset published by updateStickyOffsets() in core.js (measured stack
     height); the rem fallback is the old fixed value for the no-JS case. */
  top: var(--sticky-thead-top, 15.5rem);
  z-index: 10;
}

/* `.thead-released` is set by JS once the thead would otherwise cover the
   last tbody row. The JS also writes an inline `position: relative` and a
   frozen `top` so the thead scrolls out naturally with the table from
   that point onward, instead of snapping away. */

thead th {
  background: var(--bg-card-alt);
  color: var(--text-dim);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  font-size: 0.72rem;
  padding: 0.55rem 0.6rem;
  text-align: left;
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
  border-bottom: 1px solid var(--border);
}

thead th:hover {
  color: var(--text);
}

thead th.sorted {
  color: var(--accent);
}

thead th.sorted::after {
  content: "";
  margin-left: 0.3rem;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  display: inline-block;
  vertical-align: middle;
}

thead th.sorted.desc::after { border-top: 5px solid var(--accent); }
thead th.sorted.asc::after  { border-bottom: 5px solid var(--accent); }

thead th[data-numeric] { text-align: right; }
tbody td { padding: 0.5rem 0.6rem; border-bottom: 1px solid var(--border); vertical-align: middle; }
tbody td.numeric {
  text-align: right;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.84rem;
  white-space: nowrap;       /* numbers must never wrap to two lines */
}
tbody td.tree-name {
  font-weight: 600;
  white-space: nowrap;       /* spot/tree name fits on one line in wide layout */
}

/* Text-heavy columns: allow wrapping but at sensible breakpoints. The
   "tool" and "catching at your level" cells in the fish-cook table can
   legitimately need to wrap on narrower viewports. */
#fc-results-table tbody td:nth-child(3),   /* Tool */
#fc-results-table tbody td:nth-child(4) {  /* Catching at your level */
  min-width: 8rem;
}

tbody tr {
  cursor: pointer;
}
tbody tr:not(.recommended):not(.excluded):hover {
  background: rgba(244, 181, 63, 0.05);
}
tbody tr.ineligible {
  opacity: 0.45;
}
tbody tr.excluded {
  opacity: 0.35;
}
tbody tr.excluded td.tree-name {
  text-decoration: line-through;
  color: var(--text-dim);
}
tbody tr.excluded.recommended {
  /* If somehow both classes coexist, excluded wins — the row shouldn't
     look like the active recommendation while it's being skipped. */
  background: transparent;
}

tbody tr.ineligible .tree-name::after {
  content: "🔒";
  margin-left: 0.4rem;
  opacity: 0.7;
  font-size: 0.85em;
}

tbody tr.recommended {
  background: rgba(244, 181, 63, 0.09);
  box-shadow: inset 3px 0 0 var(--accent);
}

tbody tr.recommended .tree-name {
  color: var(--accent);
}

.tree-swatch {
  display: inline-block;
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 2px;
  margin-right: 0.5rem;
  vertical-align: middle;
}

.chart-wrap {
  position: relative;
  height: 640px;
}


footer {
  margin-top: 2rem;
  padding-top: 1rem;
  border-top: 1px solid var(--border);
  font-size: 0.8rem;
  color: var(--text-dim);
  text-align: center;
}

footer a {
  color: var(--accent);
}

code {
  background: var(--bg-card-alt);
  color: var(--accent);
  font-family: var(--font-mono);
  padding: 0.1rem 0.35rem;
  border-radius: 3px;
  font-size: 0.82rem;
}

/* ---- Top toolbar (shared across all views) ------------------------- */

.top-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 0;
  padding: 2rem 0 0.85rem 0;
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--bg);
  /* Negative margin cancels the body's 2rem top padding so the toolbar
     reaches the viewport's top edge once scrolled; the matching padding
     keeps its content in the same visual spot when at rest. */
  margin-top: -2rem;
}

.view-title {
  position: sticky;
  top: var(--sticky-title-top, 5.5rem);
  z-index: 30;
  background: var(--bg);
  padding: 0.75rem 0 0.5rem 0;
  margin: 0 !important;
  border-bottom: 1px solid var(--border);
}

.view-flex .inputs.card {
  position: sticky;
  top: var(--sticky-inputs-top, 9rem);
  z-index: 20;
  margin-bottom: 1rem;
}

.top-toolbar-left {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  flex-wrap: wrap;
}

.app-version {
  color: var(--accent-dim);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.5px;
}
.app-version:empty { display: none; }

.top-toolbar-right {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}

/* ---- Section switcher (the heading is the menu) -------------------- */

/* The section name in each .view-title is a button that inherits the big
   gold Cinzel heading look and drops a menu of the other tools. */
.view-title-switch {
  appearance: none;
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;             /* Cinzel, 1.5rem, 700 from .view-title */
  color: inherit;            /* gold */
  letter-spacing: inherit;
  text-shadow: inherit;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  transition: text-shadow 140ms;
}
.view-title-switch:hover { text-shadow: 0 0 16px rgba(244, 181, 63, 0.4); }
.view-title-switch:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* Downward caret drawn from borders so it tracks the gold currentColor. */
.view-title-switch .caret {
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 0.36em 0.3em 0 0.3em;
  border-color: currentColor transparent transparent transparent;
  opacity: 0.8;
  transition: transform 160ms, opacity 140ms;
}
.view-title-switch:hover .caret { opacity: 1; }
.view-title-switch[aria-expanded="true"] .caret { transform: rotate(180deg); }

/* Dropdown panel — anchored under the heading button (the sticky .view-title
   is the positioned containing block). */
.view-title-menu {
  position: absolute;
  top: calc(100% + 0.4rem);
  left: 0;
  z-index: 50;
  min-width: 16rem;
  display: flex;
  flex-direction: column;
  padding: 0.35rem;
  background: var(--bg-card);
  border: 1px solid var(--gold-edge);
  border-radius: 6px;
  box-shadow: inset 0 1px 0 var(--gold-hi), 0 8px 24px rgba(0, 0, 0, 0.5);
}
.view-title-menu[hidden] { display: none; }
.view-title-menu a {
  display: block;
  padding: 0.5rem 0.7rem;
  border-radius: 4px;
  color: var(--text);
  text-decoration: none;
  font-family: var(--font-body);
  font-size: 0.95rem;
  font-weight: 500;
  letter-spacing: normal;
  text-shadow: none;
  white-space: nowrap;
}
.view-title-menu a:hover { background: rgba(244, 181, 63, 0.10); color: var(--accent); }
.view-title-menu a[aria-current] { color: var(--accent); font-weight: 700; }
/* "All tools" sits apart as the way back to the index. */
.view-title-menu a[data-id="home"] {
  color: var(--text-dim);
  border-bottom: 1px solid var(--border);
  margin-bottom: 0.25rem;
  padding-bottom: 0.55rem;
  border-radius: 4px 4px 0 0;
}
.view-title-menu a[data-id="home"]:hover { color: var(--accent); }

/* ---- Views (switched by hash router) ------------------------------- */

.view {
  /* visible by default; .hidden flips it off */
}

.view-title {
  font-family: var(--font-display);
  font-size: 1.5rem;
  color: var(--accent);
  margin: 0 0 1.25rem 0;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

/* (i) toggle for each section's data/calc notes — collapsed by default. */
.info-btn {
  flex: 0 0 auto;
  width: 1.45rem;
  height: 1.45rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid var(--accent-dim);
  border-radius: 50%;
  background: transparent;
  color: var(--accent);
  font-family: Georgia, "Times New Roman", serif;
  font-style: italic;
  font-size: 0.95rem;
  font-weight: 700;
  line-height: 1;
  text-shadow: none;
  cursor: pointer;
  transition: background 120ms, border-color 120ms, color 120ms;
}
.info-btn:hover { border-color: var(--accent); background: rgba(244, 181, 63, 0.12); }
.info-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.info-btn[aria-expanded="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: #1f1f1f;
}

/* ---- Startpage section picker -------------------------------------- */

.intro {
  max-width: 62ch;
  margin: 0 0 1rem 0;
  color: var(--text-dim);
  font-size: 0.95rem;
  line-height: 1.65;
  /* even out the wrap so there's no short orphaned last line */
  text-wrap: balance;
  /* a gold hairline keys it to the theme without shouting */
  border-left: 2px solid var(--accent-dim);
  padding-left: 0.85rem;
}

.lede {
  font-size: 1rem;
  color: var(--text);
  margin: 0 0 1.5rem 0;
}

.section-picker-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 1rem;
  margin-bottom: 1.5rem;
}

.section-card {
  display: block;
  background:
    radial-gradient(130% 100% at 0% 0%, rgba(244, 181, 63, 0.05), transparent 70%),
    linear-gradient(180deg, var(--bg-card), #202021);
  border: 1px solid var(--gold-edge);
  border-radius: 6px;
  padding: 1.25rem 1.25rem 1.4rem;
  color: var(--text);
  text-decoration: none;
  box-shadow: inset 0 1px 0 var(--gold-hi), 0 2px 10px rgba(0, 0, 0, 0.45);
  transition: border-color 140ms, transform 140ms, box-shadow 140ms;
}
.section-card:hover {
  border-color: var(--accent);
  transform: translateY(-2px);
  box-shadow: inset 0 1px 0 var(--gold-hi), 0 6px 22px rgba(244, 181, 63, 0.12);
}
.section-card h2 {
  margin: 0 0 0.5rem 0;
  font-size: 1.15rem;
}
.section-card p {
  margin: 0;
  font-size: 0.9rem;
  color: var(--text-dim);
}

/* ---- Gauntlets checkbox row ---------------------------------------- */

.inputs label.checkbox-cell {
  flex-direction: row;
  align-items: center;
  gap: 0.5rem;
  align-self: end;
  padding-bottom: 0.55rem;
}

.inputs label.checkbox-cell span {
  text-transform: none;
  letter-spacing: 0;
  font-size: 0.85rem;
  color: var(--text);
}

input[type="checkbox"] {
  width: 1rem;
  height: 1rem;
  accent-color: var(--accent);
  cursor: pointer;
}

/* ---- Mode rail (sticky skill selector per section) ---------------- */

/* Each non-home view lays out as: title above, then a flex row with the
   rail on the left and the content body on the right. The rail uses
   position: sticky so its top edge starts aligned with the inputs card
   (both are flex-start children of .view-flex), scrolls up with the
   content, and anchors at top:1rem once the user scrolls past it. */
.view-flex {
  display: flex;
  align-items: flex-start;
  gap: 1rem;
}
.view-body {
  flex: 1 1 auto;
  min-width: 0;     /* allow children to shrink past their content width */
}

.mode-rail {
  position: sticky;
  /* Sit just below the sticky inputs card so the rail's "Tracking" header
     stays roughly aligned with the input labels as the user scrolls. */
  top: var(--sticky-inputs-top, 9rem);
  flex: 0 0 auto;
  align-self: flex-start;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.55rem 0.6rem;
  box-shadow: 0 2px 8px rgba(0,0,0,0.25);
  min-width: 9.5rem;
}

.mode-rail-label {
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-dim);
  padding-bottom: 0.15rem;
  border-bottom: 1px solid var(--border);
  margin-bottom: 0.25rem;
  text-align: center;
}

.mode-rail-btn {
  background: var(--bg-card-alt);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.4rem 0.6rem;
  font-family: inherit;
  font-size: 0.82rem;
  cursor: pointer;
  text-align: left;
  transition: border-color 120ms, background 120ms, color 120ms;
}
.mode-rail-btn:hover { border-color: var(--accent); }
.mode-rail-btn.active {
  background: var(--accent);
  border-color: var(--accent);
  color: #1f1f1f;
  font-weight: 600;
}

/* ---- Mining rock-count input --------------------------------------- */

/* Compact number input for the per-row "Rocks available" column in the
   mining table. Inherits the global input[type=number] colours/border so
   it stays consistent with the dark theme; width is just kept tight. */
.rock-count {
  width: 4.5em;
  padding: 0.25rem 0.4rem;
  font-size: 0.84rem;
}

/* Dim second line under a rock's success %: its 100%-success level, or the
   ceiling it caps at if it never reaches 100%. */
.success-note {
  display: block;
  margin-top: 0.1rem;
  font-size: 0.68rem;
  font-weight: normal;
  color: var(--text-dim);
}

/* The rail is now in normal flow (sticky inside .view-flex), so no body
   padding shenanigans are needed — the layout naturally reserves space
   for it. */

/* ---- Responsive --------------------------------------------------- */

/* On narrower desktop / tablet widths, allow the spot name to wrap so the
   numeric columns get to stay on one line. */
@media (max-width: 1100px) {
  tbody td.tree-name { white-space: normal; }
  thead th { padding: 0.5rem 0.45rem; font-size: 0.68rem; }
  tbody td { padding: 0.45rem 0.45rem; }
  table { font-size: 0.85rem; }
}

/* The Tracking rail's ~150px column narrows .view-body. Below ~1137px there's
   no longer room for it AND a 3-up rec layout, so the rec cards would drop to
   2+1 while the rail is still shown — then jump back to 3-up the instant the
   rail is hidden, and collapse again as you keep narrowing (the reported
   3 -> 2+1 -> 3 -> 2+1 -> 1 bounce). Hiding the rail at 1150px, with margin,
   means the rail only appears when 3-up fits beside it, so the rec grid
   reflows monotonically. The clickable column headers sort by the same metrics
   once the rail is gone. */
@media (max-width: 1150px) {
  .mode-rail:not(.mode-rail--activity) { display: none; }

  /* The activity rail switches the active sub-activity, so unlike the Tracking
     rail it must stay reachable at every width. Instead of hiding, it reflows
     from the vertical side-rail to a horizontal tab strip at the top of the
     body — .view-flex--activity stacks rail-over-body so the body keeps the
     full content width (and the rec grid reflows monotonically, since a side
     column no longer competes for horizontal space below this width). */
  .view-flex--activity { flex-direction: column; align-items: stretch; }
  .mode-rail--activity {
    position: static;
    flex-direction: row;
    flex-wrap: wrap;
    width: 100%;
    min-width: 0;
    margin-bottom: 1rem;
  }
  .mode-rail--activity .mode-rail-label { display: none; }
  .mode-rail--activity .mode-rail-btn { text-align: center; }
}

/* Safeguard: below this width the input grid wraps to several rows, so the
   stacked sticky bars get tall enough to eat most of a short viewport — and if
   JS hasn't published the measured offsets yet, the rem fallbacks no longer
   line up. Drop the lower bars to static (the toolbar stays pinned at top:0,
   which never depends on the stack height). The dynamic offsets above keep the
   full sticky stack correct at all wider widths. */
@media (max-width: 768px) {
  .view-flex .inputs.card,
  .mode-rail,
  thead { position: static; }
  /* `relative` (not `static`) drops the sticky behaviour while still anchoring
     the section-switcher menu, which is absolutely positioned within it.
     `top: auto` cancels the sticky offset, which `relative` would otherwise
     honour and push the heading down over the inputs. */
  .view-title { position: relative; top: auto; }
  /* No-JS fallback: with the sticky stack static here, the wrap can safely be a
     horizontal scroll container so a too-wide table scrolls inside its card
     instead of spilling past it. When JS runs, `is-scrolling` already does this
     at any width. */
  .table-wrap { overflow-x: auto; }
}

@media (max-width: 600px) {
  body { padding: 1rem 0.5rem; }
  h1 { font-size: 1.4rem; }
  .rec-tree { font-size: 1.2rem; }
  .chart-wrap { height: 520px; }
  .top-toolbar { flex-direction: column; align-items: stretch; }
  .top-toolbar-right { justify-content: flex-start; }
  input[type="text"] { min-width: 0; flex: 1; }
  /* On phones the toolbar becomes column-stacked and its height is
     unpredictable; the sticky stack would shove half the chart offscreen,
     so drop the toolbar too (the rest of the stack is already static at the
     768px breakpoint above, and the rail is hidden from 1100px). */
  .top-toolbar { position: static; margin-top: 0; padding-top: 0; margin-bottom: 1.25rem; }
  .view-title { border-bottom: none; padding: 0; margin: 0 0 1.25rem 0 !important; }
}

/* ---- Display-mode toggle (success % vs avg seconds) ---------------- */
.display-mode-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}
.display-mode-toggle .dm-label {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-dim);
}
.dm-btn {
  background: var(--bg-card-alt);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.25rem 0.55rem;
  font-family: inherit;
  font-size: 0.8rem;
  cursor: pointer;
  transition: border-color 120ms, background 120ms, color 120ms;
}
.dm-btn:hover { border-color: var(--accent); }
.dm-btn.active {
  background: var(--accent);
  border-color: var(--accent);
  color: #1f1f1f;
  font-weight: 600;
}
