/* scenarios.css
   Roster scenarios: the list of them, the one-scenario page (its hero, the
   build columns and the projected roster), and the player picker that slides
   in from the right.

   Part of the Teleport stylesheet, split by concern. index.html links these
   in source order; keep that order, the cascade depends on it. */

/* ═══════════════════════════════════════════════════════════════════════════
   THE LIST
   ═══════════════════════════════════════════════════════════════════════════ */
.scn-toolbar {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  margin-bottom: 16px;
}

.scn-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 12px;
}

/* The duplicate button sits outside the card's own link rather than inside it —
   an <a> may not contain a <button>, and "open this" and "copy this" are two
   different intentions that shouldn't share one hit target. */
.scn-card {
  position: relative; display: flex; align-items: flex-start;
  background: var(--surface); border: 1px solid var(--border-2); border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  transition: transform 0.12s, box-shadow 0.16s, border-color 0.16s;
}
.scn-card:hover {
  transform: translateY(-2px); box-shadow: var(--shadow-md);
  border-color: color-mix(in srgb, var(--accent) 40%, transparent);
}
.scn-card-main { flex: 1; min-width: 0; display: flex; gap: 13px; padding: 15px 4px 15px 16px; }
.scn-card-body { flex: 1; min-width: 0; }
.scn-card-name { font-size: 15px; font-weight: 680; letter-spacing: -0.01em; }
.scn-card-meta {
  font-size: 11.5px; color: var(--label-2); margin-top: 3px;
  display: flex; align-items: center; gap: 5px; flex-wrap: wrap;
}
/* Two lines at most: the notes are context for the name, not the content of the
   card, and an eight-line note would push the counts out of a scannable grid. */
.scn-card-notes {
  margin-top: 7px; font-size: 12.5px; color: var(--label-2); line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.scn-card-counts { display: flex; gap: 6px; margin-top: 10px; }
.scn-card-dupe { margin: 12px 10px 0 0; flex-shrink: 0; }

/* ═══════════════════════════════════════════════════════════════════════════
   ONE SCENARIO — the hero
   ═══════════════════════════════════════════════════════════════════════════ */
.scn-hero {
  background: var(--surface); border: 1px solid var(--border-2); border-radius: var(--r-xl);
  padding: 20px 22px 18px; box-shadow: var(--shadow-sm); margin-bottom: 18px;
}
.scn-hero-top { display: flex; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
.scn-hero-main { flex: 1; min-width: 220px; }
.scn-hero-main h1 { font-size: 24px; font-weight: 780; letter-spacing: -0.025em; line-height: 1.1; }
.scn-hero-main p {
  font-size: 13px; color: var(--label-2); margin-top: 5px;
  display: flex; align-items: center; gap: 5px; flex-wrap: wrap;
}
/* pre-wrap, because the notes are typed into a textarea and their line breaks
   are the author's own structure — flattening them would run three assumptions
   together into one sentence. */
.scn-hero-notes {
  margin-top: 10px; font-size: 13px; color: var(--label); line-height: 1.5;
  white-space: pre-wrap; overflow-wrap: break-word; max-width: 70ch;
}
.scn-hero-acts { display: flex; gap: 8px; flex-shrink: 0; }

/* ── The four numbers ──────────────────────────────────────────────────
   Today, out, in, and what's left — read left to right as the arithmetic they
   are. Equal tracks rather than auto-fit, so the four always sit in one row at
   the same width and the eye can compare them; they drop to two-by-two on a
   phone (see responsive.css). */
.scn-stats {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-top: 18px;
}
.scn-stat {
  padding: 12px 14px; border-radius: var(--r-md);
  background: var(--surface-2); border: 1px solid var(--border-2);
  border-left: 3px solid var(--border);
}
.scn-stat-val { font-size: 24px; font-weight: 760; letter-spacing: -0.03em; font-variant-numeric: tabular-nums; line-height: 1.1; }
.scn-stat-lbl { font-size: 11px; font-weight: 650; color: var(--label-2); margin-top: 3px; letter-spacing: 0.01em; }
.scn-stat--slate  { border-left-color: var(--slate); }
.scn-stat--red    { border-left-color: var(--red);   }
.scn-stat--red .scn-stat-val   { color: var(--red);   }
.scn-stat--green  { border-left-color: var(--green); }
.scn-stat--green .scn-stat-val { color: var(--green); }
.scn-stat--accent { border-left-color: var(--accent); background: var(--accent-light); border-color: transparent; }
.scn-stat--accent .scn-stat-val { color: var(--accent-deep); }
:root[data-theme="dark"] .scn-stat--accent .scn-stat-val { color: var(--accent); }

/* ── Pieces the chart's own rows lean on ───────────────────────────────
   What used to be a second pane's worth of markup collapsed into the chart
   itself (see the header of js/views/scenario.js), so only three rules survived
   the move: the group heading, the grade dot, and the departure reason — which
   is a control, not a label, and looks like the pill it replaced. */
.scn-group-name {
  font-size: 11px; font-weight: 750; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--label-2);
}

/* Reserved on every row, dot or no dot — an incoming player has none and a
   departing one has none, and letting the slot collapse on those rows shifted
   their dollar figures out of the money column below. See GRADE_SPACER in
   views/scenario.js. */
.scn-grade { width: 8px; height: 8px; flex-shrink: 0; }

/* The reason a man is leaving, as the control that sets it. A native <select>,
   so it is keyboard- and screen-reader-correct out of the box, wearing the
   colours of the pill it would otherwise have been. */
.scn-reason {
  appearance: none; -webkit-appearance: none;
  border: 1px solid transparent; border-radius: var(--r-full);
  padding: 3px 19px 3px 8px; cursor: pointer; flex-shrink: 0;
  font-family: var(--font); font-size: 10px; font-weight: 700;
  letter-spacing: 0.02em; text-transform: uppercase;
  background-repeat: no-repeat; background-position: right 6px center; background-size: 8px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
}
.scn-reason--accent { background-color: var(--accent-light); color: var(--accent-deep); }
:root[data-theme="dark"] .scn-reason--accent { color: var(--accent); }
.scn-reason--slate  { background-color: var(--slate-light); color: var(--slate); }
.scn-reason--gold   { background-color: var(--gold-light);  color: var(--gold);  }
.scn-reason--red    { background-color: var(--red-light);   color: var(--red);   }
/* Options are drawn by the OS, which won't inherit the pill's tint — so give
   them the page's own surface rather than leaving them unreadable in dark mode. */
.scn-reason option { background: var(--surface); color: var(--label); text-transform: none; font-weight: 500; }

/* ── The budget ────────────────────────────────────────────────────────
   One number a staff types, one they have left, and a bar between them. It sits
   under the four count tiles because it answers the same question one step
   further on: those say what the roster becomes, this says whether they can
   afford it.

   The field is the display. There is no "edit budget" dialogue and no pencil —
   a figure somebody revises three times in a meeting should not cost three
   dialogues, so the number on screen *is* the input, quiet until it is hovered
   or focused. The same rule runs down the chart's rows (.scn-cash below), so a
   money field is one recognisable thing wherever it appears. */
.scn-money {
  margin-top: 12px; padding: 14px 16px 13px;
  background: var(--surface-2); border: 1px solid var(--border-2);
  border-radius: var(--r-md);
}
.scn-money-top {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 18px; flex-wrap: wrap;
}
.scn-money-lbl {
  display: block;
  font-size: 10px; font-weight: 750; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--label-3);
}

/* The whole thing is one <label>, so a click anywhere near the figure — the
   caption, the dollar mark, the padding — lands in the field. */
.scn-bud { display: block; min-width: 0; cursor: text; }
.scn-bud-field { display: flex; align-items: baseline; gap: 1px; margin-top: 2px; }
.scn-bud-sym {
  font-size: 18px; font-weight: 700; color: var(--label-3);
  transition: opacity 0.12s;
}
.scn-bud-in {
  width: 7ch; min-width: 7ch; max-width: 100%;
  border: none; background: none; padding: 0; margin: 0;
  font-family: var(--font); font-size: 26px; font-weight: 780;
  letter-spacing: -0.03em; color: var(--label);
  font-variant-numeric: tabular-nums;
  border-bottom: 1.5px solid transparent; transition: border-color 0.14s, color 0.14s;
}
/* An unset budget has to *look* like somewhere to type, or it reads as a
   missing number rather than an empty field. It is the one place here that
   carries its own prompt, and it needs the room for it. */
.scn-bud-in::placeholder { font-size: 16px; font-weight: 620; letter-spacing: -0.01em; color: var(--label-3); }
.scn-bud-in:placeholder-shown { width: 11ch; min-width: 11ch; }
.scn-bud-in:hover { border-bottom-color: var(--border); }
.scn-bud-in:focus { outline: none; border-bottom-color: var(--accent); }
/* No dollar mark in front of a field that has nothing in it — "$ Set a budget"
   reads as a broken string. It fades in with the first digit, and on focus, so
   the field never changes width as it appears. */
.scn-bud:has(.scn-bud-in:placeholder-shown:not(:focus)) .scn-bud-sym { opacity: 0; }

.scn-money-figs { display: flex; gap: 22px; flex-shrink: 0; flex-wrap: wrap; justify-content: flex-end; }
.scn-money-fig { text-align: right; }
.scn-money-fig-val {
  font-size: 17px; font-weight: 730; letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums; line-height: 1.15;
}
.scn-money-fig-lbl {
  font-size: 10px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--label-3); margin-top: 2px;
}
/* Money left is good news and money past the line is the alarm — the same
   two-colour logic the group deltas use, so a staff reads them the same way. */
.scn-money-fig--left .scn-money-fig-val { color: var(--green); }
.scn-money-fig--over .scn-money-fig-val { color: var(--red); }

/* An empty track when no budget is set: there is nothing for a fill to be a
   fraction of, and a bar sitting at 0% would say "you have spent nothing" when
   what is true is that nobody has said how much there is. */
.scn-meter {
  position: relative; height: 6px; margin-top: 12px;
  border-radius: var(--r-full); background: var(--border-2); overflow: hidden;
}
.scn-meter-fill {
  height: 100%; border-radius: var(--r-full);
  background: linear-gradient(90deg, var(--green), color-mix(in srgb, var(--green) 55%, var(--gold)));
  transition: width 0.34s var(--ease-out), background 0.2s;
}
.scn-meter.is-over .scn-meter-fill { background: var(--red); }

.scn-money-note {
  margin-top: 7px; font-size: 11.5px; color: var(--label-2);
  font-variant-numeric: tabular-nums;
}
/* The blob is on the row and this session could not open it — see
   sealMoneyOnWrite in the lambda. Stated, and deliberately not styled as an
   error a coach could act on: nothing has been lost and nothing here will fix
   it. */
.scn-money--locked .scn-money-note { max-width: 62ch; line-height: 1.5; }

/* ── A player's own figure ─────────────────────────────────────────────
   The same field as the budget above, at row scale. Always on screen rather
   than revealed on hover the way the Leaving button is: that button is an
   action somebody goes looking for, and this is a column of numbers they read
   down the card. Right-aligned and tabular, so a card of six figures lines up
   as a column and can be scanned as one. */
/* Left-aligned against the dollar mark, so each row reads as one token —
   "$1.8M" — and the tokens start in the same pixel down the card. The mark is
   *always* drawn, dimmed on an unpriced row rather than hidden, since hiding it
   punched a hole in the very edge the column is aligned to. See moneyCell in
   views/scenario.js for the other condition this depends on: nothing ahead of
   it in the row may collapse. */
.scn-cash { display: flex; align-items: center; gap: 1px; flex-shrink: 0; cursor: text; }
.scn-cash-sym {
  font-size: 10.5px; font-weight: 700; color: var(--label-3);
  opacity: 0.85; transition: opacity 0.12s, color 0.12s;
}
.scn-cash:has(.scn-cash-in:placeholder-shown:not(:focus)) .scn-cash-sym { opacity: 0.3; }
.scn-cash:hover .scn-cash-sym,
.scn-cash:focus-within .scn-cash-sym { opacity: 1; color: var(--label-2); }

.scn-cash-in {
  /* Fixed, and wide enough for the longest short form ("12.34M") with a couple
     of pixels of guard — a clipped figure is worse than a little trailing
     space. Left-aligned, so the first digit sits hard against the dollar mark
     and every figure on the card begins at the same x; tabular, so the digits
     after it line up too. */
  width: 46px; padding: 2px 3px; border: 1px solid transparent; border-radius: var(--r-sm);
  background: none; text-align: left;
  font-family: var(--font); font-size: 11.5px; font-weight: 650;
  letter-spacing: -0.01em; color: var(--label);
  font-variant-numeric: tabular-nums;
  transition: border-color 0.13s, background 0.13s, color 0.16s, width 0.16s var(--ease-out);
}
.scn-cash-in::placeholder { color: var(--label-3); font-weight: 500; }
.scn-cash-in:hover { border-color: var(--border); }
.scn-cash-in:focus {
  outline: none; border-color: var(--accent); background: var(--surface);
  /* Room to read the exact figure, which is what the field swaps to on focus
     (see wireMoneyField in views/scenario.js). It grows to the right, so the
     left edge every other row is aligned to doesn't move under the one row
     being edited. */
  width: 88px;
}
.scn-cash-in:disabled { opacity: 0.6; }
/* A quarter-second of green on the field that just saved — the only
   acknowledgement a figure gets. Forty alerts would be unusable, and a failure
   already speaks for itself through saveItem. */
.scn-cash-in.is-saved { color: var(--green); border-color: var(--green); }
.scn-cash:has(.scn-cash-in:placeholder-shown:not(:focus)) .scn-cash-sym { opacity: 0; }

/* ── The crystal ball ──────────────────────────────────────────────────
   One per row, in the fixed slot just before the money field so the dollar
   column below still lines up (see benchButton in views/scenario.js). Visible
   at rest rather than hover-revealed — it's a feature to find, and the practice
   field has no hover — but muted, since sixty bright orbs would drown out the
   names. It brightens to accent on hover/focus and holds its slot either way. */
.scn-bench {
  flex-shrink: 0; width: 24px; height: 24px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: none; background: none; border-radius: var(--r-sm);
  color: var(--label-3); cursor: pointer;
  transition: color 0.14s, background 0.14s, transform 0.12s;
}
.scn-bench svg { width: 15px; height: 15px; }
.scn-bench:hover {
  color: var(--accent-deep); background: var(--accent-light); transform: translateY(-1px);
}
:root[data-theme="dark"] .scn-bench:hover { color: var(--accent); }
.scn-bench:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--accent-light); color: var(--accent-deep); }
:root[data-theme="dark"] .scn-bench:focus-visible { color: var(--accent); }

/* His figure is freed, not spent, so it reads as struck through with the rest of
   his row — but it stays editable, because what a departing man was costing is
   exactly the number that makes the freed total worth anything. A departing row
   is dimmed to 0.55, which is right for reading and wrong for typing into, so
   the row comes back to full strength while its field has focus. */
.scn-prow.is-out .scn-cash-in { text-decoration: line-through; text-decoration-thickness: 1px; }
.scn-prow.is-out .scn-cash-in:focus { text-decoration: none; }
.scn-prow.is-out:has(.scn-cash-in:focus) { opacity: 1; }

/* ═══════════════════════════════════════════════════════════════════════════
   THE CHART — the whole of a scenario, one card per position
   ═══════════════════════════════════════════════════════════════════════════ */
/* Wide enough for a handle, a depth number, a face, a name, a money field and
   an "In" tag on one line — a narrower track ellipsed the names, which is the
   one thing on the row that can't be guessed from the rest of it.

   It was 290px before a figure sat on every row. The field and its gap are
   about fifty pixels, and they come out of the name's share rather than the
   card's, so the track grew by the same amount to leave the names exactly the
   room they had. */
.scn-proj {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 10px;
  padding: 4px;
}
.scn-pgroup {
  background: var(--surface-2); border: 1px solid var(--border-2);
  border-radius: var(--r-md); padding: 10px 10px 8px;
}
.scn-pgroup-head {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding-bottom: 6px; border-bottom: 1px solid var(--border-2);
}

/* "5 → 4", and the change beside it. Tabular figures so the numbers on twelve
   position cards line up down the grid instead of wobbling. */
.scn-delta {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 12px; font-weight: 700; color: var(--label-2);
  font-variant-numeric: tabular-nums;
}
.scn-delta i { display: inline-flex; color: var(--label-3); }
.scn-delta i svg { width: 11px; height: 11px; }
.scn-delta em {
  font-style: normal; font-size: 10.5px; font-weight: 700;
  padding: 1px 6px; border-radius: var(--r-full); margin-left: 2px;
}
.scn-delta--down em { background: var(--red-light);   color: var(--red);   }
.scn-delta--up   em { background: var(--green-light); color: var(--green); }
.scn-delta--down  { color: var(--red);   }
.scn-delta--up    { color: var(--green); }

/* ── A position's own budget ───────────────────────────────────────────
   The third and smallest of the three money fields, under each card's heading:
   the roster has a budget, a position has a budget inside it, and a man has a
   price counted against both. Same field, same behaviour, three scales — which
   matters most at the level a staff reaches for least often.

   The figure on the right is what is **left in this room**, because that is the
   number somebody sitting on this card is about to act on. What the room costs
   is the bar, and it's the right-hand figure only when there is no budget to
   subtract it from. */
.scn-gmoney {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 5px 2px 4px;
}
/* The chip is the whole control — caption, dollar mark and field share one
   border, so the hit target is everything you'd think to click and the label
   names the number rather than floating beside it. The <label> wrapper means a
   click anywhere in it lands in the input. */
.scn-gbud {
  display: flex; align-items: center; gap: 3px; min-width: 0; cursor: text;
  padding: 2px 7px; border: 1px solid var(--border); border-radius: var(--r-sm);
  background: var(--surface);
  transition: border-color 0.14s, background 0.14s, box-shadow 0.14s;
}
.scn-gbud:hover { border-color: color-mix(in srgb, var(--accent) 55%, transparent); }
.scn-gbud:focus-within {
  border-color: var(--accent); border-style: solid;
  box-shadow: 0 0 0 3px var(--accent-light);
}
/* Empty reads as an invitation rather than as a blank: dashed and tinted, the
   same gesture the card's own "Add" row makes at its foot. The caption is
   hidden here because the placeholder already says the word. */
.scn-gbud:has(.scn-gbud-in:placeholder-shown) {
  border-style: dashed; background: none;
}
.scn-gbud:has(.scn-gbud-in:placeholder-shown):hover { background: var(--accent-light); }
.scn-gbud:has(.scn-gbud-in:placeholder-shown) .scn-gbud-lbl,
.scn-gbud:has(.scn-gbud-in:placeholder-shown) .scn-gbud-sym { display: none; }

.scn-gbud-lbl {
  font-size: 9px; font-weight: 750; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--label-3); flex-shrink: 0;
}
.scn-gbud-sym { font-size: 10.5px; font-weight: 700; color: var(--label-3); }
.scn-gbud-in {
  width: 50px; padding: 0; border: none; background: none;
  font-family: var(--font); font-size: 11.5px; font-weight: 700;
  letter-spacing: -0.01em; color: var(--label);
  font-variant-numeric: tabular-nums;
  transition: color 0.16s, width 0.16s var(--ease-out);
}
.scn-gbud-in:focus { outline: none; }
/* "Set budget" needs more room than "2.4M", and the exact figure the field
   swaps to on focus needs more still. */
.scn-gbud-in::placeholder { color: var(--label-2); font-weight: 650; }
.scn-gbud-in:placeholder-shown { width: 60px; }
.scn-gbud:hover .scn-gbud-in::placeholder { color: var(--accent-deep); }
:root[data-theme="dark"] .scn-gbud:hover .scn-gbud-in::placeholder { color: var(--accent); }
.scn-gbud-in:focus { width: 84px; }
.scn-gbud-in:disabled { opacity: 0.6; }
/* The save flash is on the chip as well as the figure, since the border is what
   reads as the control now — see flashSaved in views/scenario.js. */
.scn-gbud-in.is-saved { color: var(--green); }
.scn-gbud:has(.scn-gbud-in.is-saved) { border-color: var(--green); }

.scn-gm-fig {
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.01em; flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}
.scn-gm-fig--left { color: var(--green); }
.scn-gm-fig--over { color: var(--red);   }
/* No budget set, so this is what the room costs rather than what it has left —
   a statement, not a verdict, and it wears neither colour. */
.scn-gm-fig--none { color: var(--label-3); font-weight: 600; }

/* Thinner than the hero's, because there are seventeen of them and they are a
   texture down the grid rather than a headline. Always in the DOM so that
   typing the first budget into a card doesn't shift everything below it; the
   track simply goes invisible when there is no budget for a fill to be a
   fraction of. */
.scn-gmeter {
  height: 3px; border-radius: var(--r-full); background: var(--border-2);
  overflow: hidden; margin-bottom: 6px;
  transition: opacity 0.16s;
}
.scn-gmeter.is-empty { opacity: 0; }
.scn-gmeter-fill {
  height: 100%; border-radius: var(--r-full); background: var(--green);
  transition: width 0.3s var(--ease-out), background 0.2s;
}
.scn-gmeter.is-over .scn-gmeter-fill { background: var(--red); }

/* ── A position's target — the target headcount ──────────────────────────
   The count sibling of the budget above: how many bodies a room should hold,
   where the budget is how much they may cost. It sits above the budget on the
   card because roster construction comes first — you decide you want five
   corners before you decide what five corners cost.

   A stepper rather than a typed field, the one place this departs from the
   money fields: a headcount is a small integer nudged a body at a time, so two
   buttons are surer and faster than a keyboard (the same reasoning the depth-
   chart reorder uses). See targetBlock in views/scenario.js. */
.scn-target { padding: 5px 2px 3px; }

/* Unset — the same dashed, quiet-until-hovered invitation the budget chip and
   the Add row wear, so a card's optional planning controls read as one family. */
.scn-target--unset {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
}
.scn-targetset {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 10px 3px 8px; border: 1px dashed var(--border); border-radius: var(--r-full);
  background: none; color: var(--label-2); cursor: pointer;
  font-family: var(--font); font-size: 10.5px; font-weight: 700; letter-spacing: 0.02em;
  transition: background 0.14s, color 0.14s, border-color 0.14s;
}
.scn-targetset svg { width: 12px; height: 12px; color: var(--label-3); transition: color 0.14s; }
.scn-targetset:hover {
  background: var(--accent-light); color: var(--accent-deep);
  border-color: color-mix(in srgb, var(--accent) 55%, transparent);
}
.scn-targetset:hover svg { color: inherit; }
:root[data-theme="dark"] .scn-targetset:hover { color: var(--accent); }
.scn-target-now {
  flex-shrink: 0; font-size: 10.5px; font-weight: 650; color: var(--label-3);
  font-variant-numeric: tabular-nums;
}

/* Set — the stepper on the left, the status on the right, a bar under both. */
.scn-target-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.scn-target-step { display: flex; align-items: center; gap: 4px; }
.scn-target-cap {
  display: inline-flex; align-items: center; gap: 4px; margin-right: 2px;
  font-size: 9px; font-weight: 750; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--label-3);
}
.scn-target-cap svg { width: 11px; height: 11px; color: var(--accent-deep); }
:root[data-theme="dark"] .scn-target-cap svg { color: var(--accent); }

/* Two round buttons that read as one control — the − and + are the same weight
   (see IC.minus / IC.plus), and the number between them is the only thing that
   moves. */
.scn-target-btn {
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 20px; height: 20px; padding: 0;
  border: 1px solid var(--border); border-radius: var(--r-full);
  background: var(--surface); color: var(--label-2); cursor: pointer;
  transition: background 0.13s, color 0.13s, border-color 0.13s, transform 0.1s;
}
.scn-target-btn svg { width: 12px; height: 12px; }
.scn-target-btn:hover {
  background: var(--accent-light); color: var(--accent-deep);
  border-color: color-mix(in srgb, var(--accent) 55%, transparent);
}
:root[data-theme="dark"] .scn-target-btn:hover { color: var(--accent); }
.scn-target-btn:active { transform: scale(0.9); }
.scn-target-btn:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--accent-light); }

.scn-target-n {
  min-width: 16px; text-align: center;
  font-size: 14px; font-weight: 760; letter-spacing: -0.02em; color: var(--label);
  font-variant-numeric: tabular-nums;
}

/* Short of the target is the attention state (gold); on it is settled (green);
   past it is noted but not alarmed (a plain slate) — being deep at a position
   is rarely the emergency being thin is, so it never wears the budget's red. */
.scn-target-status {
  flex-shrink: 0; font-size: 10.5px; font-weight: 700; letter-spacing: 0.01em;
  font-variant-numeric: tabular-nums;
}
.scn-target-status--short { color: var(--gold);  }
.scn-target-status--met   { color: var(--green); }
.scn-target-status--over  { color: var(--label-3); font-weight: 650; }

/* The same thin texture as the budget bar, toned to match the status. Always in
   the DOM so setting the first target doesn't shift the card below it. */
.scn-target-track {
  height: 3px; border-radius: var(--r-full); background: var(--border-2);
  overflow: hidden; margin: 5px 0 1px;
}
.scn-target-fill {
  height: 100%; border-radius: var(--r-full); background: var(--green);
  transition: width 0.3s var(--ease-out), background 0.2s;
}
.scn-target-track--short .scn-target-fill { background: var(--gold);  }
.scn-target-track--met   .scn-target-fill { background: var(--green); }
.scn-target-track--over  .scn-target-fill { background: var(--slate); }

/* The drag list holds nothing but rows — the empty-group note and the departing
   players are siblings of it, so finishGroupDrag can read `list.children` as the
   group's order and nothing else. */
.scn-plist { display: flex; flex-direction: column; }

.scn-prow {
  display: flex; align-items: center; gap: 6px;
  padding: 4px 5px 4px 2px; border-radius: var(--r-sm);
  transition: background 0.13s;
}
.scn-prow:hover { background: var(--surface); }

/* Everything that acts on this man, in one cluster at the end of the row: the
   Leaving button for someone on the roster, the In tag and its ✕ for someone
   coming in, the reason and its ✕ for someone going out. One container, so the
   three cases line up down a card whichever they are. */
/* A minimum width, so the money fields line up down a card. The three tails are
   naturally different widths — a "Leaving" button, an "In" pill plus a ✕, a
   reason <select> plus a ✕ — and with the field sitting immediately before them
   that put the figures at three different x positions inside one card, which is
   the one thing a column of numbers must not do. Pinned to the widest of the
   two that share the ranked list; the departing rows sit in their own section
   below a rule, so their slightly wider tail reads as a different block rather
   than a misalignment. */
.scn-prow-tail {
  display: flex; align-items: center; justify-content: flex-end; gap: 3px;
  flex-shrink: 0; min-width: 80px;
}
.scn-prow-x { width: 22px; height: 22px; }
.scn-prow-x svg { width: 12px; height: 12px; }

/* Quiet until the row is hovered — a card of six loud buttons would drown out
   the names they belong to — but it never leaves the layout, so nothing shifts
   sideways when it appears. Keyboard users get it on focus, and it simply stays
   on touch, where there is no hover to reveal it with. */
.scn-mark { opacity: 0; transition: opacity 0.14s; padding-left: 7px; padding-right: 7px; }
.scn-prow:hover .scn-mark, .scn-mark:focus-visible { opacity: 1; }
.scn-mark svg { width: 12px; height: 12px; }
@media (hover: none) {
  .scn-mark { opacity: 1; }
}
.scn-prow-body {
  flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px;
  color: inherit; text-decoration: none;
}
.scn-prow-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0; }
.scn-prow-name {
  font-size: 12.5px; font-weight: 600; letter-spacing: -0.01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.scn-prow-sub { font-size: 11px; color: var(--label-3); }
.scn-tag { flex-shrink: 0; }

/* ── The grab handle and the depth number ──────────────────────────────
   `touch-action: none` is load-bearing, not a nicety: without it the browser
   claims the gesture for scrolling and the drag never starts on a touchscreen —
   which is the device this is most for. The same rule sits on the board's
   handle; see ui/drag-list.js. */
.scn-prow-handle {
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 18px; height: 26px; border: none; background: none; padding: 0;
  color: var(--label-3); cursor: grab; border-radius: 5px; touch-action: none;
  opacity: 0; transition: opacity 0.14s, color 0.14s, background 0.14s;
}
.scn-prow:hover .scn-prow-handle,
.scn-prow-handle:focus-visible { opacity: 1; }
.scn-prow-handle:hover { color: var(--label-2); background: var(--border-2); }
.scn-prow-handle svg { width: 13px; height: 13px; }
/* Reserved on a departing row so the names stay in one column whether or not the
   row can be dragged — the same "nothing collapses" rule playerFace follows. */
.scn-prow-handle-space { width: 18px; flex-shrink: 0; }
/* No hover to reveal it with, so it simply stays. */
@media (hover: none) {
  .scn-prow-handle { opacity: 1; }
}

.scn-prow-rank {
  flex-shrink: 0; width: 14px; text-align: center;
  font-size: 11px; font-weight: 700; color: var(--label-3);
  font-variant-numeric: tabular-nums;
}

/* Lifted off the chart while it's moving. This drag floats the row free of the
   flow (ui/drag-list.js re-parents it to <body>, position:fixed), so it is its
   own detached card here — a solid --surface fill (the card behind it is
   --surface-2; this is the inverse of the hover state, which settles a row into
   the card rather than picking it up) and a lifted shadow, with a rounded corner
   since it no longer borrows the card's. position/z-index are set inline on the
   floated element; will-change gives it its own layer for the transform that's
   rewritten every frame. */
.scn-prow.is-dragging {
  background: var(--surface); box-shadow: var(--shadow-lg); border-radius: var(--r-sm);
  will-change: transform;
}
.scn-prow.is-dragging .scn-prow-handle { opacity: 1; cursor: grabbing; }

/* The position card a held row is currently over, during a cross-card drag. A
   quiet accent ring rather than a fill, so it reads as "he lands here" without
   repainting the names underneath — the inset keeps it inside the card's own
   rounded corner. Set only while a drag is in flight (see ui/drag-list.js), so
   it never shows at rest. */
.scn-pgroup.is-drop-target {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}

/* The gap a floated row leaves behind and will drop into, during a cross-card
   drag (ui/drag-list.js sets its height to the row's own). A dashed accent
   outline over a faint wash, so the drop slot reads clearly in the column the
   row is headed for. box-sizing keeps the outline inside the reserved height, so
   nothing below it shifts as the placeholder moves from card to card. */
.scn-ph {
  box-sizing: border-box;
  border: 1.5px dashed var(--accent);
  border-radius: var(--r-sm);
  background: var(--accent-light);
}

/* Arriving reads as added; leaving reads as struck out and stepped back. Both
   stay on the card — the value of this pane is the change, and a man who simply
   vanished would be the one change it failed to show. */
.scn-prow.is-in .scn-prow-name { color: var(--green); }
.scn-prow.is-out { opacity: 0.55; }
.scn-prow.is-out .scn-prow-name { text-decoration: line-through; text-decoration-thickness: 1px; }

/* Departures sit below the ranked list, behind a rule and their own label, so
   the numbered chart above reads as the whole of the projection and these read
   as a footnote to it. */
.scn-pouts { margin-top: 6px; padding-top: 5px; border-top: 1px dashed var(--border); }
.scn-pouts-head {
  padding: 0 6px 3px 2px;
  font-size: 10px; font-weight: 750; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--label-3);
}
/* What these departures give this position back. It sits on their own heading
   rather than in the card's budget line because it is money that is *not*
   committed — folding it into "left" would double-count it, since their figures
   stopped counting the moment they were marked out. Green, because at this
   position it is good news, and lower case against the shouted label so it
   reads as the number it is. */
.scn-gm-freed {
  color: var(--green); text-transform: none; letter-spacing: 0;
  font-weight: 700; font-variant-numeric: tabular-nums;
}

/* A position that lost everyone — the alarm this page exists to raise. */
.scn-pempty {
  padding: 8px 6px 4px; font-size: 11.5px; font-weight: 600; color: var(--red);
}
/* A position nobody was ever listed at. Ordinary, so it is stated and not
   shouted — see emptyGroupNote in views/scenario.js. */
.scn-pempty--never { color: var(--label-3); font-weight: 500; }

/* ── Adding into a group ───────────────────────────────────────────────
   A full-width dashed row at the foot of each card rather than a button in its
   header: it reads as the next empty depth slot, which is exactly what it fills.
   Muted until hovered, because on a chart of seventeen cards these would
   otherwise be the loudest thing on the page — and the chart, not the adding, is
   what a coach is here to read. */
.scn-add-row {
  display: flex; align-items: center; justify-content: center; gap: 5px;
  width: 100%; margin-top: 4px; padding: 6px;
  border: 1px dashed var(--border); border-radius: var(--r-sm);
  background: none; color: var(--label-3); cursor: pointer;
  font-family: var(--font); font-size: 11.5px; font-weight: 650;
  transition: background 0.14s, color 0.14s, border-color 0.14s;
}
.scn-add-row svg { width: 12px; height: 12px; }
.scn-add-row:hover {
  background: var(--accent-light); color: var(--accent-deep);
  border-color: color-mix(in srgb, var(--accent) 55%, transparent);
}
:root[data-theme="dark"] .scn-add-row:hover { color: var(--accent); }

/* A departure filed against somebody the current download no longer lists — see
   outRow in views/scenario.js. Said in words on the row rather than only as a
   colour, since the whole point is that it needs explaining. */
.scn-prow.is-stale { opacity: 0.75; }
.scn-stale-note { display: block; color: var(--red); font-weight: 600; }

/* ═══════════════════════════════════════════════════════════════════════════
   THE PLAYER PICKER
   ═══════════════════════════════════════════════════════════════════════════
   A panel that slides in from the right, the same gesture and the same timing
   the inbox uses (see css/inbox.css) — deliberately its own classes rather than
   the inbox's, so a change to one can never quietly restyle the other. The
   backdrop fades while the panel slides: two properties on two elements, both
   driven by one .is-open class added a frame after mount. */
.pick-overlay {
  position: fixed; inset: 0; z-index: 300;
  background: rgba(10, 10, 20, 0);
  display: flex; justify-content: flex-end;
  transition: background 0.24s var(--ease-out);
}
.pick-overlay.is-open { background: rgba(10, 10, 20, 0.42); }

.pick-panel {
  width: min(440px, 100vw); height: 100%; flex-shrink: 0;
  background: var(--surface); box-shadow: var(--shadow-lg);
  display: flex; flex-direction: column;
  transform: translateX(100%);
  transition: transform 0.26s var(--ease-out);
}
.pick-overlay.is-open .pick-panel { transform: translateX(0); }

@media (prefers-reduced-motion: reduce) {
  .pick-overlay, .pick-panel { transition: none; }
}

.pick-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 18px 14px; border-bottom: 1px solid var(--border-2); flex-shrink: 0;
}
.pick-title { display: flex; align-items: center; gap: 9px; font-size: 17px; font-weight: 700; letter-spacing: -0.01em; }
.pick-title svg { width: 17px; height: 17px; color: var(--accent-deep); }
:root[data-theme="dark"] .pick-title svg { color: var(--accent); }

/* Which roster is being searched, and the way back out of it. */
.pick-context {
  display: flex; align-items: center; gap: 10px; flex-shrink: 0;
  padding: 12px 16px; background: var(--surface-2); border-bottom: 1px solid var(--border-2);
}
.pick-context-main { flex: 1; min-width: 0; }
.pick-context-name { font-size: 13.5px; font-weight: 650; letter-spacing: -0.01em; }
.pick-context-sub { font-size: 11.5px; color: var(--label-2); }

/* `.search` sets `flex: 1`, which inside this column panel would make the box
   grow to fill the panel's height. It has to be pinned back to its own size —
   the scrolling list below it is the one thing here that takes the slack. The
   icon keeps the box's own vertical centring (no `top`, so it sits at its
   static position) and only moves right by the panel's gutter. */
.pick-search { flex: 0 0 auto; padding: 12px 16px 10px; }
.pick-search svg { left: 27px; }
.pick-search input { padding: 10px 12px 10px 38px; }

.pick-body { flex: 1; overflow-y: auto; padding: 4px 12px 20px; }

/* Offered above the results rather than folded into a section of its own —
   see openAddRecruitModal in views/scenario.js, the caller. Same dashed,
   quiet-until-hovered language as a position card's own Add row
   (.scn-add-row) — it's the same idea one level up: the next entry, not yet
   on file anywhere this box already searches. */
.pick-addnew {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  width: 100%; margin: 6px 0 10px; padding: 9px;
  border: 1px dashed var(--border); border-radius: var(--r-md);
  background: none; color: var(--label-2); cursor: pointer;
  font-family: var(--font); font-size: 12.5px; font-weight: 620;
  transition: background 0.14s, color 0.14s, border-color 0.14s;
}
.pick-addnew svg { width: 13px; height: 13px; }
.pick-addnew:hover {
  background: var(--accent-light); color: var(--accent-deep);
  border-color: color-mix(in srgb, var(--accent) 55%, transparent);
}
:root[data-theme="dark"] .pick-addnew:hover { color: var(--accent); }

.pick-section + .pick-section { margin-top: 10px; }
.pick-section-head {
  padding: 10px 6px 6px;
  font-size: 10.5px; font-weight: 750; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--label-3);
}
.pick-rows { display: flex; flex-direction: column; }

/* Both row types are whole-width buttons: a small "Add" target on a list
   somebody is working quickly through would be the wrong thing to aim at. */
.pick-team, .pick-player {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  padding: 8px 10px; border: none; background: none; color: inherit;
  border-radius: var(--r-md); cursor: pointer; font-family: var(--font);
  transition: background 0.12s;
}
.pick-team:hover, .pick-player:hover:not(:disabled) { background: var(--surface-2); }

.pick-team-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.pick-team-name { font-size: 13.5px; font-weight: 620; letter-spacing: -0.01em; }
.pick-team-sub { font-size: 11.5px; color: var(--label-2); }
.pick-chev { display: inline-flex; color: var(--label-3); flex-shrink: 0; }
.pick-chev svg { width: 15px; height: 15px; }

.pick-player-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.pick-player-top { display: flex; align-items: center; gap: 6px; min-width: 0; }
.pick-player-name { font-size: 13.5px; font-weight: 620; letter-spacing: -0.01em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pick-player-sub { font-size: 11.5px; color: var(--label-2); }

/* The plus is quiet until the row is hovered; "Added" is not, because it is the
   answer to "did that work". */
.pick-add {
  flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center;
  min-width: 26px; height: 26px; border-radius: var(--r-full);
  background: var(--accent-light); color: var(--accent-deep);
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.02em;
  opacity: 0; transition: opacity 0.14s;
}
.pick-add svg { width: 13px; height: 13px; }
.pick-player:hover .pick-add, .pick-player:focus-visible .pick-add { opacity: 1; }
:root[data-theme="dark"] .pick-add { color: var(--accent); }

.pick-player.is-taken { opacity: 0.55; cursor: default; }
.pick-player.is-taken .pick-add {
  opacity: 1; padding: 0 9px;
  background: var(--green-light); color: var(--green);
}
@media (hover: none) {
  .pick-add { opacity: 1; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   NFL CAP BENCHMARK — one player's crystal-ball panel
   ═══════════════════════════════════════════════════════════════════════════
   A large centered panel opened from a row's crystal ball (see
   ui/nfl-benchmark-popover.js). It borrows the modal shell (.modal-overlay /
   .modal in modals.css) the way critical-factors-popover does, and adds only
   what's specific: the player identity strip, the salary verdict, and the tier
   ladder. */
.nbp-modal { width: min(460px, calc(100vw - 32px)); }
.nbp-head { align-items: flex-start; }
.nbp-title-lbl {
  font-size: 11px; font-weight: 750; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--label-3);
}
.nbp-body { display: flex; flex-direction: column; gap: 16px; }

/* Who this is about — the same face the hero and roster draw, so the panel is
   unmistakably his. */
.nbp-id { display: flex; align-items: center; gap: 13px; }
.nbp-id-main { min-width: 0; }
.nbp-id-name { font-size: 19px; font-weight: 760; letter-spacing: -0.02em; line-height: 1.1; }
.nbp-id-sub {
  margin-top: 3px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 12.5px; color: var(--label-2);
}
.nbp-id-pos { font-weight: 680; color: var(--label); }
.nbp-id-team { position: relative; padding-left: 9px; }
.nbp-id-team::before {
  content: ""; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 3px; height: 3px; border-radius: 50%; background: var(--label-3);
}

/* The verdict — what he costs, and what that buys at his position. The money
   leads at headline size; the sentence sits under it. */
.nbp-verdict {
  padding: 13px 15px; border-radius: var(--r-md);
  background: var(--accent-light); border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
}
.nbp-verdict-money {
  display: block; font-size: 23px; font-weight: 780; letter-spacing: -0.03em;
  color: var(--accent-deep); font-variant-numeric: tabular-nums; line-height: 1.05;
}
:root[data-theme="dark"] .nbp-verdict-money { color: var(--accent); }
.nbp-verdict-txt { display: block; margin-top: 3px; font-size: 13px; font-weight: 600; color: var(--label); }
/* Nothing to place yet — an instruction, not a verdict, so it wears the page's
   quiet surface rather than the accent wash. */
.nbp-verdict--muted {
  background: var(--surface-2); border-color: var(--border-2);
  font-size: 12.5px; color: var(--label-2); line-height: 1.5; font-weight: 500;
}

/* The tier ladder — the five calibers as a climbing set of bars, muted depth to
   gold all-american, each labelled with its scaled dollar figure. The bracket
   the player's salary falls in is lit. */
.nbp-ladder { display: flex; flex-direction: column; gap: 3px; }
.nbp-tier {
  display: grid; grid-template-columns: 92px 1fr auto auto; align-items: center; gap: 10px;
  padding: 7px 9px; border-radius: var(--r-sm); border: 1px solid transparent;
  transition: background 0.14s, border-color 0.14s;
}
.nbp-tier-lbl {
  font-size: 11px; font-weight: 700; letter-spacing: 0.02em; color: var(--label-2);
  white-space: nowrap;
}
.nbp-tier-track {
  height: 7px; border-radius: var(--r-full); background: var(--border-2); overflow: hidden;
}
.nbp-tier-fill { display: block; height: 100%; border-radius: var(--r-full); }
.nbp-tier-fig {
  font-size: 13.5px; font-weight: 720; letter-spacing: -0.02em; color: var(--label);
  font-variant-numeric: tabular-nums; text-align: right; min-width: 58px;
}
.nbp-tier-pct {
  font-size: 10.5px; font-weight: 650; color: var(--label-3);
  font-variant-numeric: tabular-nums; text-align: right; min-width: 34px;
}

/* The caliber gradient — muted depth climbing to the gold of an all-american, so
   the ascending prestige reads before a single number does. */
.nbp-tier--depth   .nbp-tier-fill { background: var(--slate); }
.nbp-tier--two     .nbp-tier-fill { background: color-mix(in srgb, var(--slate) 60%, var(--accent)); }
.nbp-tier--starter .nbp-tier-fill { background: var(--accent); }
.nbp-tier--allconf .nbp-tier-fill { background: color-mix(in srgb, var(--accent) 55%, var(--gold)); }
.nbp-tier--allamer .nbp-tier-fill { background: var(--gold); }

/* The bracket his price lands in. A tinted row and a full-strength label, so the
   two figures he sits between are the first thing the eye finds. */
.nbp-tier.is-hot {
  background: var(--surface-2); border-color: var(--border);
}
.nbp-tier.is-hot .nbp-tier-lbl { color: var(--label); }

/* A tier a team doesn't roster (a "depth" kicker) — 0% of the cap, so it reads
   as not-applicable rather than $0. */
.nbp-tier.is-na .nbp-tier-fig,
.nbp-tier.is-na .nbp-tier-lbl { color: var(--label-3); font-weight: 550; }
.nbp-tier.is-na .nbp-tier-track { opacity: 0; }

/* A position the cap table has no row for. */
.nbp-none {
  padding: 22px 16px; text-align: center;
  font-size: 13px; color: var(--label-2); line-height: 1.5;
}

.nbp-modal-foot { display: flex; align-items: center; justify-content: space-between; gap: 14px; }
.nbp-foot-note { font-size: 11px; color: var(--label-3); line-height: 1.4; text-align: left; }
