/* Wyrmtable 2.0 — frontend styles built from "Wyrmtable Brand.dc.html"
   Tokens: Night/Slate surfaces, Ember accent, Frost text, Mist muted,
   Inter for headings & UI, JetBrains Mono for numbers & data.

   v3.1.5 TYPOGRAPHY AND CONTRAST. Two changes, for one reason: a great deal of
   this interface is 11 to 12.5px explanatory text on a near-black background,
   and it was hard to read.

   Archivo -> Inter. Archivo is a display grotesque; its x-height is short and
   its counters close up below about 13px, which is most of the small text here.
   Inter was drawn for interface text at exactly these sizes: taller x-height,
   more open apertures, and a tabular-figure feature that keeps numbers aligned.
   Same weights, so nothing else in the sheet changes.

   The muted greys were also too dark. --dim at #4d565e sat near 2.5:1 against
   the card surfaces, well under the 4.5:1 that small text needs, and --mist was
   marginal. Each is lifted while keeping the ordering and the hue, so anything
   relying on "dim is quieter than mist" still holds. */

:root {
  /* Surfaces lifted a step in v2.7.1: the original set sat so close to the page
     background that cards, rows and inputs barely separated from it. Same hues
     and the same ordering, each roughly 5 to 7 points lighter, so nothing that
     depends on the palette's contrast direction changes. */
  --night: #0a0c0e;
  --slate: #171c22;
  --slate-2: #1b2127;
  --slate-3: #222a32;
  --border: #2b343c;
  --border-soft: #262e35;
  --border-strong: #37424c;
  --row-border: #222931;
  /* v3.0.1: `--line` was used by seventeen rules added in v3.0 and never
     defined. An undefined var makes the whole declaration invalid at computed-
     value time, so `border: 1px solid var(--line)` fell back to currentColor
     and `color: var(--line)` inherited its parent instead. That is why the
     unfilled grade stars rendered ember: they inherited .grade-stars. */
  --line: #2b343c;
  --ember: #ff5c1f;
  --ember-soft: #ff8a5c;
  --frost: #e6edf2;
  --mist: #99a4ad;
  --mist-2: #c5ced6;
  --dim: #77828b;
  --green: #4ecb71;
  --red: #e05b4f;
  --neutral: #9aa5ad;
  --legendary: #e8b84a;
  --epic: #b07ce8;
  --rare: #5ba7e0;
  --font-ui: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, monospace;
  /* The one colour that is meant to interrupt: used for the recommendation on
     the army count, and nothing decorative. */
  --info: #58b6ff;
  --info-soft: #8fd0ff;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--night);
  color: var(--frost);
  font-family: var(--font-ui);
  font-size: 15px;
  line-height: 1.5;
}
a { color: var(--ember); text-decoration: none; }
a:hover { color: var(--ember-soft); }
button { font-family: inherit; cursor: pointer; }
select, input {
  font-family: inherit;
  color: var(--frost);
  background: var(--slate-3);
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  padding: 8px 11px;
  font-size: 13px;
}
select:focus, input:focus { outline: 1px solid var(--ember); outline-offset: 0; }

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

/* ---------- shared building blocks ---------- */
.kicker {
  font-size: 11px; font-weight: 700; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--ember);
}
.section-label {
  font-size: 11.5px; font-weight: 700; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--mist);
}
.h-display {
  font-weight: 800; letter-spacing: -0.02em; line-height: 0.98;
  text-transform: uppercase;
}
.card {
  background: var(--slate);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.btn {
  display: inline-block; border-radius: 6px; border: 0;
  font-weight: 800; font-size: 13px; letter-spacing: 0.06em;
  text-transform: uppercase; padding: 14px 26px; text-align: center;
}
.btn-primary { background: var(--ember); color: var(--night); }
.btn-primary:hover { background: var(--ember-soft); color: var(--night); }
.btn-ghost {
  background: transparent; color: var(--frost); font-weight: 600;
  border: 1px solid var(--border-strong);
}
.btn-ghost:hover { border-color: var(--mist); color: var(--frost); }
.btn-sm { padding: 9px 16px; font-size: 11px; }

.rarity { font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; }
.rarity-Legendary { color: var(--legendary); }
.rarity-Epic { color: var(--epic); }
.rarity-Rare { color: var(--rare); }
.rarity-badge {
  font-size: 9.5px; border-radius: 4px; padding: 2px 6px;
}
.rarity-badge.rarity-Legendary { border: 1px solid rgba(232, 184, 74, 0.45); }
.rarity-badge.rarity-Epic { border: 1px solid rgba(176, 124, 232, 0.45); }
.rarity-badge.rarity-Rare { border: 1px solid rgba(91, 167, 224, 0.45); }

.dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; }
.dot-green { background: var(--green); }
.dot-red { background: var(--red); }
.dot-neutral { background: var(--neutral); }
.affinity-tag {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 10px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
}
.affinity-green { color: var(--green); }
.affinity-red { color: var(--red); }
.affinity-neutral { color: var(--neutral); }

/* star pips */
.pips { display: flex; gap: 2.5px; }
.pips span { flex: 1; height: 4px; border-radius: 2px; background: var(--border-strong); }
.pips span.on { background: var(--ember); }

/* habit chips */
.habit-chips { display: flex; gap: 4px; }
.habit-chips span {
  flex: 1; text-align: center; font-family: var(--font-mono); font-size: 10.5px;
  padding: 4px 0; border-radius: 4px; background: var(--slate-2);
  color: var(--dim); border: 1px solid var(--border);
}
.habit-chips span.on {
  background: rgba(255, 92, 31, 0.16); color: var(--ember-soft);
  border-color: rgba(255, 92, 31, 0.4);
}

/* the scale texture — hero sections only, never behind data */
.scale-texture {
  background-image:
    radial-gradient(700px 420px at 18% 0%, rgba(255, 92, 31, 0.10), transparent 70%),
    radial-gradient(circle 12px at 12px 0, transparent 11px, #171c22 11.5px),
    radial-gradient(circle 12px at 36px 12px, transparent 11px, rgba(23, 28, 34, 0.6) 11.5px);
  background-size: 100% 100%, 48px 24px, 48px 24px;
}

/* ---------- top bar ---------- */
.topbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 48px; border-bottom: 1px solid var(--border-soft);
}
.logo-lockup { display: inline-flex; align-items: center; gap: 11px; color: var(--frost); }
.logo-lockup:hover { color: var(--frost); }
.logo-mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 50%; background: var(--ember); flex: none;
}
.logo-word {
  font-weight: 800; font-size: 18px; letter-spacing: 0.04em; text-transform: uppercase;
}
.topnav { display: flex; align-items: center; gap: 26px; }
.topnav a {
  font-size: 12.5px; font-weight: 600; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--mist);
}
.topnav a:hover, .topnav a.active { color: var(--frost); }
.hamburger { display: none; background: none; border: 0; padding: 12px 4px; }
.hamburger span { display: block; width: 20px; height: 2px; background: var(--frost); margin: 4px 0; }

/* segmented app tabs (calculator header) */
.seg-tabs {
  display: flex; gap: 4px; background: var(--slate);
  border: 1px solid var(--border); border-radius: 7px; padding: 3px;
}
.seg-tabs a {
  color: var(--mist); font-size: 11px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; padding: 7px 16px; border-radius: 5px;
}
.seg-tabs a.active { background: var(--ember); color: var(--night); font-weight: 800; }

/* ---------- homepage ---------- */
.hero {
  display: grid; grid-template-columns: 1fr 560px; gap: 56px; align-items: center;
  padding: 76px 48px 68px;
}
.hero h1 { font-size: 58px; max-width: 560px; margin: 16px 0 0; }
.hero-sub { color: var(--mist); font-size: 17px; margin-top: 18px; max-width: 480px; line-height: 1.6; text-wrap: pretty; }
.hero-ctas { display: flex; gap: 12px; margin-top: 28px; }
.hero-note { font-family: var(--font-mono); font-size: 12px; color: var(--dim); margin-top: 24px; }

.hero-aside { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.preview-card {
  background: var(--slate); border: 1px solid var(--border); border-radius: 10px;
  padding: 20px 22px; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.45);
}

/* Latest updates block: three newest entries from /data/news.json */
.news-card { padding: 18px 22px 8px; }
.news-viewall {
  font-size: 11.5px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ember);
}
.news-row {
  display: grid; grid-template-columns: 8px 54px 1fr; align-items: baseline; gap: 12px;
  padding: 10px 0; border-top: 1px solid var(--border); color: inherit;
}
.news-row:first-child { border-top: 0; }
.news-row:hover .news-row-title { color: var(--ember); }
.news-dot {
  width: 6px; height: 6px; border-radius: 50%; background: var(--dim);
  align-self: start; margin-top: 6px;   /* lines up with the first line, not the middle of a wrapped title */
}
.news-dot.latest { background: var(--ember); }
.news-row-date { font-size: 11px; color: var(--dim); white-space: nowrap; }
.news-row-title { font-size: 13px; color: var(--mist-2); line-height: 1.45; }
.preview-row {
  display: grid; grid-template-columns: 92px 1fr 118px 70px; align-items: center;
  gap: 12px; background: var(--slate-2); border: 1px solid var(--border);
  border-radius: 7px; padding: 11px 14px;
}
.preview-row.lead { border-color: rgba(255, 92, 31, 0.35); }
.pos-label {
  font-size: 10px; font-weight: 700; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--mist);
}
.preview-row.lead .pos-label { color: var(--ember); }

.section { padding: 64px 48px; }
.section + .section { padding-top: 0; }
.section h2 {
  font-size: 30px; font-weight: 800; letter-spacing: -0.01em;
  text-transform: uppercase; margin: 10px 0 36px;
}
/* v3.0.1: one explainer block. Replaces .steps (three cards) plus .features
   (two more), which together restated what the tool grid above them already
   said. The numbers come from a counter so the markup stays an <ol>. */
.explain-card { padding: 30px 34px; counter-reset: explain; }
.explain-title { font-size: 22px; margin: 8px 0 20px; }
.explain-steps {
  margin: 0; padding: 0; list-style: none;
  display: grid; gap: 14px;
}
.explain-steps li {
  counter-increment: explain;
  display: grid; grid-template-columns: 30px 1fr; gap: 14px;
  color: var(--mist); font-size: 13.5px; line-height: 1.65; text-wrap: pretty;
}
.explain-steps li::before {
  content: '0' counter(explain);
  font-family: var(--font-mono); font-size: 12px; color: var(--ember);
  padding-top: 2px;
}
.explain-steps b { color: var(--frost); }
.explain-foot {
  margin: 22px 0 0; padding-top: 18px; border-top: 1px solid var(--border);
  color: var(--mist); font-size: 13px; line-height: 1.65; text-wrap: pretty;
}

.cta-band {
  margin: 0 48px; border: 1px solid rgba(255, 92, 31, 0.35); border-radius: 10px;
  padding: 44px; text-align: center;
  background: radial-gradient(420px 200px at 50% 0%, rgba(255, 92, 31, 0.12), transparent 70%);
}
.cta-band h2 { font-size: 30px; font-weight: 800; letter-spacing: -0.01em; text-transform: uppercase; margin: 0; }
.cta-band p { color: var(--mist); font-size: 14.5px; margin: 10px 0 0; }

/* Community strip: text left, Discord button right, stacked on narrow screens. */
.community-band {
  display: flex; align-items: center; justify-content: space-between; gap: 28px; flex-wrap: wrap;
  border: 1px solid rgba(88, 101, 242, 0.4); border-radius: 10px; padding: 26px 30px;
  background: radial-gradient(420px 200px at 15% 0%, rgba(88, 101, 242, 0.14), transparent 70%);
}
.community-copy { min-width: 0; }
.community-copy h2 { font-size: 20px; margin: 4px 0 0; }
.community-copy p { color: var(--mist); font-size: 13.5px; line-height: 1.6; margin: 8px 0 0; max-width: 620px; }
@media (max-width: 700px) {
  .community-band { padding: 22px; }
  .discord-lg { width: 100%; justify-content: center; }
}

.footer {
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  padding: 36px 48px 32px; margin-top: 56px; border-top: 1px solid var(--border-soft);
}
.footer-disclaimer {
  font-size: 11.5px; color: var(--dim); max-width: 560px; line-height: 1.55; text-align: center;
}
.footer-links { display: flex; gap: 18px; }
.footer-links a {
  font-size: 11.5px; font-weight: 600; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--mist);
}

/* ---------- data tables (roster / dragons) ---------- */
.data-table { border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.data-table .thead, .data-table .trow { display: grid; gap: 12px; padding: 12px 20px; align-items: center; }
.data-table .thead {
  background: var(--slate); font-size: 11px; font-weight: 700;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--mist);
  border-bottom: 1px solid var(--border);
}
.data-table .trow { border-bottom: 1px solid var(--row-border); font-size: 14.5px; }
.data-table .trow:last-child { border-bottom: 0; }
.table-scroll { overflow-x: auto; }

/* v3.0.1: a dragon row opens onto its Command, Vanguard skill and habit names.
   The summary keeps the grid, so a closed table looks exactly as it did. */
.dragon-row > summary {
  cursor: pointer;
  list-style: none;
}
.dragon-row > summary::-webkit-details-marker { display: none; }
.dragon-row > summary:hover { background: var(--slate-2); }
.dragon-row[open] > summary { background: var(--slate-2); border-bottom-color: transparent; }
.dragon-row:last-child > summary { border-bottom: 0; }
.dragon-row[open]:not(:last-child) { border-bottom: 1px solid var(--row-border); }
.dragon-kit {
  padding: 2px 20px 16px;
  background: var(--slate-2);
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.dragon-kit-line {
  display: grid;
  grid-template-columns: 82px 1fr;
  gap: 12px;
  align-items: baseline;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--mist-2);
}
.dragon-kit-label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ember);
}
@media (max-width: 700px) {
  .dragon-kit-line { grid-template-columns: 1fr; gap: 2px; }
}

/* ---------- calculator layout ---------- */
.appbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 28px; border-bottom: 1px solid var(--border-soft); gap: 16px;
}
.appbar-left { display: flex; align-items: center; gap: 28px; }
.app-shell { display: grid; grid-template-columns: 280px 1fr; min-height: calc(100vh - 65px); }
.sidebar {
  border-right: 1px solid var(--border-soft); padding: 20px 18px;
  display: flex; flex-direction: column; gap: 20px;
}
.roster-item {
  width: 100%; text-align: left; background: var(--slate); border: 1px solid var(--border);
  border-radius: 7px; padding: 10px 12px; display: flex; align-items: center;
  justify-content: space-between; color: var(--frost); gap: 8px;
}
.roster-item:hover { border-color: var(--border-strong); }
.roster-item.selected { border-color: rgba(255, 92, 31, 0.4); }
.roster-name { font-size: 13px; font-weight: 800; }
.roster-sub { font-family: var(--font-mono); font-size: 11.5px; color: var(--mist); margin-top: 2px; }
.roster-tag { font-size: 9px; font-weight: 800; letter-spacing: 0.08em; vertical-align: 2px; }
.add-dragon {
  width: 100%; border: 1px dashed var(--border-strong); border-radius: 7px; background: none;
  padding: 10px 12px; text-align: center; font-size: 11px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--mist);
}
.add-dragon:hover { color: var(--frost); border-color: var(--mist); }

.build-item {
  width: 100%; display: flex; justify-content: space-between; gap: 8px; background: var(--slate);
  border: 1px solid var(--border); border-radius: 6px; padding: 9px 12px;
  font-family: var(--font-mono); font-size: 12.5px; color: var(--mist); text-align: left;
}
.build-item:hover { border-color: var(--border-strong); }
.build-item.active { border-color: rgba(255, 92, 31, 0.4); color: var(--frost); }

.workspace { padding: 24px 28px; }
.workspace-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 16px; margin-bottom: 18px; flex-wrap: wrap;
}
.workspace-title { font-size: 24px; font-weight: 800; letter-spacing: -0.01em; text-transform: uppercase; margin: 4px 0 0; }
.army-power { font-family: var(--font-mono); font-size: 32px; font-weight: 600; color: var(--ember); line-height: 1.15; }
.army-delta { font-family: var(--font-mono); font-size: 12px; }

.position-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 14px; }
.position-card { padding: 16px; display: flex; flex-direction: column; gap: 12px; }
.position-card.vanguard {
  border-color: rgba(255, 92, 31, 0.45);
  box-shadow: 0 0 0 1px rgba(255, 92, 31, 0.12), 0 8px 24px rgba(255, 92, 31, 0.06);
}
.position-card.vanguard > .position-head .section-label { color: var(--ember); }
.position-head { display: flex; align-items: center; justify-content: space-between; }
.position-dragon { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.position-dragon .name { font-size: 18px; font-weight: 800; }
.position-dragon select { width: 100%; }
.stat-line { display: flex; align-items: center; justify-content: space-between; margin-bottom: 5px; }
.mini-label { font-size: 10.5px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--mist); }
.troop-select {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  background: var(--slate-3); border: 1px solid var(--border-strong);
  border-radius: 6px; padding: 8px 11px;
}
.troop-select select { border: 0; background: none; padding: 0; font-size: 12.5px; font-weight: 700; }
/* The per-dragon breakdown. Monospace at 12px on a dark card is the densest
   text on the site, so it carries mist-2 rather than mist and a little more
   leading; it is meant to be read line by line, not skimmed. */
.power-lines {
  font-family: var(--font-mono); font-size: 12px; line-height: 1.65;
  color: var(--mist-2); display: flex; flex-direction: column; gap: 3px;
}
.power-lines .row { display: flex; justify-content: space-between; }
.power-lines .total { border-top: 1px solid var(--border); padding-top: 5px; margin-top: 2px; }
.power-lines .total .k { color: var(--frost); font-weight: 600; }
.power-lines .total .v { color: var(--ember); font-weight: 600; font-size: 13px; }
/* minmax(0,1fr), not 1fr: grid items default to min-content width, so a value
   like "+12.06%" pushes the track wider than the card instead of fitting. */
.attr-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }
.attr-cell { background: var(--slate-2); border-radius: 5px; padding: 6px 8px; text-align: center; min-width: 0; }
.attr-cell .k { font-size: 9.5px; font-weight: 700; letter-spacing: 0.1em; color: var(--dim); text-transform: uppercase; }
.attr-cell .v { font-family: var(--font-mono); font-size: 13px; color: var(--mist-2); margin-top: 2px; }

/* Four calibrated percentages never fit across a ~250px upgrade card, so those
   go 2x2. Scoped to the card so the wider attribute grids elsewhere keep 4x1. */
#upgradeCards .attr-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
#upgradeCards .attr-cell { padding: 5px 6px; }
#upgradeCards .attr-cell .v { font-size: 12.5px; }
.empty-slot { color: var(--dim); font-size: 12.5px; text-align: center; padding: 24px 8px; }

.panel-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-top: 14px; }
.panel { padding: 16px 18px; }
.enemy-row { display: grid; grid-template-columns: 96px 1fr; gap: 10px; align-items: center; margin-bottom: 8px; }
.enemy-row .mini-label { color: var(--dim); }
.matchup-row {
  display: flex; align-items: center; justify-content: space-between;
  background: var(--slate-2); border-radius: 5px; padding: 7px 11px;
  font-family: var(--font-mono); font-size: 12.5px; color: var(--neutral); margin-bottom: 8px;
}
.matchup-adv { color: var(--green); }
.matchup-dis { color: var(--red); }
.matchup-neu { color: var(--neutral); }
.panel-tip { font-size: 11.5px; color: var(--mist); margin-top: 11px; line-height: 1.5; }
.display-note { font-family: var(--font-mono); font-size: 10.5px; color: var(--dim); margin-top: 10px; }

/* ---------- dialogs ---------- */
dialog {
  background: var(--slate); color: var(--frost); border: 1px solid var(--border-strong);
  border-radius: 10px; padding: 24px; width: min(420px, calc(100vw - 40px));
}
dialog::backdrop { background: rgba(4, 5, 6, 0.7); }
/* The calibration help holds a screenshot, so it gets a wider box than the
   forms and scrolls internally rather than growing past the viewport. */
.help-dialog {
  width: min(720px, calc(100vw - 32px));
  max-height: calc(100dvh - 48px);
  overflow-y: auto;
}
.help-steps { margin: 0 0 16px; padding-left: 20px; display: flex; flex-direction: column; gap: 8px; }
.help-steps li { font-size: 13px; color: var(--mist-2); line-height: 1.6; }
.help-steps b { color: var(--frost); }
.help-figure { margin: 0 0 14px; }
.help-figure img {
  display: block; width: 100%; height: auto; border-radius: 8px;
  border: 1px solid var(--border);
}
.help-figure figcaption {
  font-size: 12px; color: var(--mist); line-height: 1.55; margin-top: 8px;
}
.help-note { font-size: 12px; color: var(--dim); line-height: 1.6; margin: 0; }
.cal-stats-label {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  margin-bottom: 6px; flex-wrap: wrap;
}
.dialog-title { font-size: 16px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.02em; margin: 0 0 16px; }
.field { margin-bottom: 14px; }
.field label { display: block; margin-bottom: 6px; }
.field select, .field input { width: 100%; }
.dialog-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 20px; }
.danger-link { background: none; border: 0; color: var(--red); font-size: 11.5px; padding: 0; margin-right: auto; }
/* Secondary in-dialog action (forgot password): readable, never competes with
   the primary button. */
.link-quiet {
  background: none; border: 0; padding: 0; font-family: inherit;
  font-size: 11.5px; color: var(--mist); text-decoration: underline; cursor: pointer;
}
.link-quiet:hover { color: var(--ember); }

/* toast */
.toast {
  position: fixed; left: 50%; bottom: 28px; transform: translateX(-50%);
  background: var(--slate-3); border: 1px solid var(--border-strong); border-radius: 7px;
  color: var(--frost); font-size: 12.5px; padding: 10px 18px; opacity: 0;
  pointer-events: none; transition: opacity 0.25s; z-index: 60;
}
.toast.show { opacity: 1; }

/* mobile bottom tab bar */
.tabbar {
  display: none; position: fixed; left: 0; right: 0; bottom: 0;
  border-top: 1px solid var(--border-soft); background: #0d1013; z-index: 50;
}
.tabbar a {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 12px 0 14px; color: var(--mist);
  font-size: 9.5px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
}
.tabbar a.active { color: var(--ember); }
.tabbar a svg [stroke] { stroke: currentColor; }
.tabbar a svg [fill]:not([fill='none']) { fill: currentColor; }

/* mobile nav drawer (homepage) */
.mobile-nav { display: none; border-bottom: 1px solid var(--border-soft); padding: 8px 20px 16px; }
.mobile-nav.open { display: flex; flex-direction: column; gap: 4px; }
.mobile-nav a {
  padding: 10px 4px; color: var(--mist); font-size: 13px; font-weight: 700;
  letter-spacing: 0.06em; text-transform: uppercase;
}

/* ================= Step 2 · mobile (390 reference) ================= */
@media (max-width: 900px) {
  .topbar { padding: 16px 20px; }
  /* Hide nav + the CTA (it lives in the drawer) so the hamburger fits. */
  .topnav, .topbar > .btn, .topbar .btn-primary { display: none; }
  .hamburger { display: block; }

  .hero { grid-template-columns: 1fr; gap: 32px; padding: 40px 20px 36px; }
  .hero h1 { font-size: 38px; line-height: 1; }
  .hero-sub { font-size: 15px; }
  .hero-ctas { flex-direction: column; }
  .hero-ctas .btn { width: 100%; padding: 16px 0; }
  .hero-note { text-align: center; }
  .preview-row { grid-template-columns: 1fr auto; row-gap: 4px; }
  .preview-row .pos-label { grid-column: 1 / -1; }

  .section { padding: 36px 20px; }
  .section h2 { font-size: 24px; margin-bottom: 18px; }
  .explain-card { padding: 20px 18px; }
  .explain-title { font-size: 18px; margin-bottom: 16px; }
  .explain-steps li { grid-template-columns: 24px 1fr; gap: 10px; }
  .cta-band { margin: 0 20px; padding: 28px 22px; }
  .cta-band h2 { font-size: 22px; }
  .footer { flex-direction: column; padding: 32px 20px 92px; text-align: center; }

  .appbar { padding: 14px 20px; }
  .appbar .seg-tabs { display: none; }
  .app-shell { grid-template-columns: 1fr; min-height: 0; }
  .sidebar { border-right: 0; border-bottom: 1px solid var(--border-soft); }
  .workspace { padding: 16px 16px 96px; }
  .position-grid, .panel-grid { grid-template-columns: 1fr; }
  .army-power { font-size: 28px; }
  .tabbar { display: flex; }

  .data-table .thead, .data-table .trow { padding: 11px 14px; gap: 8px; }
}

/* ---------- war room ---------- */
/* v3.1.5 — a two-way switch replaces the five mode cards. Two options that
   trade against each other read as one control; five that mostly differed in
   troop presets read as a menu of things to be unsure about. */
.strategy-switch {
  display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
  background: var(--slate); border: 1px solid var(--border);
  border-radius: 10px; padding: 6px;
}
.strategy-opt {
  display: flex; flex-direction: column; gap: 5px; text-align: left;
  background: transparent; border: 1px solid transparent; border-radius: 7px;
  padding: 12px 14px; color: var(--mist-2); cursor: pointer;
  transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.strategy-opt:hover { background: var(--slate-2); color: var(--frost); }
.strategy-opt.active {
  background: var(--slate-3); border-color: rgba(255, 92, 31, 0.45);
  color: var(--frost); box-shadow: 0 0 0 1px rgba(255, 92, 31, 0.12);
}
.strategy-name {
  font-size: 13.5px; font-weight: 700; letter-spacing: 0.01em; color: var(--frost);
}
.strategy-opt.active .strategy-name { color: var(--ember); }
/* The recommendation, on the card rather than only in the hint underneath. */
.strategy-rec {
  margin-left: 8px; padding: 2px 7px; border-radius: 999px; vertical-align: middle;
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--green); background: rgba(78, 203, 113, 0.12);
  border: 1px solid rgba(78, 203, 113, 0.35);
}
.strategy-desc { font-size: 12.5px; line-height: 1.55; color: var(--mist); }
.strategy-opt.active .strategy-desc { color: var(--mist-2); }
@media (max-width: 700px) {
  .strategy-switch { grid-template-columns: 1fr; }
  .strategy-desc { font-size: 12px; }
}
/* v3.1.7 — at one army both strategies solve the identical problem, so the
   control is disabled rather than left live to imply a choice that is not
   there. Dimmed, not hidden: a control that disappears reads as a bug, and the
   note underneath says why it is off. */
.strategy-switch.locked { opacity: 0.5; }
.strategy-switch.locked .strategy-opt { cursor: default; }
.strategy-opt[disabled] { pointer-events: none; }

/* ---------- war room: count advice + scenario map (v3.1.7) ---------- */
.count-advice:empty { display: none; }
.count-advice {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 10px; padding: 11px 14px; border-radius: 8px;
  font-size: 12.5px; line-height: 1.6; color: var(--mist-2);
  border: 1px solid var(--border); border-left-width: 3px;
  background: var(--slate-2);
}
.count-advice b { color: var(--frost); }
.count-advice span { flex: 1 1 320px; }
/* The warning is the one that interrupts, so it takes the ember. The locked
   note is only an explanation, and stays quiet. */
.count-advice.warn {
  border-color: rgba(255, 92, 31, 0.35); background: rgba(255, 92, 31, 0.06);
}
.count-advice.locked { color: var(--mist); }

/* Force affinity (v3.7.6): a toggle plus the sentence that keeps it honest. */
.force-affinity {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line);
}
.aff-toggle {
  display: inline-flex; align-items: center; gap: 8px; flex: none;
  font: inherit; font-size: 12.5px; font-weight: 600; color: var(--mist-2);
  background: transparent; border: 1px solid var(--border); border-radius: 7px;
  padding: 6px 12px; cursor: pointer;
}
.aff-toggle:hover:not([disabled]) { border-color: var(--mist); color: var(--frost); }
.aff-toggle.on { color: var(--ember); border-color: rgba(255, 92, 31, 0.45); background: var(--slate-3); }
.aff-toggle[disabled] { opacity: 0.55; cursor: default; }
.aff-box {
  display: inline-flex; align-items: center; justify-content: center;
  width: 14px; height: 14px; border-radius: 4px; font-size: 10px; line-height: 1;
  border: 1px solid var(--border); color: var(--ember);
}
.aff-toggle.on .aff-box { border-color: var(--ember); }
.aff-note { font-size: 12px; line-height: 1.55; color: var(--mist); flex: 1 1 260px; }

/* The even-split alternative (v3.7.6), stated with its cost before the click. */
.even-switch {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  flex-wrap: wrap; margin-bottom: 12px; padding: 12px 16px; border-radius: 8px;
  border: 1px solid var(--border); border-left: 3px solid var(--ember);
  background: var(--slate-2);
}
.even-switch-copy { font-size: 12.5px; line-height: 1.6; color: var(--mist); flex: 1 1 320px; }
.even-switch-copy b { color: var(--frost); display: block; margin-bottom: 2px; }

/* Full-affinity marker on an army card. */
.army-allgreen {
  display: inline-flex; align-items: center; gap: 5px; padding: 2px 8px;
  border-radius: 999px; font-size: 10.5px; font-weight: 700; letter-spacing: 0.03em;
  text-transform: uppercase; color: var(--green);
  background: rgba(78, 203, 113, 0.12); border: 1px solid rgba(78, 203, 113, 0.35);
}

/* The advisor's scope switch is the same control as the War Room's strategy
   switch, so it reuses it rather than growing a second look for the same
   two-way choice. */
.scope-switch { margin-top: 12px; }
@media (max-width: 700px) {
  .scenario-grid { grid-template-columns: max-content repeat(5, 1fr); }
  .scenario-row-label { font-size: 11.5px; }
  .count-advice { font-size: 12px; }
}

/* ---------- de-emphasized power + war room breakdown ---------- */
/* The vanguard's flank skill: which lane it buffs is the one verified rule
   deciding placement now that role-based lane fit is gone (v3.1.5), so it is
   readable rather than a caption. */
.flank-skill {
  font-size: 12px; line-height: 1.6; color: var(--mist-2);
}
.flank-skill .mini-label { color: var(--ember-soft); }
@media (max-width: 700px) { .flank-skill { font-size: 12.5px; } }

.power-est {
  font-family: var(--font-mono); font-size: 11px; color: var(--dim); margin-top: 4px;
}
.power-lines.power-muted, .power-lines .row.power-muted { color: var(--dim); }
.power-lines.power-muted .total .v { color: var(--mist); font-size: 12px; }
.power-lines.power-muted .total .k { color: var(--mist); }
.army-detail { margin-top: 12px; border-top: 1px solid var(--border); }
.army-detail summary {
  cursor: pointer; padding: 10px 0 2px; font-size: 12px; font-weight: 700;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--mist);
  list-style: none;
}
.army-detail summary::before { content: '▸ '; color: var(--ember); }
.army-detail[open] summary::before { content: '▾ '; }
.army-detail summary::-webkit-details-marker { display: none; }
.army-detail-body {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; padding: 12px 0 4px;
}
.army-detail-body > div:last-child { grid-column: 1 / -1; }
.synergy-line {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  font-size: 12.5px; color: var(--mist-2); padding: 4px 0;
  border-bottom: 1px solid var(--row-border);
}
/* The description side must be allowed to shrink and wrap, or a long habit line
   pushes the flex row wider than the viewport (v2.8: the uptime marker made this
   reachable at 390px). min-width:0 is what lets a flex item wrap at all. */
.synergy-line > span:first-child { min-width: 0; overflow-wrap: anywhere; }
.synergy-line > .num { flex: 0 0 auto; }
.synergy-line:last-child { border-bottom: 0; }
/* v2.8: uptime marker on round-gated habits. Muted — it explains a small
   contribution, it is not the point of the line. Deliberately NOT nowrap: at
   390px that was enough to overflow the page by 5px. */
.synergy-uptime { color: var(--dim); font-size: 11px; }

/* v2.9.2: marks a breakdown line as coming from the Command rather than a
   habit. Quiet on purpose: it explains where the number is from, it is not a
   feature to advertise. */
.kit-tag {
  color: var(--mist-2);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border: 1px solid var(--line);
  border-radius: 7px;
  padding: 0 4px;
}
@media (max-width: 900px) {
  .army-detail-body { grid-template-columns: 1fr; }
}

/* ---------- v2.1: global footer, score bars, job progress ---------- */
.site-footer {
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  padding: 32px 20px 40px; margin-top: 48px; border-top: 1px solid var(--border-soft);
  text-align: center;
}
.site-footer p { font-size: 11.5px; color: var(--dim); max-width: 520px; line-height: 1.55; margin: 0; }
.score-bar { height: 5px; border-radius: 2.5px; background: var(--border-strong); overflow: hidden; min-width: 120px; }
.score-bar > span { display: block; height: 100%; background: var(--ember); border-radius: 2.5px; }
.job-progress {
  display: flex; align-items: center; gap: 12px; padding: 20px;
  font-family: var(--font-mono); font-size: 12.5px; color: var(--mist);
}
.job-progress .score-bar { flex: 1; }
@media (max-width: 900px) { .site-footer { padding-bottom: 96px; } }

/* ---------- v2.2: verify banner + cookie notice ---------- */
.notice-bar {
  display: flex; align-items: center; gap: 14px; justify-content: center;
  padding: 9px 20px; background: rgba(255, 92, 31, 0.10);
  border-bottom: 1px solid rgba(255, 92, 31, 0.35);
  font-size: 12.5px; color: var(--mist-2);
}
.notice-close { background: none; border: 0; color: var(--mist); font-size: 16px; padding: 2px 8px; }
.cookie-notice {
  position: fixed; left: 16px; bottom: 16px; z-index: 70;
  display: flex; align-items: center; gap: 12px; max-width: 420px;
  background: var(--slate-3); border: 1px solid var(--border-strong);
  border-radius: 8px; padding: 10px 14px; font-size: 12px; color: var(--mist-2);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.4);
}
@media (max-width: 900px) { .cookie-notice { left: 12px; right: 12px; bottom: 84px; } }

.notice-bar.notice-ok { background: rgba(78, 203, 113, 0.10); border-bottom-color: rgba(78, 203, 113, 0.35); }
.notice-bar.notice-error { background: rgba(224, 91, 79, 0.10); border-bottom-color: rgba(224, 91, 79, 0.40); }
.notice-bar span { max-width: 820px; line-height: 1.5; }

/* ---------- v2.3: inline roster editor ---------- */
.roster-toolbar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 12px 14px; margin-bottom: 12px;
}
.roster-toolbar input[type="search"] { min-width: 220px; flex: 1 1 220px; }
.toolbar-check {
  display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px;
  color: var(--mist-2); white-space: nowrap;
}
.save-state { font-family: var(--font-mono); font-size: 11.5px; margin-top: 4px; min-height: 16px; }
.save-state.saving { color: var(--mist); }
.save-state.saved { color: var(--green); }
.save-state.error { color: var(--red); }

.bulk-bar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  background: rgba(255, 92, 31, 0.08); border: 1px solid rgba(255, 92, 31, 0.35);
  border-radius: 8px; padding: 10px 14px; margin-bottom: 12px; font-size: 12.5px;
}
.bulk-bar label { display: inline-flex; align-items: center; gap: 6px; color: var(--mist-2); }
.bulk-bar input { width: 68px; padding: 5px 8px; }

.roster-head, .roster-row {
  display: grid;
  grid-template-columns: 26px 26px minmax(170px, 1.3fr) 112px 74px minmax(180px, 1fr) minmax(220px, 1.05fr);
  align-items: center; gap: 12px;
}
.roster-head {
  padding: 0 14px 8px; font-size: 11px; font-weight: 700; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--mist);
}

/* Sortable column headers (v2.7.5). The header is the affordance; the toolbar
   dropdown covers the keys that have no column of their own. */
.sort-head {
  display: inline-flex; align-items: center; gap: 5px;
  background: none; border: 0; padding: 2px 0; min-width: 0;
  font: inherit; letter-spacing: inherit; text-transform: inherit;
  color: var(--mist); cursor: pointer; text-align: left;
}
.sort-head:hover { color: var(--mist-2); }
.sort-head.active { color: var(--ember); }
.sort-arrow { font-size: 10px; line-height: 1; }
.sort-dir { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.sort-dir-arrow { font-size: 11px; }

/* Re-sort (v2.8.3). The list holds its order while you edit, so this button is
   the only thing that re-shuffles it. Muted while the order still matches the
   data, ember once an edit has moved a row out of place. */
.resort { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.resort-icon { font-size: 12px; line-height: 1; display: inline-block; }
.resort:not(.stale) { color: var(--dim); }
.resort.stale {
  color: var(--ember);
  border-color: rgba(255, 92, 31, 0.55);
  background: rgba(255, 92, 31, 0.08);
}
.resort.stale .resort-icon { animation: resort-nudge 2.4s ease-in-out infinite; }
@keyframes resort-nudge {
  0%, 84%, 100% { transform: rotate(0deg); }
  92% { transform: rotate(180deg); }
}
@media (prefers-reduced-motion: reduce) {
  .resort.stale .resort-icon { animation: none; }
}

.roster-troops { min-width: 0; text-align: right; }
.roster-troops .roster-capacity.none { color: var(--dim); }
/* Desktop has the TROOPS column header to name this number; mobile hides the
   headers, so the unit has to travel with the value. */
.cap-unit { display: none; }
.roster-row {
  background: var(--slate); border: 1px solid var(--border); border-radius: 8px;
  padding: 9px 14px; margin-bottom: 6px;
}
.roster-row.owned { border-color: var(--border-strong); }
.roster-row.selected { border-color: rgba(255, 92, 31, 0.5); }
.roster-row:not(.owned) .roster-name .name { color: var(--mist); }
.roster-row input[type="checkbox"] { width: 15px; height: 15px; accent-color: var(--ember); }

.roster-name { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; min-width: 0; }
.roster-name .name { font-size: 14.5px; font-weight: 800; }
.roster-name .breed { font-size: 10.5px; color: var(--dim); }

.habit-toggle {
  display: flex; align-items: center; gap: 8px; background: var(--slate-2);
  border: 1px solid var(--border); border-radius: 6px; padding: 5px 10px;
  color: var(--mist-2); font-size: 12px; width: 100%;
}
.habit-toggle:hover { border-color: var(--border-strong); }
.habit-toggle.open { border-color: rgba(255, 92, 31, 0.4); color: var(--ember-soft); }
.habit-toggle::before { content: '▸'; color: var(--ember); font-size: 10px; }
.habit-toggle.open::before { content: '▾'; }
.habit-next { font-size: 10.5px; color: var(--dim); }

.star-pick { display: flex; align-items: center; gap: 1px; }
.star-pick .star {
  background: none; border: 0; padding: 0 1px; font-size: 15px; line-height: 1;
  color: var(--border-strong);
}
.star-pick .star.on { color: var(--ember); }
.star-pick:not(.disabled) .star:hover { color: var(--ember-soft); }
.star-pick .star:disabled { cursor: default; }
.star-count { font-family: var(--font-mono); font-size: 10.5px; color: var(--dim); margin-left: 7px; }

.roster-level { display: flex; align-items: center; gap: 7px; }
.roster-level .step {
  background: var(--slate-2); border: 1px solid var(--border); border-radius: 5px;
  color: var(--frost); width: 24px; height: 24px; font-size: 14px; line-height: 1; padding: 0;
}
.roster-level .step:disabled { color: var(--dim); cursor: default; }
.roster-level input[type="range"] { flex: 1; min-width: 70px; accent-color: var(--ember); }
.roster-level .level-num {
  width: 54px; padding: 4px 6px; text-align: center;
  font-family: var(--font-mono); font-size: 12px;
}

.habit-drawer {
  grid-column: 1 / -1; margin-top: 8px; padding: 12px 14px;
  background: var(--slate-2); border: 1px solid var(--border); border-radius: 7px;
}
.habit-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 5px 0; border-bottom: 1px solid var(--row-border);
}
.habit-row:last-of-type { border-bottom: 0; }
.habit-row.locked .habit-name { color: var(--dim); }
.habit-name { font-size: 12.5px; color: var(--mist-2); }
.rank-pick { display: flex; gap: 4px; flex: none; }
.rank-pick .rank {
  width: 26px; height: 24px; border-radius: 5px; background: var(--slate-3);
  border: 1px solid var(--border); color: var(--mist); font-size: 11.5px;
  font-family: var(--font-mono); padding: 0;
}
.rank-pick .rank.on { background: var(--ember); border-color: var(--ember); color: var(--night); font-weight: 700; }
.rank-pick .rank:disabled { color: var(--dim); background: var(--slate-2); cursor: default; }
.habit-hint { font-size: 11.5px; color: var(--dim); line-height: 1.55; margin-top: 10px; }

@media (max-width: 900px) {
  /* No column titles to head on mobile, but the two "all shown" toggles still
     need a home, so the head becomes a labelled strip instead of a grid. */
  .roster-head { display: flex; flex-wrap: wrap; gap: 18px; padding: 0 2px 10px; letter-spacing: 0.06em; }
  /* Column titles have no grid to head on mobile. Sorting stays reachable through
     the toolbar dropdown + direction button, which are better touch targets than
     an 11px header would be anyway. */
  .roster-head > span, .roster-head .sort-head { display: none; }
  .roster-row {
    grid-template-columns: 22px 22px 1fr; row-gap: 8px; padding: 12px;
  }
  .roster-habits, .roster-troops, .roster-stars, .roster-level { grid-column: 1 / -1; }
  .roster-troops { text-align: left; }
  .cap-unit { display: inline; }
  .roster-level input[type="range"] { min-width: 0; }
}

.habit-row.locked .rank-pick { opacity: 0.45; }
.roster-row:hover .sel-check, .roster-row.selected .sel-check { opacity: 1; }

/* ---------- footer: one-line disclaimer, Ko-fi accent, copyright ---------- */
.site-footer p.site-disclaimer {
  max-width: none;          /* one line on desktop (beats .site-footer p's 520px) */
  white-space: nowrap;
  font-size: 11.5px;
}
/* Footer call-to-actions: Discord and Ko-fi share one row, both as buttons, so
   neither reads as trailing the link groups above them. */
.site-footer-cta { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; }
.kofi-link {
  color: var(--night) !important;
  background: var(--ember);
  border-radius: 5px;
  padding: 5px 12px;
}
.kofi-link:hover { background: var(--ember-soft); color: var(--night) !important; }

/* Discord brand blurple, the one place the site steps outside its own palette:
   the button has to be recognizable as Discord at a glance. */
.discord-link {
  display: inline-flex; align-items: center; gap: 7px;
  color: #fff !important; background: #5865f2;
  border-radius: 5px; padding: 5px 12px; font-weight: 600;
}
.discord-link:hover { background: #4752c4; color: #fff !important; }
.discord-link svg { flex: none; }
.discord-lg { padding: 11px 20px; font-size: 14px; border-radius: 7px; white-space: nowrap; }
.site-copyright {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--dim);
}
/* Narrow screens: let it wrap rather than force a horizontal scrollbar. */
@media (max-width: 780px) {
  .site-footer p.site-disclaimer { white-space: normal; max-width: 420px; }
}

/* ---------- v2.3: Database menu, tier list, roster select mode ---------- */
.nav-secondary {
  display: flex; align-items: center; gap: 14px; margin-left: 18px;
  padding-left: 18px; border-left: 1px solid var(--border);
}
.db-menu { position: relative; }
.db-toggle, .nav-plain {
  background: none; border: 0; padding: 6px 2px; color: var(--mist);
  font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  font-family: inherit;
}
.db-toggle::after { content: ' ▾'; font-size: 9px; }
.db-toggle:hover, .nav-plain:hover, .db-toggle.active, .nav-plain.active { color: var(--frost); }
.db-dropdown {
  display: none; position: absolute; top: 100%; left: -10px; z-index: 60; min-width: 150px;
  background: var(--slate-3); border: 1px solid var(--border-strong); border-radius: 7px;
  padding: 5px; margin-top: 6px; box-shadow: 0 14px 34px rgba(0, 0, 0, 0.45);
}
.db-dropdown.open { display: block; }
.db-dropdown a {
  display: block; padding: 8px 12px; border-radius: 5px; color: var(--mist-2);
  font-size: 12.5px; font-weight: 600;
}
.db-dropdown a:hover { background: var(--slate-2); color: var(--frost); }

/* Bulk-select checkbox: neutral outline, never confusable with owned (orange) */
.roster-row input[type="checkbox"].sel-check {
  accent-color: var(--mist);
  opacity: 0.8;
}
.roster-row:hover .sel-check, .roster-row.selected .sel-check { opacity: 1; }
.roster-head.no-select-col, .roster-row.no-select-col {
  grid-template-columns: 26px 0 minmax(170px, 1.3fr) 112px 74px minmax(180px, 1fr) minmax(220px, 1.05fr);
}

/* "All shown" toggles in the head: same colour coding as the row checkboxes,
   so the ownership one reads orange and the mass-select one stays neutral. */
.head-check { display: inline-flex; align-items: center; gap: 7px; cursor: pointer; min-width: 0; }
.roster-head input[type="checkbox"] { width: 15px; height: 15px; accent-color: var(--ember); }
.roster-head input[type="checkbox"].sel-check { accent-color: var(--mist); }
.roster-head input[type="checkbox"]:disabled { opacity: 0.35; cursor: default; }
.head-check-label { display: none; }              /* desktop: the column IS the label */
/* Must stay a grid item when Mass Action is off, or the column titles all shift
   one column left and DRAGON lands on top of HABITS. The rows keep an empty
   <span> for the same reason. */
.roster-head.no-select-col .head-check.sel { visibility: hidden; }
/* Mobile drops the column titles, so the toggles have to name themselves. That
   labelled strip sits right under the bulk bar, making its button a duplicate.
   No columns to line up with here, so the hidden toggle can leave the flow. */
@media (max-width: 900px) {
  .head-check-label { display: inline; }
  #bulkSelectAll { display: none; }
  .roster-head.no-select-col .head-check.sel { display: none; }
}
.btn:disabled { opacity: 0.45; cursor: default; }

/* ---------- account settings ----------
   v2.6 put these on My Roster behind a <details>; v3.7 moved them to their own
   page, so the block, its summary row and its chevron are gone. The chips
   survived the move: they are the checklist, and they now appear both on
   /settings and on the pointer card the roster keeps. */

/* One chip per configured thing. The single grey line this replaced ran
   "North · capacity +1 750 and +3.49%" together and was hard to scan. */
.settings-chip {
  display: inline-flex; align-items: baseline; gap: 6px;
  background: var(--slate-3); border: 1px solid var(--border); border-radius: 999px;
  padding: 3px 10px; font-size: 11.5px; color: var(--mist-2);
  font-weight: 400; text-transform: none; letter-spacing: 0;
}
.settings-chip-key {
  font-size: 9.5px; font-weight: 700; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--dim);
}
.settings-chip-val { font-family: var(--font-mono); color: var(--frost); }
.settings-chip.on { border-color: rgba(255, 92, 31, 0.4); }
.settings-chip.off { color: var(--mist); }
.settings-chip.off .settings-chip-val { color: var(--mist); }
/* Sub-heading inside a settings card, one step below .settings-h2. */
.settings-h {
  font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.12em;
  margin: 0 0 10px; color: var(--mist);
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
}
.settings-p { color: var(--mist); font-size: 12.5px; line-height: 1.6; margin: 0 0 14px; max-width: 700px; }

/* v2.7.1: total troops a march carries, in the army header next to the score. */
/* Army score row. Was an inline flex with a fixed 14px gap, which overflowed a
   390px viewport by 5px once every element was present (v2.8). Wraps now, and
   the caption is allowed to shrink. */
.army-score-row { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; min-width: 0; }
/* v3.0.1: bar, percentage and caption are one column. Putting the caption
   beside the bar made three things compete for one row, so the caption either
   wrapped over several lines or squeezed the bar; stacked, it always has the
   full width of the meter and always fits on one line. */
.army-score-meter {
  flex: 1 1 250px; min-width: 0;
  display: flex; flex-direction: column; gap: 3px; line-height: 1.25;
}
.army-score-line { display: flex; align-items: center; gap: 10px; }
.army-score-line .score-bar { flex: 1 1 auto; min-width: 50px; }
.army-score-pct { font-size: 18px; color: var(--ember); flex: 0 0 auto; }
.army-score-note { font-size: 10.5px; color: var(--dim); white-space: nowrap; text-align: right; }
@media (max-width: 460px) {
  .army-score-row { gap: 10px; }
}

/* Measured combat role (v2.9). Ember when the dragon is standing in the lane
   its role prefers, muted when it is there on its own merits instead. */
.role-badge {
  display: inline-block; align-self: flex-start;
  font-size: 10px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  padding: 2px 7px; border-radius: 4px; margin-top: -2px;
  color: var(--mist); background: var(--slate-3); border: 1px solid var(--border-strong);
}
.role-badge.fits {
  color: var(--ember); background: rgba(255, 92, 31, 0.10);
  border-color: rgba(255, 92, 31, 0.45);
}

.army-troops {
  display: inline-flex; align-items: baseline; gap: 7px;
  background: var(--slate-3); border: 1px solid var(--border-strong);
  border-radius: 6px; padding: 4px 10px;
}
.army-troops-key {
  font-size: 9.5px; font-weight: 700; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--mist);
}
.army-troops-val { font-size: 13px; color: var(--frost); }

/* Inline counterpart to the warning dialog: shown on any result computed with
   empty account settings, including the War Room's automatic first run. */
.uncalibrated-note {
  border: 1px solid rgba(255, 92, 31, 0.35); border-left-width: 3px; border-radius: 8px;
  padding: 12px 16px; margin-bottom: 12px; font-size: 12.5px; color: var(--mist-2);
  line-height: 1.6; background: rgba(255, 92, 31, 0.06);
}
.uncalibrated-note b { color: var(--frost); }

/* "Nothing calibrated" warning before an optimization runs. */
.warn-dialog { width: min(500px, calc(100vw - 32px)); }
.warn-dialog .warn-body {
  font-size: 13px; color: var(--mist-2); line-height: 1.65; margin: 0 0 12px;
}
.warn-dialog .warn-body b { color: var(--frost); }
.warn-skip {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 12px; color: var(--mist); margin-top: 4px; cursor: pointer;
}
.warn-skip input { width: 14px; height: 14px; accent-color: var(--ember); }

/* v2.7: troop-capacity settings. Two distinct sources side by side, kept
   visually apart from the stat percentages above (different mechanic). */
.capacity-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 12px; }
.capacity-block {
  background: var(--slate-2); border: 1px solid var(--border); border-radius: 8px; padding: 14px 16px;
}
.capacity-block .mini-label { margin-bottom: 10px; }
.capacity-nodes { display: flex; flex-direction: column; gap: 7px; }
.capacity-node {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  font-size: 12.5px; color: var(--mist-2);
}
.capacity-node-name { display: inline-flex; align-items: baseline; gap: 8px; min-width: 0; }
.capacity-node-worth { font-size: 10.5px; color: var(--dim); }
.capacity-node select { width: 62px; padding: 4px 8px; }
.capacity-level { display: flex; align-items: center; gap: 10px; font-size: 12.5px; color: var(--mist-2); }
.capacity-level input { width: 78px; padding: 5px 8px; }
.capacity-total { font-size: 11.5px; color: var(--mist); margin-top: 10px; }
.capacity-example { font-size: 11.5px; color: var(--dim); margin-left: auto; }
/* Per-dragon capacity in the roster list */
.roster-capacity { display: block; font-size: 10.5px; color: var(--dim); margin-top: 4px; }
@media (max-width: 700px) {
  .capacity-example { margin-left: 0; flex-basis: 100%; }
}

/* ---------- the Account settings page ----------
   Rebuilt in v3.7.1. The first version was five cards of five different shapes
   stacked down the page, each with its own Save button and save indicator, and
   it read as a pile rather than a page. What follows gives every section the
   same skeleton (step number, title, what it affects, help button, controls),
   moves the checklist into a rail that is always on screen, and drops the Save
   buttons entirely: the page writes as you type, like My Roster always has.

   The v2.6 faction picker (.faction-card and friends) went earlier, with the
   mechanic it expressed. Seats of Power are toggles, any number of them, so
   they never shared a shape with a one-of-three choice. */

.settings-page { max-width: 1180px; margin: 0 auto; padding: 26px 22px 90px; }

/* Masthead: purpose on the left, progress and the one save indicator right. */
.settings-masthead {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 26px; flex-wrap: wrap; margin-bottom: 22px;
}
.settings-masthead-text { flex: 1 1 460px; min-width: 0; }
.settings-lede {
  font-size: 12.5px; color: var(--mist); line-height: 1.65;
  margin: 6px 0 0; max-width: 660px;
}
.settings-masthead-side {
  display: flex; flex-direction: column; align-items: flex-end; gap: 10px;
  flex: 0 0 auto; min-width: 210px;
}
.settings-progress { width: 100%; }
.settings-progress-bar {
  height: 5px; border-radius: 3px; background: var(--slate-3);
  border: 1px solid var(--border); overflow: hidden;
}
.settings-progress-bar > span {
  display: block; height: 100%; width: 0; background: var(--ember);
  transition: width 0.35s ease;
}
.settings-progress-label { font-size: 11px; color: var(--mist); margin-top: 6px; text-align: right; }

/* Two columns: a rail that stays put, and the sections. */
.settings-layout { display: grid; grid-template-columns: 232px minmax(0, 1fr); gap: 22px; align-items: start; }
.settings-rail {
  position: sticky; top: 18px; display: flex; flex-direction: column; gap: 4px;
  background: var(--slate-3); border: 1px solid var(--border); border-radius: 10px; padding: 8px;
}
.rail-item {
  display: flex; align-items: center; gap: 11px; padding: 9px 10px;
  border-radius: 7px; color: var(--mist-2); min-width: 0;
}
.rail-item:hover { background: var(--slate-2); }
.rail-dot {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--slate-2); border: 1px solid var(--border-strong);
  font-size: 11px; font-weight: 800; color: var(--mist);
  font-family: var(--font-mono);
}
.rail-item.on .rail-dot { background: var(--ember); border-color: var(--ember); color: var(--night); }
.rail-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.rail-label { font-size: 12.5px; font-weight: 700; color: var(--frost); }
.rail-value { font-size: 10.5px; color: var(--dim); }
.rail-item.on .rail-value { color: var(--mist); }

.settings-main { min-width: 0; display: flex; flex-direction: column; gap: 14px; }

/* One skeleton, five sections. */
.settings-section {
  background: var(--slate-3); border: 1px solid var(--border); border-radius: 10px;
  padding: 20px 22px; scroll-margin-top: 18px; transition: opacity 0.2s, border-color 0.2s;
}
.settings-section-head {
  display: flex; align-items: flex-start; gap: 14px; margin-bottom: 12px; flex-wrap: wrap;
}
.settings-step {
  flex: 0 0 auto; width: 26px; height: 26px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--slate-2); border: 1px solid var(--border-strong);
  font-family: var(--font-mono); font-size: 12px; font-weight: 700; color: var(--mist);
}
.settings-section-title { flex: 1 1 260px; min-width: 0; }
.settings-section-title h2 {
  font-size: 17px; font-weight: 800; letter-spacing: 0.02em; color: var(--frost);
  margin: 0; display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
}
.settings-affects { font-size: 11.5px; color: var(--dim); margin: 3px 0 0; line-height: 1.5; }
.settings-section .help-btn { flex: 0 0 auto; }
.settings-note { font-size: 11.5px; color: var(--dim); margin: 14px 0 0; line-height: 1.55; }

/* Attribute upgrades: entered in place, one panel per breed. */
.breed-panels { display: grid; grid-template-columns: repeat(auto-fit, minmax(310px, 1fr)); gap: 12px; }
.breed-panel {
  background: var(--slate-2); border: 1px solid var(--border); border-radius: 9px; padding: 14px 15px;
}
.breed-panel.is-set { border-color: rgba(255, 92, 31, 0.35); }
.breed-panel-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 10px;
}
.breed-panel-name { font-size: 14px; font-weight: 800; color: var(--frost); }
.breed-panel-state { font-size: 10px; color: var(--dim); }
.breed-panel.is-set .breed-panel-state { color: var(--green); }

.entry-grid { display: flex; flex-direction: column; gap: 5px; }
.entry-grid-head, .entry-grid-row {
  display: grid; grid-template-columns: 40px minmax(0, 1fr) minmax(0, 1fr) 74px;
  gap: 8px; align-items: center;
}
.entry-grid-head {
  font-size: 9.5px; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--dim); padding: 0 2px 2px;
}
.entry-label {
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--mist);
}
.entry-grid-row input { width: 100%; min-width: 0; padding: 5px 8px; font-size: 12.5px; }
.entry-out { font-size: 11.5px; color: var(--mist); text-align: right; }
.entry-out.is-live { color: var(--ember); }

/* Breed damage and troop research share one table shape. */
.entry-table { display: flex; flex-direction: column; gap: 6px; }
.entry-row {
  display: grid; grid-template-columns: minmax(130px, 1fr) 118px 118px minmax(170px, 1fr);
  gap: 12px; align-items: center;
  background: var(--slate-2); border: 1px solid var(--border); border-radius: 7px; padding: 8px 12px;
}
.entry-row-head {
  background: none; border: 0; padding: 0 14px 0 12px;
  font-size: 10px; letter-spacing: 0.11em; text-transform: uppercase; color: var(--dim);
}
.entry-name {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 13px; font-weight: 700; color: var(--mist-2); min-width: 0;
}
.entry-row input { width: 100%; min-width: 0; padding: 5px 8px; }
.entry-applied {
  display: flex; flex-direction: column; gap: 2px;
  font-size: 11.5px; color: var(--mist-2); text-align: right;
}
.entry-from-seat { font-size: 10px; color: var(--ember); }

/* War Tactics calculator: a helper under the troop research table, folded away
   because the battle-report route is both easier and more complete. */
.tactics-block { margin-top: 16px; border-top: 1px solid var(--border); padding-top: 14px; }
.tactics-summary {
  cursor: pointer; font-size: 12.5px; font-weight: 700; color: var(--ember-soft);
  list-style: none; display: flex; align-items: center; gap: 8px;
}
.tactics-summary::-webkit-details-marker { display: none; }
.tactics-summary::before { content: '▸'; font-size: 10px; }
.tactics-block[open] .tactics-summary::before { content: '▾'; }
.tactics-summary:hover { color: var(--ember); }
.tactics-block > .settings-p { margin-top: 12px; }
.tactics-grid { display: flex; flex-direction: column; gap: 6px; }
.tactics-row {
  display: grid; grid-template-columns: minmax(120px, 1fr) repeat(4, 74px) minmax(140px, 0.9fr);
  gap: 10px; align-items: center;
  background: var(--slate-2); border: 1px solid var(--border); border-radius: 7px; padding: 8px 12px;
}
.tactics-row-head {
  background: none; border: 0; padding: 0 14px 0 12px;
  font-size: 10px; letter-spacing: 0.11em; text-transform: uppercase; color: var(--dim);
}
.tactics-node { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
/* The column heading carries the node name on wide screens; this repeats it
   inside each cell once the heading row is dropped. */
.tactics-node-label { display: none; font-size: 9.5px; text-transform: uppercase; color: var(--dim); }
.tactics-node select { width: 100%; padding: 4px 6px; }
.tactics-out { font-size: 11.5px; color: var(--mist-2); text-align: right; }
.tactics-actions { display: flex; align-items: flex-start; gap: 14px; margin-top: 14px; flex-wrap: wrap; }
.tactics-warning { flex: 1 1 320px; font-size: 11px; color: var(--dim); line-height: 1.55; }
@media (max-width: 820px) {
  .tactics-row { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: 8px; }
  .tactics-row-head { display: none; }
  .tactics-row > .entry-name, .tactics-out { grid-column: 1 / -1; }
  .tactics-out { text-align: left; }
  .tactics-node-label { display: block; }
}

/* Seats of Power: a toggle, not a choice. Held reads as ember, the same signal
   "owned" uses everywhere else on the site. */
.seat-group { margin-top: 16px; }
.seat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(232px, 1fr)); gap: 10px; }
.seat-card {
  display: flex; align-items: center; gap: 12px; text-align: left;
  background: var(--slate-2); border: 1px solid var(--border); border-radius: 8px;
  padding: 12px 14px; cursor: pointer; font-family: inherit; min-width: 0;
}
.seat-card:hover { border-color: var(--border-strong); }
.seat-card.held { border-color: var(--ember); background: rgba(255, 92, 31, 0.08); }
.seat-check {
  flex: 0 0 auto; width: 20px; height: 20px; border-radius: 5px;
  border: 1px solid var(--border-strong); background: var(--slate-3);
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 800; color: var(--night);
}
.seat-card.held .seat-check { background: var(--ember); border-color: var(--ember); }
.seat-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.seat-name { font-size: 13.5px; font-weight: 800; color: var(--frost); }
.seat-effect { font-size: 11.5px; color: var(--mist); }
.seat-card.held .seat-effect { color: var(--mist-2); }

/* Walkthrough. Dims the page down to the step you are on and parks the
   controls for it at the bottom, so the thing being explained is the thing you
   are typing into. */
body.walk-active .settings-section { opacity: 0.4; }
body.walk-active .settings-section.walk-focus { opacity: 1; border-color: var(--ember); }
/* `display: flex` below beats the user-agent's `[hidden] { display: none }`, so
   without this the bar sat on the page from load: empty, because nothing had
   filled it in, and with Next as a second way to start the walkthrough. Any
   rule that sets `display` on an element that also uses `hidden` needs this. */
.walk-bar[hidden] { display: none; }
.walk-bar {
  position: fixed; left: 50%; transform: translateX(-50%); bottom: 18px; z-index: 80;
  width: min(920px, calc(100vw - 28px));
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  background: var(--slate-3); border: 1px solid var(--ember); border-radius: 12px;
  padding: 13px 16px; box-shadow: 0 18px 44px rgba(0, 0, 0, 0.55);
}
.walk-progress { display: flex; gap: 5px; flex: 0 0 auto; }
.walk-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--slate); border: 1px solid var(--border-strong); }
.walk-dot.past { background: var(--ember-soft); border-color: var(--ember-soft); }
.walk-dot.at { background: var(--ember); border-color: var(--ember); }
.walk-text { flex: 1 1 300px; min-width: 0; }
.walk-title { font-size: 13px; font-weight: 800; color: var(--frost); }
.walk-blurb { font-size: 11.5px; color: var(--mist); line-height: 1.5; margin-top: 2px; }
.walk-actions { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.walk-quit { padding: 4px 10px; font-size: 15px; line-height: 1; }

@media (max-width: 900px) {
  .settings-page { padding: 20px 14px 120px; }
  .settings-layout { grid-template-columns: minmax(0, 1fr); }
  /* The rail becomes a scrolling strip above the sections rather than a column
     nobody can reach without scrolling past everything it indexes. */
  .settings-rail {
    position: static; flex-direction: row; overflow-x: auto; gap: 6px;
    scrollbar-width: none;
  }
  .settings-rail::-webkit-scrollbar { display: none; }
  .rail-item { flex: 0 0 auto; }
  .settings-masthead-side { align-items: stretch; width: 100%; }
  .settings-progress-label { text-align: left; }
}
@media (max-width: 700px) {
  .entry-row { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); row-gap: 8px; }
  .entry-row-head { display: none; }
  .entry-name, .entry-applied { grid-column: 1 / -1; }
  .entry-applied { flex-direction: row; justify-content: space-between; text-align: left; }
  .walk-bar { bottom: 76px; }
  .walk-text { flex-basis: 100%; }
}

/* The card My Roster keeps: a link with the same checklist inside it. The
   settings page itself shows this state in its rail instead, so this is the
   only place the chip row still renders. */
.settings-checklist { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.settings-pointer {
  display: flex; align-items: center; justify-content: space-between; gap: 18px;
  padding: 15px 18px; margin-bottom: 14px; flex-wrap: wrap;
}
.settings-pointer:hover { border-color: var(--border-strong); }
.settings-pointer .section-label { font-size: 13px; color: var(--frost); letter-spacing: 0.1em; }
.settings-pointer-main { display: flex; flex-direction: column; gap: 8px; min-width: 0; flex: 1 1 340px; }
.settings-pointer-copy { font-size: 12.5px; color: var(--mist); line-height: 1.6; max-width: 700px; }
.settings-pointer-go { font-size: 12.5px; font-weight: 700; color: var(--ember); white-space: nowrap; }

/* `.modifier-*` and `.settings-actions` lived here until v3.7.1. They styled
   the old two-panel table and the Save row under each panel; the page has one
   table shape now (.entry-row) and no Save buttons at all, so nothing rendered
   them any more. Removed after checking every page and script, which is the
   check v3.1.5 skipped when it deleted .mode-card out from under two pages
   that were still using it. test/csscoverage.test.js now fails loudly in that
   direction, so a mistake here is caught rather than shipped. */

/* ---------- troop-type filter (shared: War Room + Tier List) ---------- */
.troop-filter {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--border);
}
.card.troop-filter { margin-top: 0; padding: 12px 16px; border-top: 1px solid var(--border); }
.troop-filter-label {
  font-size: 11px; font-weight: 700; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--mist);
}
.troop-filter-boxes { display: flex; gap: 8px; flex-wrap: wrap; }
.troop-chip {
  display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
  background: var(--slate-2); border: 1px solid var(--border); border-radius: 6px;
  padding: 6px 11px; font-size: 12px; color: var(--mist); user-select: none;
}
.troop-chip.on { border-color: rgba(255, 92, 31, 0.45); color: var(--frost); }
.troop-chip input { width: 14px; height: 14px; accent-color: var(--ember); }
.troop-chip-icon { display: inline-flex; color: var(--mist); }
.troop-chip.on .troop-chip-icon { color: var(--ember); }

/* Tier list */
.view-tabs { display: flex; gap: 4px; background: var(--slate-2); border: 1px solid var(--border); border-radius: 7px; padding: 3px; }
.view-tab {
  background: none; border: 0; padding: 7px 16px; border-radius: 5px; color: var(--mist);
  font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; font-family: inherit;
}
.view-tab.active { background: var(--ember); color: var(--night); font-weight: 800; }
.tier-row {
  display: grid; grid-template-columns: 62px 1fr; gap: 14px; align-items: stretch;
  background: var(--slate); border: 1px solid var(--border); border-radius: 8px;
  padding: 12px; margin-bottom: 8px;
}
.tier-label {
  display: flex; align-items: center; justify-content: center; border-radius: 6px;
  font-size: 26px; font-weight: 800; color: var(--night);
}
.tier-S .tier-label { background: #ff5c1f; }
.tier-A .tier-label { background: #e8b84a; }
.tier-B .tier-label { background: #b07ce8; }
.tier-C .tier-label { background: #5ba7e0; }
.tier-D .tier-label { background: #7f8b94; }
.tier-F .tier-label { background: #4d565e; color: var(--frost); }
.tier-chips { display: flex; flex-wrap: wrap; gap: 6px; align-content: center; }
.tier-chip {
  display: inline-flex; align-items: baseline; gap: 8px;
  background: var(--slate-2); border: 1px solid var(--border); border-radius: 6px;
  padding: 7px 11px; font-size: 13px;
}
.tier-rank { font-size: 10.5px; color: var(--dim); }
.tier-name { font-weight: 800; }
.tier-breed { font-size: 10.5px; color: var(--dim); }
.tier-score { font-size: 11.5px; color: var(--ember); }
.tier-note { font-size: 10.5px; color: var(--mist); font-style: italic; }
@media (max-width: 900px) {
  .nav-secondary { margin-left: 10px; padding-left: 10px; gap: 10px; }
  .tier-row { grid-template-columns: 46px minmax(0, 1fr); gap: 10px; }
  .tier-label { font-size: 20px; }
  .tier-chip { font-size: 12px; padding: 6px 9px; gap: 6px; flex-wrap: wrap; }
  .roster-toolbar .view-tabs { width: 100%; }
  .roster-toolbar .view-tab { flex: 1; }
}
.tier-chips { min-width: 0; }
.tier-row { grid-template-columns: 62px minmax(0, 1fr); }

/* v2.3: the appbar carries more now (nav + Database menu + account zone),
   so let it wrap on narrow screens instead of pushing the account button
   past the viewport edge. */
@media (max-width: 900px) {
  .appbar { flex-wrap: wrap; row-gap: 10px; }
  .appbar-left { flex-wrap: wrap; row-gap: 10px; min-width: 0; }
  .appbar > #globalAuth { margin-left: auto; }
  .seg-tabs { flex: 1 1 auto; }
  .seg-tabs a { flex: 1; text-align: center; padding: 7px 10px; }
}

/* 2026-09-15: six tabs (Chest advisor joined). Labels had started wrapping onto
   two lines at 1280px and the bar scrolled sideways below 1052px (below 963px
   it already did with five). Labels now stay on one line, the bar tightens
   between 901 and 1440px, and when it still does not fit, the account zone and
   then the menus drop to their own row instead of pushing past the edge. */
.seg-tabs a { white-space: nowrap; }
.appbar { flex-wrap: wrap; row-gap: 10px; }
.appbar-left { flex-wrap: wrap; row-gap: 10px; min-width: 0; }
.appbar > #globalAuth { margin-left: auto; }
@media (min-width: 901px) and (max-width: 1440px) {
  .appbar { padding: 14px 18px; column-gap: 12px; }
  .appbar-left { column-gap: 14px; }
  .seg-tabs { gap: 2px; }
  .seg-tabs a { padding: 7px 9px; letter-spacing: 0.03em; }
  .nav-secondary { margin-left: 10px; padding-left: 10px; gap: 10px; }
}

/* The no-select-col override must not beat the mobile stacked layout. */
@media (max-width: 900px) {
  .roster-head.no-select-col, .roster-row.no-select-col {
    grid-template-columns: 22px 0 minmax(0, 1fr);
  }
  .roster-row.no-select-col > .roster-name { min-width: 0; }
}

/* ---------- v2.4: dragon monogram badges (brand file section 06) ---------- */
.dragon-icon {
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 5px; border: 1px solid; flex: none; vertical-align: middle;
}
.dragon-icon > span {
  font-family: var(--font-mono); font-weight: 800; letter-spacing: -0.05em; line-height: 1;
}

/* ---------- v2.4: changelog, upcoming, contact ---------- */
.release-tag {
  font-family: var(--font-mono); font-size: 13px; font-weight: 600;
  color: var(--night); background: var(--ember); border-radius: 5px; padding: 3px 10px;
}
.release-list { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 7px; }
/* Roadmap items with no version assigned yet: same shape as a release tag so the
   list lines up, but muted, because "Later" is not a commitment. */
.roadmap-later {
  font-family: var(--font-mono); font-size: 13px; font-weight: 600;
  color: var(--mist); background: var(--slate-3); border: 1px solid var(--border);
  border-radius: 5px; padding: 2px 9px;
}
.release-list li { color: var(--mist-2); font-size: 13.5px; line-height: 1.6; }

/* News page entries */
.news-entry { scroll-margin-top: 84px; }   /* clears the sticky appbar on deep links */
.news-entry-head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.news-entry .news-date { font-size: 11.5px; color: var(--dim); }
.news-tag {
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ember); border: 1px solid rgba(255, 92, 31, 0.35); border-radius: 4px; padding: 2px 7px;
}
.news-author { font-size: 11.5px; color: var(--mist); }
.news-links { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.news-links a {
  font-size: 12px; font-weight: 600; color: var(--mist-2);
  border: 1px solid var(--border); border-radius: 5px; padding: 5px 11px;
}
.news-links a:hover { color: var(--ember); border-color: rgba(255, 92, 31, 0.45); }
.news-entry h2 { font-size: 17px; margin: 0 0 8px; }
.news-entry p { color: var(--mist-2); font-size: 13.5px; line-height: 1.65; margin: 0; max-width: 68ch; }
.news-entry.targeted { border-color: rgba(255, 92, 31, 0.5); }
/* 2026-09-24: a longer post's subheadings, paragraphs and lists (news.js `more`). */
.news-entry h3 { font-size: 14.5px; margin: 20px 0 6px; }
.news-entry p + p, .news-entry ul + p { margin-top: 10px; }
.news-entry ul { color: var(--mist-2); font-size: 13.5px; line-height: 1.65; margin: 8px 0 0; padding-left: 20px; max-width: 68ch; }
.news-entry li + li { margin-top: 6px; }
.support-callout {
  display: flex; align-items: center; justify-content: space-between; gap: 20px; flex-wrap: wrap;
  border: 1px solid rgba(255, 92, 31, 0.35); border-radius: 10px; padding: 22px 24px;
  margin-bottom: 18px;
  background: radial-gradient(420px 200px at 20% 0%, rgba(255, 92, 31, 0.12), transparent 70%);
}
textarea {
  font-family: inherit; color: var(--frost); background: var(--slate-3);
  border: 1px solid var(--border-strong); border-radius: 6px; padding: 9px 11px;
  font-size: 13.5px; width: 100%; resize: vertical; line-height: 1.55;
}
textarea:focus { outline: 1px solid var(--ember); }

/* ---------- v2.4.1: footer polish (grouped links, own Ko-fi row) ---------- */
.site-footer-groups {
  display: flex; gap: 56px; flex-wrap: wrap; justify-content: center; text-align: left;
  margin-bottom: 4px;
}
.site-footer-groups > div { display: flex; flex-direction: column; gap: 7px; }
.site-footer-heading {
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--dim); margin-bottom: 2px;
}
.site-footer-groups a {
  font-size: 12.5px; font-weight: 600; color: var(--mist); letter-spacing: 0;
  text-transform: none;
}
.site-footer-groups a:hover { color: var(--frost); }
@media (max-width: 900px) {
  .site-footer-groups { gap: 32px; }
}

/* ---------------------------------------------------------------------------
   Staging banner (v3.0). Only rendered by vermithor.telltimes.net; production
   never sees it. Loud enough to be unmissable, short enough not to push the
   page around: it sits above everything and the body gains .has-env-banner so
   any fixed chrome can account for it.
   ------------------------------------------------------------------------ */
.env-banner {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 7px 16px;
  background: linear-gradient(90deg, #3a1d0b, #2a1608);
  border-bottom: 1px solid #a8571f;
  color: #f2c9a0;
  font-size: 12.5px;
  line-height: 1.4;
}
.env-banner a { color: #ffb877; text-decoration: underline; }
.env-banner-tag {
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 10.5px;
  background: #a8571f;
  color: #1a0d04;
  border-radius: 4px;
  padding: 2px 7px;
}
.env-banner-rel { margin-left: auto; color: #c99b6f; font-size: 11px; }
@media (max-width: 560px) {
  .env-banner-rel { margin-left: 0; }
}

/* ---------------------------------------------------------------------------
   Army-count selector (v3.0 Part D). Sits under the troop filter and reads as
   part of the same control strip: a label, the choices, and why you would pick
   fewer. The hint carries the real reason (a smaller search) rather than
   leaving it to look like a display preference.
   ------------------------------------------------------------------------ */
.army-count {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 10px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}
.army-count-label {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--mist);
}
.army-count-opts { display: flex; gap: 4px; }
.army-count-btn {
  min-width: 32px;
  padding: 5px 9px;
  font: inherit;
  font-size: 13px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--mist-2);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 7px;
  cursor: pointer;
}
.army-count-btn:hover { border-color: var(--mist); color: var(--frost); }
.army-count-btn.active {
  color: #0a0c0e;
  background: var(--ember);
  border-color: var(--ember);
}
/* v3.7.5: the recommended count is marked on the button and stays marked
   whatever is selected, so someone sitting on 4 can still see where the advice
   points. Outlined rather than filled, because `active` owns the filled
   treatment and the two have to stay tellable apart when 2 is both. */
.army-count-btn.recommended {
  position: relative;
  border-color: var(--info);
  color: var(--info-soft);
}
.army-count-btn.recommended.active {
  color: #0a0c0e;
  background: var(--ember);
  border-color: var(--ember);
}
.army-count-star {
  position: absolute; top: -6px; right: -5px;
  font-size: 9px; line-height: 1; color: var(--info);
  text-shadow: 0 0 3px var(--night);
}
.army-count-btn.recommended.active .army-count-star { color: var(--frost); }
.army-count-hint .link-quiet { margin-left: 6px; }
/* The recommendation is the one hint meant to be read rather than noticed in
   passing, so it gets the info colour and a rule beside it. Every other count
   keeps the quiet treatment. */
.army-count-hint {
  font-size: 12.5px; line-height: 1.55; color: var(--mist); flex: 1 1 240px;
}
.army-count-hint.recommended {
  color: var(--info-soft);
  border-left: 2px solid var(--info);
  padding-left: 10px;
}
@media (max-width: 700px) {
  .army-count-hint { flex-basis: 100%; font-size: 12px; }
}

/* ---------------------------------------------------------------------------
   Saved-result notice (v3.0 Part E). Shown when the War Room served the last
   solve instead of running a new one. Calm rather than alarming: this is the
   normal, fast path, and the point is only that the user knows why it was
   instant and that Re-optimize exists.
   ------------------------------------------------------------------------ */
.saved-note {
  display: flex;
  align-items: center;
  gap: 9px;
  flex-wrap: wrap;
  margin-bottom: 12px;
  padding: 8px 11px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--mist-2);
  background: var(--slate-2);
  border: 1px solid var(--line);
  border-radius: 9px;
}
.saved-note-tag {
  font-size: 10px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--mist);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 2px 6px;
}

/* ---------------------------------------------------------------------------
   Bench sub-page (v3.0 Part F). The picker is the page's real decision: which
   saved War Room result the bench descends from. A result whose roster has
   changed is shown but disabled, because "why is my Diversified run missing"
   is a worse question than "why is it greyed out".
   ------------------------------------------------------------------------ */
.bench-picker {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 8px;
}
.bench-option {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 10px 12px;
  text-align: left;
  font: inherit;
  color: var(--mist-2);
  background: var(--slate-2);
  border: 1px solid var(--line);
  border-radius: 9px;
  cursor: pointer;
}
.bench-option:hover:not(:disabled) { border-color: var(--mist); }
.bench-option.active { border-color: var(--ember); background: #1a1207; }
.bench-option.stale { opacity: 0.45; cursor: not-allowed; }
.bench-option-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  font-size: 13px;
  color: var(--frost);
}
.bench-option-head .mono { font-size: 11px; color: var(--mist); }
.bench-option-meta { font-size: 11.5px; color: var(--mist); }
.bench-option-when { font-size: 10.5px; color: var(--dim); }
.bench-empty { font-size: 13px; color: var(--mist-2); line-height: 1.6; }
.bench-empty a { color: var(--ember); }
/* v3.7.6: the bench follows the War Room, so the usual state is one sentence
   saying which result it descended from, not a list of every saved row. */
.bench-following {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  font-size: 13px; line-height: 1.6; color: var(--mist-2);
}
.bench-following b { color: var(--frost); }

/* ---------------------------------------------------------------------------
   Habit upgrade advisor (v3.0 Part A). A ranked table, so it reads as columns
   rather than cards: rank, what, cost, gain, per-Core. Flags sit inline with
   the upgrade because "needs 8 stars first" changes whether the row is
   actionable at all, and that has to be impossible to miss.
   ------------------------------------------------------------------------ */
.advisor-head,
.advisor-row {
  display: grid;
  grid-template-columns: 30px 1fr 110px 90px 74px;
  gap: 10px;
  align-items: baseline;
  padding: 7px 4px;
}
.advisor-head {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--dim);
  border-bottom: 1px solid var(--line);
}
.advisor-row { border-bottom: 1px solid var(--line); font-size: 13px; }
.advisor-row:last-child { border-bottom: none; }
.advisor-row.harm { opacity: 0.62; }
.advisor-rank { color: var(--dim); font-size: 12px; }
.advisor-what { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.advisor-habit { font-size: 11.5px; color: var(--mist); }
.advisor-cost, .advisor-gain, .advisor-roi { text-align: right; font-size: 12.5px; }
.advisor-cost { color: var(--mist); }
.advisor-gain { color: var(--mist-2); }
.advisor-roi { color: var(--frost); font-weight: 700; }
.advisor-flag {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--mist);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 1px 5px;
  white-space: nowrap;
}
.advisor-flag.harm { color: #ff8a7a; border-color: #b3382c66; }
@media (max-width: 640px) {
  .advisor-head { display: none; }
  .advisor-row { grid-template-columns: 24px 1fr auto; row-gap: 2px; }
  .advisor-cost, .advisor-gain { grid-column: 2; text-align: left; }
}

/* Unranked advisor steps: available, but not placeable in the ranking. */
.advisor-unranked {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px dashed var(--line);
}

/* ---------------------------------------------------------------------------
   Line-up builder (v3.0 Part C). Roster on the left, lanes and the grade on the
   right: the pattern the retired calculator used, kept because it works.
   Stars and level are promoted to primary elements — they move every number in
   the score and were previously a footnote.
   ------------------------------------------------------------------------ */
.builder-layout {
  display: grid;
  grid-template-columns: 300px 1fr;
  gap: 14px;
  align-items: start;
}
.builder-roster { position: sticky; top: 12px; }
.builder-roster-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 62vh;
  overflow-y: auto;
  /* Reserve the scrollbar's width instead of letting it sit on top of the
     content. Rows used to be a single full-width button, so an overlaid
     scrollbar landed on dead space at the card's edge and nobody noticed; once
     the row ended in a Set aside button the scrollbar cut straight through it.
     The gutter keeps the column, the padding keeps it off the button. */
  padding-right: 6px;
  scrollbar-gutter: stable;
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
}
.builder-roster-list::-webkit-scrollbar { width: 8px; }
.builder-roster-list::-webkit-scrollbar-track { background: transparent; }
.builder-roster-list::-webkit-scrollbar-thumb {
  background: var(--line);
  border-radius: 4px;
}
.builder-roster-list::-webkit-scrollbar-thumb:hover { background: var(--mist); }
.builder-dragon {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 7px 9px;
  text-align: left;
  font: inherit;
  color: var(--mist-2);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 8px;
  cursor: pointer;
}
.builder-dragon:hover:not(:disabled) { border-color: var(--ember); }
.builder-dragon.used { opacity: 0.35; cursor: default; }
.builder-dragon-top { display: flex; align-items: center; justify-content: space-between; gap: 6px; }
.builder-dragon-name { font-size: 13px; font-weight: 600; color: var(--frost); }
.builder-dragon-meta { display: flex; align-items: baseline; gap: 7px; font-size: 11px; }
.builder-stars { color: var(--ember); font-size: 12px; }
.builder-level { color: var(--frost); font-size: 12px; }
.builder-breed { color: var(--dim); }

.tier-pair { display: inline-flex; gap: 3px; }
.tier-chip {
  font-size: 10px;
  font-weight: 800;
  line-height: 1;
  padding: 2px 4px;
  border-radius: 4px;
  background: var(--slate-2);
  border: 1px solid var(--line);
  color: var(--mist);
}
.tier-chip.personal { border-style: dashed; }
.tier-chip.tier-S { color: #ffd166; border-color: #ffd16655; }
.tier-chip.tier-A { color: #ff9f45; border-color: #ff9f4555; }
.tier-chip.tier-B { color: #7fd8d2; border-color: #7fd8d255; }

.builder-lanes { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.builder-lane {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-height: 92px;
  padding: 10px;
  border: 1px dashed var(--line);
  border-radius: 9px;
  cursor: pointer;
}
.builder-lane.filled { border-style: solid; background: var(--slate-2); }
.builder-lane.picking { border-color: var(--ember); }
.builder-lane-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--mist);
}
.builder-lane-name { font-size: 15px; font-weight: 700; color: var(--frost); }
.builder-lane-meta { display: flex; align-items: center; gap: 7px; font-size: 11.5px; color: var(--mist-2); }
.builder-lane-empty { font-size: 12px; color: var(--dim); }
.builder-lane-clear {
  align-self: flex-start;
  margin-top: auto;
  font: inherit;
  font-size: 10.5px;
  color: var(--mist);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 2px 6px;
  cursor: pointer;
}

.grade-card { margin-bottom: 14px; }
.grade-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
/* Always five stars, filled up to the rating. The unfilled ones carry the
   hollow glyph as well as the dimmer colour, so a one-star result cannot be
   misread as a five-star one if the two colours are hard to tell apart. */
.grade-stars { font-size: 20px; color: var(--ember); letter-spacing: 2px; }
.grade-stars-dim { color: var(--dim); }
.grade-name { font-size: 16px; font-weight: 800; color: var(--frost); }
.grade-ratio { margin-left: auto; font-size: 12px; color: var(--mist); }
.grade-best,
.grade-suggestions {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
  font-size: 12.5px;
  color: var(--mist-2);
  line-height: 1.6;
}
.grade-suggestion { display: flex; gap: 9px; align-items: baseline; margin-top: 6px; }
.grade-sev {
  flex: none;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--mist);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 1px 5px;
}
.grade-suggestion.sev-high .grade-sev { color: #ff8a7a; border-color: #b3382c66; }
@media (max-width: 900px) {
  .builder-layout { grid-template-columns: 1fr; }
  .builder-roster { position: static; }
  .builder-roster-list { max-height: 40vh; }
}

/* Where a graded line-up sits among everything the roster could build. */
.grade-bar {
  height: 5px;
  margin-top: 10px;
  background: var(--slate-2);
  border-radius: 3px;
  overflow: hidden;
}
.grade-bar span { display: block; height: 100%; background: var(--ember); }
.grade-suggestion-title { display: block; color: var(--frost); margin-bottom: 1px; }
.grade-suggestion.sev-good .grade-sev { color: #7fd8d2; border-color: #7fd8d255; }
/* Observations, not actions: nothing to do about them, so nothing that reads
   as urgency. Deliberately the quietest badge on the card. */
.grade-suggestion.sev-note .grade-sev { color: var(--dim); border-color: var(--line); }
/* How far the ceiling is from here, next to the lineup that reaches it, so the
   suggestions read as steps toward a named destination. */
.grade-gap { color: var(--ember); white-space: nowrap; }

/* The five marches, because the rating is against one army and you field five.
   A lineup at 85% of the ceiling can be a good third march, and the ladder is
   what says so. */
.grade-marches {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
  font-size: 12.5px;
  color: var(--mist-2);
  line-height: 1.6;
}
.march-ladder { display: flex; flex-direction: column; gap: 3px; margin-top: 7px; }
.march-rung {
  display: flex;
  gap: 8px;
  align-items: baseline;
  padding: 3px 7px;
  border-radius: 6px;
  border: 1px solid transparent;
  font-size: 12px;
  color: var(--mist);
}
.march-rung b { flex: none; color: var(--dim); min-width: 30px; }
.march-rung .mono { margin-left: auto; color: var(--dim); }
/* Where this lineup lands. The only coloured rung, so the eye finds it first. */
.march-rung.here {
  border-color: #b3382c55;
  background: var(--slate-2);
  color: var(--frost);
}
.march-rung.here b { color: var(--ember); }

/* Dragons committed to another march: still listed, still readable, but plainly
   out of the pool. */
.builder-dragon-row { display: flex; align-items: stretch; gap: 6px; }
.builder-dragon-row .builder-dragon { flex: 1; min-width: 0; }
.builder-dragon-row.excluded .builder-dragon { opacity: 0.4; }
/* A fixed trailing column, held even for dragons that have no button, so a card
   does not jump wider the moment it goes into the lineup and the list stops
   shifting under the cursor while you build. */
/* Width comes from the label, never from a pixel guess: a hardcoded column that
   is a few pixels short breaks "SET ASIDE" across two lines, and how many
   pixels it needs depends on the font the visitor actually gets. Rows without a
   button carry a hidden copy of the same label, so the column lines up without
   anyone having to measure anything. */
.builder-exclude-slot { flex: none; display: flex; align-items: center; }
.builder-exclude {
  font-size: 10px;
  line-height: 1.3;
  white-space: nowrap;
  text-transform: uppercase;
  color: var(--mist);
  background: none;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 4px 5px;
  cursor: pointer;
}
.builder-exclude.ghost { visibility: hidden; }
.builder-exclude:hover { color: var(--frost); border-color: var(--mist); }
.builder-dragon-row.excluded .builder-exclude { color: var(--ember); border-color: #b3382c55; }

/* ---------------------------------------------------------------------------
   Front page, v3.0. Calmer than the old hero: no fake preview, a release panel
   instead, and an honest grid of every tool. The eye should land on one
   headline, one action, and then a list it can scan.
   ------------------------------------------------------------------------ */
.section-lede {
  max-width: 62ch;
  margin: 10px 0 26px;
  color: var(--mist);
  font-size: 14.5px;
  line-height: 1.65;
  text-wrap: pretty;
}

/* v3.0.4: the all-dragons index. Plain linked prose on purpose. It exists so a
   player searching a dragon by name lands somewhere useful, and so the names
   are crawlable text rather than sitting only in a meta tag nothing reads.
   Names never wrap mid-word, otherwise a long line breaks "Sheepstealer" in
   half and the block reads as noise. */
.dragon-index p {
  max-width: 94ch;
  margin: 0 0 12px;
  color: var(--mist);
  font-size: 14.5px;
  line-height: 1.95;
  text-wrap: pretty;
}
.dragon-index b { color: var(--mist-2); }
.dragon-index a { white-space: nowrap; }

/* v3.0.4: the crawlable snapshot written by scripts/prerender.js. The client
   script replaces the container's contents on load, so this is what a crawler
   reads and what shows for the moment before JS runs or if it never does. It
   is styled plainly rather than made to imitate the real table: pretending to
   be the interactive UI while lacking its controls would be worse than reading
   as what it is, a static list. */
.prerender-only { padding: 4px 2px; }
.prerender-only h2 { font-size: 17px; margin: 0 0 6px; }
.prerender-only > p { color: var(--mist); font-size: 13.5px; margin: 0 0 18px; max-width: 70ch; }
.prerender-only article { padding: 12px 0; border-top: 1px solid var(--line, #1b2026); }
.prerender-only h3 { font-size: 14.5px; margin: 0 0 5px; }
.prerender-only article p { color: var(--mist); font-size: 13px; line-height: 1.6; margin: 0 0 4px; }
.prerender-only ul { margin: 0; padding-left: 20px; color: var(--mist); font-size: 13px; line-height: 1.7; }

/* v3.0.1: the release panel now carries the release rather than mentioning it.
   Ember border, an ember wash off the top edge and a lit badge, so the biggest
   thing on the page after the headline is what is actually new. */
.release-card {
  border-color: var(--ember);
  background:
    linear-gradient(180deg, rgba(255, 92, 31, 0.10), rgba(255, 92, 31, 0) 46%),
    var(--slate);
  box-shadow: 0 0 0 1px rgba(255, 92, 31, 0.18), 0 22px 60px -22px rgba(255, 92, 31, 0.5);
}
.release-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}
.release-badge {
  font-size: 12px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--night);
  background: var(--ember);
  border-radius: 5px;
  padding: 5px 11px;
  box-shadow: 0 0 18px rgba(255, 92, 31, 0.45);
}
.release-title {
  font-size: 19px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  color: var(--frost);
  margin: 0 0 12px;
}
.release-list-compact { margin: 0; padding: 0; list-style: none; }
.release-list-compact li {
  position: relative;
  padding: 0 0 9px 15px;
  font-size: 13px;
  line-height: 1.55;
  color: var(--mist-2);
}
.release-list-compact li:last-child { padding-bottom: 0; }
.release-list-compact li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 8px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--ember);
}
.release-list-compact b { color: var(--frost); }

.tool-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(255px, 1fr));
  gap: 12px;
}
.tool-card {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 20px 22px;
}
.tool-card:hover { border-color: var(--ember); }
.tool-name { font-size: 15px; font-weight: 800; color: var(--frost); }
.tool-desc { font-size: 13px; line-height: 1.6; color: var(--mist); flex: 1; }
.tool-go {
  margin-top: 2px;
  font-size: 12px;
  font-weight: 700;
  color: var(--ember);
}

/* ---------- context cards (Army Review, Habit Advice) ----------
   Removed in v3.1.5 with the War Room's mode switch, which was the only page
   these were written for. Two others still render .mode-card: builder.js for
   'Who are you fighting' and habit-advisor.js for its lens picker. Both had
   been laying out as unstyled full-width blocks ever since.
   Restored verbatim, except the column count, which is now driven by the
   content instead of the five War Room modes that no longer exist: Army Review
   shows three contexts and Habit Advice two. */
.mode-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 10px;
}
.mode-card {
  display: flex; flex-direction: column; gap: 8px; text-align: left;
  background: var(--slate-2); border: 1px solid var(--border); border-radius: 8px;
  padding: 14px 16px; color: var(--frost); cursor: pointer;
}
.mode-card:hover { border-color: var(--border-strong); }
.mode-card.active {
  border-color: rgba(255, 92, 31, 0.5);
  box-shadow: 0 0 0 1px rgba(255, 92, 31, 0.15);
}
.mode-card.active > span:first-child { color: var(--ember); }
@media (max-width: 720px) {
  .mode-grid { grid-template-columns: 1fr; }
}

/* ---------- chest odds (2026-09-15) ---------- */
.chest-intro { font-size: 12.5px; color: var(--mist); margin-top: 4px; max-width: 640px; line-height: 1.55; }
.chest-form { margin-bottom: 14px; }
.chest-fields { display: grid; grid-template-columns: 2fr 1.4fr 1fr 1fr; gap: 12px; }
.chest-fields .field { margin-bottom: 0; }
.chest-hint { font-size: 11.5px; color: var(--dim); margin-top: 5px; }
.chest-row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border-soft);
}
.chest-row select { min-width: 150px; }
.chest-check { display: flex; align-items: center; gap: 9px; font-size: 13px; color: var(--mist-2); cursor: pointer; }
.chest-check input { width: auto; padding: 0; accent-color: var(--ember); }
.chest-plan { margin-bottom: 14px; border-color: var(--border-strong); }
.chest-plan-note { font-size: 13px; color: var(--mist-2); margin: 8px 0 0; line-height: 1.55; }
.chest-buys { display: flex; flex-wrap: wrap; gap: 10px 26px; margin: 12px 0 14px; }
.chest-buy { font-size: 15px; font-weight: 700; }
.chest-buy .num { color: var(--ember); margin-right: 6px; }
.chest-sub { display: block; font-size: 11.5px; font-weight: 500; color: var(--mist); }
.chest-stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
.chest-stat { background: var(--slate-2); border-radius: 6px; padding: 8px 10px; min-width: 0; }
.chest-stat .k { font-size: 10px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--dim); }
.chest-stat .v { font-family: var(--font-mono); font-size: 18px; font-weight: 600; color: var(--frost); margin-top: 2px; }
.chest-table-label { display: block; margin: 4px 0 8px; }
.chest-table { min-width: 720px; }
.chest-table .thead, .chest-table .trow {
  grid-template-columns: minmax(170px, 2fr) repeat(4, minmax(64px, 1fr)) minmax(150px, 1.6fr);
}
.chest-table .trow { font-size: 13.5px; }
.chest-table .trow.chest-top { background: rgba(255, 92, 31, 0.07); }
.chest-table .trow.chest-none { color: var(--dim); }
.chest-key { font-weight: 700; }
@media (max-width: 900px) {
  .chest-fields { grid-template-columns: 1fr 1fr; }
  .chest-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* 2026-09-24: the Chest advisor is marked beta on its page (the owner). */
.beta-tag {
  display: inline-block; margin-left: 6px; vertical-align: 1px;
  font-size: 9.5px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ember); border: 1px solid rgba(255, 92, 31, 0.5); border-radius: 6px; padding: 1px 6px;
}

/* ---------------------------------------------------------------------------
   2026-09-24: the support note on the most visited pages (ui.js
   mountSupportNotice) and the War Room's dragon pool (war-room.js), where a
   dragon can be left out without touching its roster data.
   ------------------------------------------------------------------------ */
.support-notice {
  display: flex; align-items: center; justify-content: space-between; gap: 14px 18px; flex-wrap: wrap;
  border: 1px solid rgba(255, 92, 31, 0.35); border-radius: 10px; padding: 14px 18px;
  margin-bottom: 16px; font-size: 13px; line-height: 1.6; color: var(--mist-2);
  background: radial-gradient(420px 160px at 15% 0%, rgba(255, 92, 31, 0.10), transparent 70%);
}
/* Pages without a <main> (the home page) get it straight under the header. */
body > .support-notice { box-sizing: border-box; width: calc(100% - 32px); max-width: 1200px; margin: 16px auto 0; }
.support-notice-text { flex: 1 1 420px; max-width: 820px; }
.support-notice-text b { color: var(--frost); }
.support-notice-actions { display: flex; align-items: center; gap: 6px; }
@media (max-width: 560px) {
  .support-notice-actions { width: 100%; justify-content: space-between; }
}

.war-pool { margin-top: 12px; }
.war-pool-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 12.5px; color: var(--mist-2); }
.war-pool-grid { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.pool-chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px; border-radius: 999px;
  border: 1px solid var(--border-strong); background: var(--slate-2); color: var(--frost);
  font: inherit; font-size: 12px; cursor: pointer;
}
.pool-chip:hover { border-color: rgba(255, 92, 31, 0.5); }
.pool-chip.off { opacity: 0.55; background: transparent; color: var(--mist); text-decoration: line-through; }
.pool-chip-stars { font-family: var(--font-mono); font-size: 11px; color: var(--dim); }
