:root {
  --bg: #0b0d12;
  --panel: #161922;
  --text: #e6e6e6;
  --muted: #9aa0a6;
  --accent: #ff4d4f;
  --good: #3ecf5f;
  --mixed: #f5c26b;
  --bad: #ff4d4f;
  --twist: #a78bfa;
}

* { box-sizing: border-box; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: 'Courier New', monospace;
  margin: 0;
  padding: 1rem;
  min-height: 100vh;
}

/* Widened from an earlier 480px (phone-portrait width) so the config
   circle-grid can lay out 4 categories across with room for larger circles
   -- team devices in practice are laptops/tablets, not narrow phones, so
   the extra width is fine on every other screen too. */
#app { max-width: 760px; margin: 0 auto; }

/* Utility -- !important is deliberate: several elements toggled by this
   class (#join-form, #decision-buttons, etc.) have their own ID-selector
   `display` rule, which would otherwise win over a plain .hidden class on
   specificity alone and silently fail to hide. This class must always win. */
.hidden { display: none !important; }

/* Surfaces a caught render-time JS error directly on the page -- a team
   phone at a live event has no way to open dev tools, so this is the only
   practical way to find out *what* broke instead of just *that* something
   silently didn't render. Meant to be temporary/diagnostic, not permanent UI. */
#debug-error {
  position: fixed; top: 0; left: 0; right: 0; z-index: 999; background: #500;
  color: #fff; font-size: 0.75rem; padding: 0.5rem; word-break: break-word;
  max-height: 30vh; overflow-y: auto;
}

h1 { color: var(--accent); letter-spacing: 0.04em; font-size: 1.6rem; text-align: center; }
h2 { color: var(--text); font-size: 1.3rem; }
h3 { color: var(--muted); font-size: 1rem; margin-bottom: 0.4rem; }

.muted { color: var(--muted); }
.error { color: var(--bad); min-height: 1.2em; }

#join-form { display: flex; flex-direction: column; gap: 0.75rem; align-items: center; }
#team-name {
  width: 100%; padding: 0.75rem; font-size: 1.1rem; background: var(--panel);
  border: 1px solid #333; color: var(--text); border-radius: 4px;
}
button {
  padding: 0.9rem 1.2rem; font-size: 1.05rem; background: var(--panel);
  color: var(--text); border: 1px solid var(--accent); border-radius: 4px; cursor: pointer;
}
/* (hover: hover) guards every :hover rule in this file -- team devices are
   touchscreens (iPad/tablet), and touch WebKit/Blink simulate a :hover
   state on tap that only clears on a *later* tap elsewhere, not on blur()
   or on the element being hidden/reshown. Without this guard, tapping e.g.
   NEGOTIATE leaves it permanently painted with the hover fill, which reads
   exactly like "this is the selected choice" on the next round even though
   nothing has been picked yet -- a real bug found live, not a focus-ring
   issue (see [[ransom_or_restore_game]] for the two failed focus-based
   fixes that preceded this one). Real pointer devices (mouse/trackpad)
   still get the hover feedback as before. */
@media (hover: hover) {
  button:hover:not(:disabled) { background: var(--accent); color: var(--bg); }
}
button:disabled { opacity: 0.4; cursor: not-allowed; }

#connected-teams { list-style: none; padding: 0; }
#connected-teams li {
  background: var(--panel); margin: 0.3rem 0; padding: 0.5rem 0.75rem; border-radius: 4px;
}
.bot-icon { margin-right: 0.4em; }

.timer {
  font-size: 2.5rem; text-align: center; color: var(--accent); font-weight: bold;
  margin: 0.5rem 0 1rem;
}

#token-counter { text-align: center; margin: 1.75rem 0 0.75rem; }
.token-counter-label {
  display: block; color: var(--muted); font-size: 0.75rem; letter-spacing: 0.1em;
  text-transform: uppercase; margin-bottom: 0.15rem;
}
.token-counter-score {
  display: inline-block; font-size: 2rem; font-weight: 800; color: var(--accent);
  font-variant-numeric: tabular-nums; letter-spacing: 0.03em;
}

/* Config circle-grid: one cell per category, category name above in plain
   white, then a circle filled/colored by the chosen tier's position
   (cheapest/middle/priciest -- see TIER_COLORS in play.js). Two columns so
   7 categories read as 3-4 rows instead of a long single-column list --
   see [[ransom_or_restore_game]] memory for why the earlier
   per-category-color list design was replaced. */
.config-grid {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.5rem 0.6rem; margin: 0.75rem 0;
}
.config-cell { text-align: center; }
.config-circle-row { display: flex; align-items: center; justify-content: center; gap: 0.4rem; }
.config-circle {
  width: 3.4rem; height: 3.4rem; border-radius: 50%; flex-shrink: 0;
  border: 2px solid #2a2a2a;
}
.config-name {
  color: var(--text); font-size: 0.9rem; font-weight: bold; letter-spacing: 0.02em; margin-bottom: 0.4rem;
}
/* Read-only "Your Setup" badges only (see .config-grid-readonly below) --
   the specific tier purchased, shown below the circle. */
.config-tier-label { font-size: 0.8rem; margin-top: 0.15rem; opacity: 0.85; }

/* Setup screen only: all 3 tiers listed in cost order below the circle,
   each a clickable word that selects it directly (see selectConfig in
   play.js) and shows the token delta switching to it would cost (negative)
   or refund (positive) relative to the current selection -- e.g.
   "RBAC (-2)" -- so a table can see every option's price before picking,
   instead of discovering it by trial and error. */
.config-tier-menu { margin-top: 0.5rem; display: flex; flex-direction: column; gap: 0.3rem; }
.config-tier-option { font-size: 0.68rem; line-height: 1.3; cursor: pointer; }
.config-tier-option.selected { font-weight: bold; }
@media (hover: hover) {
  .config-tier-option:not(.unaffordable):hover { text-decoration: underline; }
}
/* Can't afford switching to this tier right now -- dimmed and inert rather
   than just uncolored, so it still reads as "an option that exists" (see
   the same reasoning for .config-btn:disabled it replaced). */
.config-tier-option.unaffordable { opacity: 0.35; cursor: default; }

/* Read-only variant ("Your Setup" badges on the decision/results/final
   screens) -- same name-above-circle stacking as the interactive setup
   screen, but with a single reference tier-label below the circle (instead
   of the clickable tier-menu) and a hairline divider between the two, so
   it's unambiguous which text is the category and which is the level --
   before the divider, both lines sat directly under the circle with no
   separation and read as one confusing blob. Sized a third larger than the
   interactive grid's circles/text plus extra margin, since this badge is
   meant to be skimmed at a glance mid-decision, not studied. */
.config-grid-readonly { gap: 2rem 0.8rem; }
.config-grid-readonly .config-circle { width: 2.3rem; height: 2.3rem; }
.config-grid-readonly .config-name { font-size: 0.95rem; margin-bottom: 0.7rem; }
.config-grid-readonly .config-divider {
  height: 1px; background: rgba(255, 255, 255, 0.15); margin: 0.6rem auto; width: 70%;
}
.config-grid-readonly .config-tier-label { font-size: 0.7rem; margin-top: 0; }

/* A small round icon button rather than a full-width labeled one -- locking
   in is a single deliberate tap at the end of setup, not something that
   needs to compete visually with the config grid above it. */
#lock-in-button {
  width: 3rem; height: 3rem; padding: 0; display: flex; align-items: center;
  justify-content: center; border-radius: 50%; margin: 1.25rem auto 0;
}

.dossier {
  background: var(--panel); border-left: 4px solid var(--accent); padding: 0.75rem;
  margin-bottom: 1rem;
}
.dossier-round { color: var(--muted); font-size: 0.85rem; letter-spacing: 0.1em; }
/* Swapped in for the normal "Round X / Y" label wherever a round heading
   appears, whenever the optional practice round is in progress (see
   GameState._resolve_practice_round) -- muted rather than the app's usual
   accent red, since practice is deliberately the low-stakes screen. */
.practice-label { color: var(--muted); font-weight: bold; letter-spacing: 0.05em; }
.dossier-hint { font-style: italic; margin-top: 0.3rem; }

.demand {
  font-size: 1.6rem; color: var(--accent); text-align: center; font-weight: bold; margin: 1rem 0;
}
.health { text-align: center; font-size: 1.1rem; margin: 0.5rem 0; }

.status-line { text-align: center; color: var(--muted); margin-bottom: 0.75rem; }

/* Three side-by-side columns instead of stacked full-width rows -- makes
   better use of the widened #app, and lets each choice read at a glance
   (icon + name + one line) instead of a long row of mostly-empty space. */
#decision-buttons { display: flex; flex-direction: row; gap: 0.6rem; align-items: stretch; }
.decision-btn {
  flex: 1; display: flex; flex-direction: column; align-items: center;
  text-align: center; gap: 0.35rem; padding: 1rem 0.6rem;
}
.decision-icon { color: var(--accent); }
.decision-btn strong { font-size: 1rem; letter-spacing: 0.03em; }
.decision-desc { color: var(--muted); font-size: 0.78rem; }

/* Negotiate's counteroffer-percent picker -- replaces #decision-buttons in
   place (same panel, same width) once Negotiate is tapped, rather than
   opening a separate screen. */
.negotiate-picker {
  background: var(--panel); border: 1px solid #333; border-radius: 6px;
  padding: 0.9rem 0.75rem; text-align: center;
}
.negotiate-picker-label { margin: 0 0 0.6rem; font-size: 0.95rem; }
.negotiate-picker-label span { color: var(--accent); font-weight: bold; font-size: 1.1rem; }
.negotiate-percent-chips {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.4rem; margin-bottom: 0.75rem;
}
.percent-chip {
  padding: 0.6rem 0.3rem; background: transparent; color: var(--text);
  border: 1px solid #444; border-radius: 4px; font-size: 0.9rem;
}
.percent-chip.active { border-color: var(--accent); color: var(--accent); font-weight: bold; }
@media (hover: hover) {
  .percent-chip:hover { border-color: var(--accent); }
}
.negotiate-picker-actions .negotiate-confirm { width: 100%; margin-bottom: 0.5rem; }
.negotiate-picker-actions .change-button { margin-top: 0; }

/* Shown only at/below NEGOTIATE_INSULT_LOWBALL_THRESHOLD (see play.js) --
   makes the "insult effect" in resolve.py's _scale_negotiate_buckets
   legible in the moment the offer is chosen, not just discovered after the
   fact at resolution. */
.negotiate-insult-warning {
  color: var(--mixed); font-size: 0.8rem; text-align: center; margin: 0 0 0.75rem;
}

.results-choice { font-size: 1.3rem; text-align: center; }

/* Misattribution reveal -- mirrors host.css's version (own "twist" color,
   distinct from the good/mixed/bad severity palette). */
.misattribution-reveal {
  background: var(--panel); border: 2px solid var(--twist); border-radius: 8px;
  padding: 0.9rem 1rem; margin-bottom: 1rem; font-size: 0.85rem;
}
.misattribution-title { color: var(--twist); font-weight: bold; letter-spacing: 0.04em; margin-bottom: 0.4rem; }

#final-history { list-style: none; padding: 0; }
#final-history li {
  background: var(--panel); margin: 0.3rem 0; padding: 0.5rem 0.75rem; border-radius: 4px;
}

.final-rank, .final-score { text-align: center; font-size: 1.4rem; margin: 0.5rem 0; }

/* Budget reminder widget -- a read-only config circle-grid (see .config-grid
   above), shown on every post-setup team screen as a quick reference while
   they're deciding. Replaces an earlier per-category-colored list design --
   see [[ransom_or_restore_game]] memory. */
.budget-badge {
  margin: 0.75rem 0; padding: 0.8rem 1rem; background: var(--panel); border-radius: 6px;
  border: 1px solid #333;
}
.budget-label {
  text-align: center; font-size: 1rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 0.65rem;
}

/* On the decision screen specifically, this is meant to actively inform
   the choice being made right now -- give it more visual weight than the
   quieter, purely-reference appearance it has on other screens. */
#budget-badge-decision { border-color: var(--accent); }

.change-button {
  display: block; width: 100%; margin-top: 0.5rem; background: transparent;
  color: var(--muted); border: 1px dashed #444; font-size: 0.9rem; padding: 0.6rem;
}
@media (hover: hover) {
  .change-button:hover { color: var(--text); border-color: var(--accent); }
}

.decision-recap {
  background: var(--panel); border-left: 3px solid var(--accent); border-radius: 4px;
  padding: 0.6rem 0.75rem; margin-bottom: 1rem; font-size: 0.9rem;
}
.decision-recap .recap-hint { font-style: italic; color: var(--muted); margin-bottom: 0.3rem; }
.decision-recap .recap-demand { color: var(--accent); font-weight: bold; margin-top: 0.3rem; }
