/* ===== Race to the Role: card-game specific styles ===== */
/* Uses tokens already defined in styles.css (--ink, --surface, --border,
   --accent, --radius, --font-mono, --shadow, etc.) and adds the four
   card-category colours plus all game-screen layout. */

:root {
  --cyan: #78dce8;
  --pink: #f48bb7;
  --gold: #ffcb70;
  --lime: #c6f36b;
  --orange: #ff9f5e;
}

/* ===== Setup screen ===== */
.setup {
  max-width: 650px;
  margin: 4vh auto 0;
  padding: 30px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 22px;
  box-shadow: var(--shadow);
}

.setup h2 {
  font-family: var(--font-display);
  font-size: 34px;
  line-height: 1.08;
  letter-spacing: -0.045em;
  margin: 10px 0 12px;
}

.setup p {
  color: var(--ink-soft);
  line-height: 1.65;
  font-size: 14px;
}

.setup label {
  display: block;
  margin: 22px 0 8px;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--ink-soft);
}

#jobSelect {
  width: 100%;
  padding: 0.7rem 0.8rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--ink);
  font-size: 0.95rem;
}

.rules-note {
  font-size: 0.85rem;
  color: var(--ink-soft);
  margin: 1rem 0 1.25rem;
}

.primary-btn {
  background: var(--accent);
  color: var(--on-accent);
  border: 1px solid var(--accent);
  border-radius: var(--radius-sm);
  padding: 0.75rem 1.25rem;
  font-weight: 600;
  font-size: 0.95rem;
  cursor: pointer;
  transition: var(--transition-fast);
  box-shadow: 0 5px 15px rgba(198, 243, 107, 0.15);
}

.primary-btn:hover {
  transform: translateY(-1px);
  filter: brightness(1.08);
}

.primary-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  transform: none;
}

.setup .primary-btn,
.setup .outline-btn,
.setup .quiet-btn,
.setup .btn {
  margin: 0.5rem;
}

.setup-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 1rem;
}

.industry-breadcrumb {
  margin-bottom: 1.5rem;
}

.breadcrumb-link {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  background: none;
  border: none;
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: 0.8rem;
  cursor: pointer;
  padding: 0.5rem 0;
}

.breadcrumb-link:hover {
  text-decoration: underline;
}

/* ===== Industry Selection ===== */
.industry-select {
  max-width: 1200px;
  margin: 2vh 0;
  padding: 20px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 22px;
  box-shadow: var(--shadow);
  text-align: center;
}

.industry-select h2 {
  font-family: var(--font-display);
  font-size: 30px;
  line-height: 1.08;
  letter-spacing: -0.045em;
  margin: 10px 0 12px;
}

.industry-select>p {
  color: var(--ink-soft);
  line-height: 1.65;
  font-size: 14px;
  margin-bottom: 1rem;
}

.industry-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 1rem;
  margin-bottom: 2rem;
}

.industry-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 1rem 1.5rem 0.5rem 1.5rem;
  background: var(--bg);
  border: 2px solid var(--border);
  border-radius: var(--radius);
  cursor: pointer;
  transition: var(--transition-fast);
}

.industry-card:hover {
  border-color: var(--accent);
  transform: translateY(-2px);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
}

.industry-icon {
  font-size: 3rem;
  margin-bottom: 0.25rem;
}

.industry-card h3 {
  font-family: var(--font-display);
  font-size: 1rem;
  margin: 0 0 0.5rem;
  color: var(--ink);
}

.industry-card p {
  font-size: 0.75rem;
  color: var(--ink-soft);
  margin: 0;
}

.industry-select .rules-note {
  margin-top: 1.5rem;
}

/* ===== Buttons ===== */
.quiet-btn {
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--ink);
  border-radius: var(--radius-sm);
  padding: 0.55rem 0.9rem;
  font-size: 0.85rem;
  cursor: pointer;
  transition: var(--transition-fast);
}

.quiet-btn:hover {
  border-color: var(--accent);
}

.quiet-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* ===== Learn screen ===== */
.learn-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
}

.learn-progress {
  font-family: var(--font-mono);
  color: var(--ink-soft);
  font-size: 0.85rem;
}

.learn-content h3 {
  font-family: var(--font-display);
  margin-top: 0;
}

.learn-content {
  min-height: 8rem;
}

/* Learn visual elements */
.learn-visual {
  margin-top: 1.25rem;
  padding: 1rem;
  background: color-mix(in srgb, var(--surface), var(--bg) 50%);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.learn-caption {
  margin-top: 0.75rem;
  font-size: 0.8rem;
  color: var(--ink-soft);
  line-height: 1.5;
}

/* Card type examples */
.learn-card-example {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  justify-content: center;
}
.example-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 0.75rem 1rem;
  border-radius: var(--radius-sm);
  border: 2px solid;
  background: var(--surface);
  min-width: 90px;
  text-align: center;
}
.example-card .card-art { font-size: 1.5rem; margin-bottom: 0.25rem; }
.example-card strong { font-size: 0.75rem; display: block; margin-bottom: 0.125rem; }
.example-card span { font-size: 0.6rem; color: var(--ink-soft); }

/* Flow diagram */
.learn-flow {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0.75rem;
}
.flow-step {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
}
.flow-label { font-size: 0.7rem; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 0.05em; }
.flow-cards { display: flex; gap: 0.35rem; }
.mini-card {
  padding: 0.5rem 0.75rem;
  border-radius: var(--radius-sm);
  border: 2px solid;
  font-size: 0.65rem;
  font-weight: 600;
  text-align: center;
  min-width: 70px;
}
.mini-card.selected { box-shadow: 0 0 0 2px var(--accent); }
.flow-arrow { color: var(--accent); font-size: 1.25rem; font-weight: bold; }

/* Set examples */
.learn-set-examples {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.set-example {
  padding: 0.75rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.set-header {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}
.set-icon { font-size: 1.25rem; }
.set-header strong { font-size: 0.85rem; }
.set-size { font-size: 0.65rem; color: var(--ink-soft); font-family: var(--font-mono); }
.set-cards { display: flex; gap: 0.35rem; flex-wrap: wrap; }
.set-card {
  padding: 0.4rem 0.7rem;
  border-radius: var(--radius-sm);
  border: 2px solid;
  font-size: 0.65rem;
  font-weight: 600;
  text-align: center;
}
.wildcard-demo {
  margin-top: 0.5rem;
  padding: 0.75rem;
  background: color-mix(in srgb, var(--gold-soft), transparent 80%);
  border: 1px solid var(--gold);
  border-radius: var(--radius-sm);
}
.wildcard-note {
  margin-top: 0.5rem;
  font-size: 0.7rem;
  color: var(--gold);
  font-weight: 600;
}

/* Rival preview */
.rival-preview {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.rival-row {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 0.5rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.rival-name { font-weight: 600; font-size: 0.8rem; }
.rival-strat { font-size: 0.7rem; color: var(--ink-soft); }
.rival-bar {
  height: 6px;
  background: var(--border);
  border-radius: 999px;
  overflow: hidden;
}
.rival-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--accent), var(--good));
  border-radius: 999px;
}

/* Apply preview */
.apply-preview {
  text-align: center;
}
.cv-checklist {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  text-align: left;
  max-width: 280px;
  margin: 0 auto 1rem;
}
.check-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.75rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 0.75rem;
}
.check-item.passed { border-color: var(--good); background: color-mix(in srgb, var(--good), transparent 90%); }
.check-icon { color: var(--good); font-weight: bold; }

@media (max-width: 600px) {
  .learn-flow { flex-direction: column; gap: 1rem; }
  .flow-arrow { transform: rotate(90deg); }
  .example-card { min-width: calc(50% - 0.25rem); }
}

.job-title {
  font-family: var(--font-display);
  font-size: 1.3rem;
  font-weight: 600;
}

.job-desc {
  margin: 0.25rem 0 0;
  color: var(--ink-soft);
  font-size: 0.85rem;
  max-width: 32ch;
}

.job-goal {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  align-items: flex-start;
}

.need {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--ink-soft);
  white-space: nowrap;
}

.need.met {
  color: var(--good);
  font-weight: 600;
}

.need small {
  color: var(--ink-soft);
  font-size: 0.62rem;
  font-weight: 400;
  font-weight: 400;
  display: block;
  margin-top: 0.15rem;
}

/* Pill-shaped requirement indicators */
.need-pills {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  width: 100%;
}
.need-pill {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  padding: 0.6rem 0.85rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.need-pill.met {
  border-color: var(--good);
  background: color-mix(in srgb, var(--good), transparent 92%);
}
.need-pill[data-tip] { cursor: help; }
.pill-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}
.pill-label {
  font-family: var(--font-mono);
  font-size: 0.65rem;
  color: var(--ink);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  flex-shrink: 0;
}
.pill-count {
  font-family: var(--font-mono);
  font-size: 0.65rem;
  color: var(--ink-soft);
  font-weight: 600;
  flex-shrink: 0;
}
.need-pill.met .pill-count {
  color: var(--good);
}
.pill-bar {
  width: 100%;
  height: 6px;
  background: var(--border);
  border-radius: 999px;
  overflow: hidden;
}
.pill-fill {
  height: 100%;
  background: var(--accent);
  border-radius: 999px;
  transition: width 0.3s ease;
}
.need-pill.met .pill-fill {
  background: var(--good);
}
.pill-sub {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.6rem;
  color: var(--ink-soft);
  line-height: 1.4;
}
@media (max-width: 600px) {
  .pill-label { font-size: 0.6rem; }
  .pill-count { font-size: 0.6rem; }
  .pill-sub { font-size: 0.55rem; }
}

.guide {
  background: var(--accent-soft);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm);
  padding: 0.45rem 0.7rem;
  font-size: 0.76rem;
  line-height: 1.4;
  color: var(--ink);
  margin: 0;
  min-height: 1.2em;
  /* Clamped so a long message cannot push the board down. Full text on hover. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.set-builder-status {
  display: flex;
  flex-direction: column;
  gap: 0.22rem;
  margin: 0.75rem 0;
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--line, var(--border));
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink);
  font-size: 0.84rem;
  line-height: 1.45;
}

.set-builder-status strong {
  color: var(--accent);
}

.set-builder-status span {
  color: var(--ink-soft);
}

@media (max-width: 1000px) {}

.turnbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  color: var(--ink-soft);
  margin-bottom: 0.6rem;
}

.turntext {
  font-weight: 600;
  color: var(--ink);
  padding-right: 10px;
  ;
}

/* ===== Rivals ===== */
.rival-board {
  margin-bottom: 0.9rem;
  padding: 0.8rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md, 12px);
  background: color-mix(in srgb, var(--surface), transparent 12%);
}

.rival-board-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.65rem;
}

.rival-board-head h3 {
  margin: 0;
  font-size: 0.95rem;
}

.rival-board-head p {
  margin: 0.2rem 0 0;
  max-width: 680px;
  color: var(--ink-soft);
  font-size: 0.75rem;
  line-height: 1.45;
}

.rival-turn-order {
  flex: 0 0 auto;
  padding: 0.3rem 0.45rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--accent);
  font: 0.62rem var(--font-mono);
  white-space: nowrap;
}

.rivals {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.55rem;
}

.rival-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.55rem 0.75rem;
}

.rival-head {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  font-size: 0.85rem;
}

.rival-strategy {
  color: var(--accent);
  font-size: 0.68rem;
  font-family: var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.rival-plan {
  margin-top: 0.3rem;
  color: var(--ink-soft);
  font-size: 0.72rem;
  line-height: 1.4;
}

.rival-bar {
  height: 6px;
  background: var(--border);
  border-radius: 999px;
  margin: 0.35rem 0;
  overflow: hidden;
}

.rival-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--accent), var(--good));
}

.rival-stats {
  font-size: 0.68rem;
  color: var(--ink-soft);
  font-family: var(--font-mono);
  line-height: 1.45;
}

/* ===== Table sections (market/hand) ===== */
.table {
  margin-bottom: 1rem;
}

.section-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 0.5rem;
}

.section-head h3 {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.05rem;
}

.section-head small {
  font-family: var(--font-mono);
  color: var(--ink-soft);
  font-size: 0.65rem;
  letter-spacing: 0.04em;
}

.panel {
  background: color-mix(in srgb, var(--surface), var(--bg) 50%);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.panel:hover {
  border-color: color-mix(in srgb, var(--border), var(--accent) 40%);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent), transparent 70%);
}

.panel.drag-over {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent-soft), var(--surface) 30%);
  box-shadow: 0 0 0 2px var(--accent-soft);
}

.market,
.hand {
  display: grid;
  /* Hand cap is 6 and the market holds 6, so six equal columns keeps a full hand on
     one row at desktop widths. Cards fill their column instead of a fixed 182px. */
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 0.6rem;
}

.market .card,
.hand .card {
  width: 100%;
}

/* ===== Cards ===== */
/* One colour per card, driven by the card TYPE (Setup / Action / Proof / Impact /
   Wildcard). Both the border and the fill read from it, so they always agree.
   The experience ROUTE a card belongs to is not encoded in colour: it is named in
   the card's text line ("Setup · Block Placement") and explained in the Routes tab
   and the card tooltip. The route list items in the rail do keep their own route
   colours, since there each row is a single route. */
/* Two pieces of information, one dominant and one discreet:
     the card's colour is its experience ROUTE, so it matches the Experience sets
     list, and its TYPE (Setup / Action / Proof / Impact / Wildcard) is the small
     dot in the bottom-right corner. */
.card {
  --card-route: var(--cyan);
  --card-cat: var(--card-route);
  --card-glow: var(--card-cat);
  width: 182px;
  min-height: 178px;
  position: relative;
  isolation: isolate;
  overflow: hidden;
  border-radius: 14px;
  /* Pure route colour, matching the Experience sets list exactly. */
  border: 2px solid var(--card-route);
  background: linear-gradient(180deg, color-mix(in srgb, var(--card-cat), var(--surface) 90%) 0%, var(--surface) 35%, color-mix(in srgb, var(--surface), var(--bg) 20%) 100%);
  color: var(--ink);
  padding: 0.65rem;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.3rem;
  transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
  box-shadow: var(--shadow-md), inset 0 0 0 1px color-mix(in srgb, var(--card-route), var(--surface) 70%);
}

.card::before,
.card::after {
  content: "";
  position: absolute;
  inset: 5px;
  border-radius: 9px;
  pointer-events: none;
}

.card::before {
  z-index: 0;
  opacity: 0.15;
  background: linear-gradient(125deg, transparent 18%, color-mix(in srgb, var(--ink) 15%, transparent) 30%, color-mix(in srgb, var(--cyan) 28%, transparent) 39%, color-mix(in srgb, var(--lime) 28%, transparent) 48%, color-mix(in srgb, var(--pink) 22%, transparent) 57%, transparent 72%);
  background-size: 240% 240%;
  background-position: 100% 0;
  mix-blend-mode: screen;
  transition: opacity 0.18s ease, background-position 0.3s ease;
}

.card::after {
  z-index: 2;
  border: 1px solid color-mix(in srgb, var(--border), var(--ink) 12%);
  box-shadow: inset 0 0 14px color-mix(in srgb, var(--ink) 5%, transparent);
}

.card>* {
  position: relative;
  z-index: 1;
}

.card:hover {
  transform: translateY(-5px) rotate(-1deg) scale(1.025);
  /* Darken the SAME route colour rather than switching channel. Reading
     --card-glow only worked because it happens to alias --card-route, which is
     the kind of implicit coupling that let the border rules drift apart. */
  border-color: color-mix(in srgb, var(--card-route), var(--ink) 18%);
  box-shadow: var(--shadow), 0 0 18px color-mix(in srgb, var(--card-glow), transparent 68%), inset 0 0 0 3px var(--surface), inset 0 0 0 4px color-mix(in srgb, var(--border), var(--ink) 24%);
}

.card:hover::before {
  opacity: 0.28;
  background-position: 0 100%;
}

.card.selected {
  /* A neutral, not a colour: any hue here reads as one of the five route
     colours. Black by day, white at night. Deliberately leaves --card-glow alone
     so the card still shows its own route. */
  outline: 2px solid var(--select);
  outline-offset: 2px;
  box-shadow: 0 0 0 5px var(--select-soft), var(--shadow), inset 0 0 0 3px var(--surface), inset 0 0 0 4px var(--select);
  transform: translateY(-4px);
}

/* Top accent band. Reads --card-glow, which aliases the card's route colour, so the
   band, the border and the fill all agree. It used to be coloured by card type. */
.card::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 4px;
  background: var(--card-glow);
  z-index: 1;
  border-radius: 12px 12px 0 0;
}

/* Card type is carried by shape alone. These five hues are also used for the
   experience routes, so a coloured marker would read as a route. */
.card-type-dot { background: color-mix(in srgb, var(--ink), transparent 35%); }

/* Setup: a square. It is the foundation of a set, and the plainest shape. */
.card.cat-cyan .card-type-dot,
.card.tone-setup .card-type-dot { border-radius: 2px; }

/* Action: a triangle, pointing the way you have to go. */
.card.cat-pink .card-type-dot,
.card.tone-action .card-type-dot {
  clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
  border-radius: 0;
}

/* Proof: a plain dot, the simplest marker. */
.card.cat-gold .card-type-dot,
.card.tone-proof .card-type-dot {
  border-radius: 50%;
  clip-path: none;
}

/* Impact: a diamond, the punchiest shape here. */
.card.cat-orange .card-type-dot,
.card.tone-impact .card-type-dot {
  clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
  border-radius: 0;
}

/* Wildcard: a star, sized up a little because a star at the same box as the
   other shapes reads thinner than they do. */
.card.cat-lime .card-type-dot,
.card.tone-wild .card-type-dot {
  clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
  border-radius: 0;
  width: 0.92rem;
  height: 0.92rem;
  right: 0.32rem;
  bottom: 0.3rem;
}

/* Match card borders and stored-set tiles by opportunity route. */
.card.set-placement,
.set-row.set-placement,
.banked-set-tile.set-placement {
  --card-route: #4fa6ef;
  --card-glow: #4fa6ef;
}

.card.set-visit,
.set-row.set-visit,
.banked-set-tile.set-visit {
  --card-route: #b184ea;
  --card-glow: #b184ea;
}

.card.set-volunteering,
.set-row.set-volunteering,
.banked-set-tile.set-volunteering {
  --card-route: #40b99a;
  --card-glow: #40b99a;
}

.card.set-brief,
.set-row.set-brief,
.banked-set-tile.set-brief {
  --card-route: #ed9c4d;
  --card-glow: #ed9c4d;
}

.card.set-partnership,
.set-row.set-partnership,
.banked-set-tile.set-partnership {
  --card-route: #e66b98;
  --card-glow: #e66b98;
}

.set-row[class*="set-"] {
  border-left: 4px solid var(--card-glow);
  padding-left: 0.45rem;
  background: color-mix(in srgb, var(--surface), var(--card-glow) 8%);
}

/* Wildcards fit any route, so they carry no route colour. --card-cat matches
   --card-route so the fill, the top band and the border all agree; setting it to a
   near-white surface made the top band invisible. */
.card.wildcard-card {
  --card-route: color-mix(in srgb, var(--border), var(--ink) 22%);
  --card-cat: color-mix(in srgb, var(--surface), var(--ink) 6%);
}

.card.wildcard-card::before {
  opacity: 0.22;
}

.storage-count {
  color: var(--accent);
  font: 0.65rem var(--font-mono);
  white-space: nowrap;
}

.banked-set-list {
  display: grid;
  gap: 0.4rem;
}

.storage-empty {
  border: 1px dashed var(--border);
  border-radius: var(--radius-sm);
  padding: 0.65rem;
  color: var(--ink-soft);
  font-size: 0.75rem;
  text-align: center;
}

.banked-set-tile {
  --card-glow: var(--accent);
  display: flex;
  align-items: center;
  gap: 0.55rem;
  min-width: 0;
  padding: 0.55rem 0.65rem;
  border: 1px solid color-mix(in srgb, var(--border), var(--card-glow) 45%);
  border-left: 4px solid var(--card-glow);
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--surface), var(--card-glow) 8%);
  color: var(--ink);
}

.banked-set-art {
  font-size: 1.35rem;
  flex: 0 0 auto;
}

.banked-set-tile>div {
  display: grid;
  gap: 0.12rem;
  min-width: 0;
}

.banked-set-tile strong {
  font-size: 0.78rem;
  overflow-wrap: anywhere;
}

.banked-set-tile small {
  color: var(--ink-soft);
  font-size: 0.65rem;
  line-height: 1.3;
}

.banked-set-repeat {
  margin-left: auto;
  color: var(--card-glow);
  font: 0.7rem var(--font-mono);
}

.card-art {
  font-size: 2rem;
  filter: drop-shadow(0 2px 4px var(--black-20));
  margin-top: 0.3rem;
}

.card-name {
  color: var(--ink);
  font-weight: 700;
  font-size: 0.82rem;
  line-height: 1.25;
  overflow-wrap: anywhere;
}

.card-type {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  color: var(--ink-soft);
  text-transform: uppercase;
  letter-spacing: 0.035em;
  line-height: 1.35;
}

.card-top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  font-family: var(--font-mono);
  font-size: 0.65rem;
  color: var(--ink-soft);
  margin-top: auto;
}

.controls {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.75rem;
}

.left-actions,
.right-actions {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}

#bankBtn.ready-to-bank {
  background: linear-gradient(135deg, var(--gold), var(--gold-soft));
  color: #fff;
  box-shadow: 0 0 0 3px var(--gold), 0 0 20px 4px var(--gold);
  animation: bankPulse 1.5s ease-in-out infinite;
}

#bankBtn.ready-to-bank:hover {
  box-shadow: 0 0 0 4px var(--gold), 0 0 30px 6px var(--gold);
}

@keyframes bankPulse {

  0%,
  100% {
    box-shadow: 0 0 0 3px var(--gold), 0 0 20px 4px var(--gold);
  }

  50% {
    box-shadow: 0 0 0 5px var(--gold), 0 0 30px 8px var(--gold);
  }
}

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.9rem;
  margin-top: 0.75rem;
  font-size: 0.75rem;
  color: var(--ink-soft);
  align-items: center;
}

.legend .dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  display: inline-block;
  margin-right: 0.3rem;
  vertical-align: middle;
}

/* ===== Sidebar ===== */
.sidebar {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.set-list {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.set-row {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.82rem;
  padding: 0.25rem 0;
  border-bottom: 1px solid var(--border);
}

.set-row:last-child {
  border-bottom: none;
}

.set-name {
  flex: 1;
}

.set-recipe {
  display: block;
  margin-top: 0.15rem;
  color: var(--ink-soft);
  font-size: 0.68rem;
  line-height: 1.35;
}

.set-count {
  font-family: var(--font-mono);
  font-weight: 700;
  color: var(--accent);
}

.cv-stats {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  font-size: 0.85rem;
}


.cv-row strong {
  text-align: right;
}

.log {
  max-height: 220px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.log-line {
  font-size: 0.78rem;
  color: var(--ink-soft);
  border-bottom: 1px dashed var(--border);
  padding-bottom: 0.3rem;
}

.log-line:last-child {
  border-bottom: none;
}

.help {
  font-size: 0.82rem;
  color: var(--ink-soft);
  line-height: 1.5;
}

/* ===== Animations =====
 * These were both named `pulse` at different depths, so the later definition in
 * the file silently overrode the earlier one for both uses. Named by purpose now.
 */
@keyframes pulse-soft {

  0%,
  100% {
    opacity: 1;
  }

  50% {
    opacity: 0.35;
  }
}

@keyframes pulse-alert {

  0%,
  100% {
    opacity: 1;
  }

  50% {
    opacity: 0.5;
  }
}

/* ===== Timer =====
 * Consolidated here from styles.css and card-styles.css, which both defined
 * .timer-display. card-styles.css loads last, so its shorter rule was silently
 * winning. The timer is a board component, so it lives with the rest of the game.
 *
 * The timer floats over the career feed, so it has no row of its own.
 */
.timer-display {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.35rem 0.9rem 0.35rem 0.7rem;
  font-size: 0.95rem;
}

/* Row that holds the turn timer and the players button, floated right on the
   same line as the wordmark. */
.header-meta {
  grid-area: timer;
  justify-self: end;
  align-self: center;
  display: flex;
  /* stretch, not center: the timer, the Players button and the tooltip toggle are a
     matched set and were rendering at three different heights. The row takes its
     height from the tallest child and the rest fill it. */
  align-items: stretch;
  gap: 0.6rem;
}

/* Players: a labelled control, not another anonymous header icon. */
.players-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}

.players-btn:hover,
.players-btn[aria-expanded="true"] {
  border-color: var(--accent);
  color: var(--accent);
  background: color-mix(in srgb, var(--accent), transparent 92%);
}

.players-btn i {
  font-size: 0.75rem;
}

.players-count {
  min-width: 1.15rem;
  padding: 0 0.3rem;
  border-radius: 999px;
  background: var(--accent);
  color: var(--bg);
  font-size: 0.6rem;
  font-weight: 700;
  text-align: center;
}

.header-timer {
  /* Floated right on the same row as the wordmark. align-self is left unset so the
     row can stretch it to match the other controls. */
  justify-self: end;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.3rem 0.9rem 0.3rem 0.7rem;
  font-size: 0.9rem;
}

.timer-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--good);
  animation: pulse-soft 1.5s ease-in-out infinite;
}

.timer {
  font-family: var(--font-mono);
  font-weight: 700;
  letter-spacing: 0.02em;
}

.timer.low {
  color: var(--bad);
}

/* ===== Toast ===== */
.toast {
  position: fixed;
  left: 50%;
  bottom: 1.5rem;
  transform: translateX(-50%) translateY(120%);
  background: var(--ink);
  color: var(--bg);
  padding: 0.65rem 1.1rem;
  border-radius: var(--radius-pill);
  font-size: 0.85rem;
  box-shadow: var(--shadow-md);
  transition: transform 0.3s ease, opacity 0.3s ease;
  z-index: 500;
  max-width: 90vw;
  text-align: center;
  opacity: 0;
}

.toast.show {
  transform: translateX(-50%) translateY(0);
  opacity: 1;
}

/* ===== Generic modal backdrop (event / win modals) ===== */
.modal-back {
  position: fixed;
  inset: 0;
  background: var(--overlay);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
  z-index: 300;
  padding: 1rem;
}

.modal-back.show {
  opacity: 1;
  pointer-events: auto;
}

.modal-back .modal-content {
  background: var(--surface);
  border-radius: var(--radius);
  padding: 1.5rem;
  max-width: 420px;
  width: 100%;
  box-shadow: var(--shadow-md);
}

.modal-back .modal-content h2 {
  margin-top: 0;
  font-family: var(--font-display);
}

.modal-back .modal-content .modal-actions {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-top: 1rem;
}

.modal-back .modal-content .modal-actions .btn {
  width: 100%;
}

/* ===== Rival turn summaries ===== */
.modal-back .modal-content:has(.rival-turn-modal) {
  width: min(760px, calc(100vw - 2rem));
  max-width: 760px;
  max-height: min(88vh, 820px);
  overflow-y: auto;
  box-sizing: border-box;
}

.rival-turn-modal>.eyebrow {
  color: var(--accent);
  font-size: 0.68rem;
}

.rival-turn-modal h2 {
  margin: 0.35rem 0;
}

.rival-modal-plan {
  margin: 0 0 1rem;
  color: var(--ink-soft);
  font-size: 0.85rem;
}

.rival-turn-actions {
  display: grid;
  gap: 0.65rem;
}

.rival-action-row {
  display: grid;
  grid-template-columns: 2rem minmax(120px, 1fr) auto;
  align-items: center;
  gap: 0.75rem;
  padding: 0.7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
}

.rival-action-number {
  width: 1.8rem;
  height: 1.8rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent);
  font: 0.75rem var(--font-mono);
}

.rival-action-row b {
  color: var(--ink);
  font-size: 0.85rem;
}

.rival-action-row p {
  margin: 0.15rem 0 0;
  color: var(--ink-soft);
  font-size: 0.75rem;
}

.rival-action-cards {
  display: flex;
  gap: 0.4rem;
}

.rival-action-card {
  --rival-card-glow: var(--cyan);
  width: 112px;
  min-height: 88px;
  display: grid;
  grid-template-columns: 1.5rem 1fr;
  grid-template-rows: auto 1fr;
  align-items: start;
  gap: 0.2rem 0.45rem;
  padding: 0.45rem;
  border: 1px solid color-mix(in srgb, var(--border), var(--rival-card-glow) 45%);
  border-left: 3px solid var(--rival-card-glow);
  border-radius: var(--radius-xs);
  background: var(--surface);
  color: var(--ink);
}

.rival-action-card.cat-pink {
  --rival-card-glow: var(--pink);
}

.rival-action-card.cat-gold {
  --rival-card-glow: var(--gold);
}

.rival-action-card.cat-lime {
  --rival-card-glow: var(--lime);
}

.rival-action-art {
  grid-row: 1 / 3;
  font-size: 1.25rem;
}

.rival-action-label {
  color: var(--ink-soft);
  font: 0.52rem var(--font-mono);
  text-transform: uppercase;
}

.rival-action-card strong {
  font-size: 0.66rem;
  line-height: 1.2;
  overflow-wrap: anywhere;
}

.rival-win-callout {
  margin: 0.9rem 0 0;
  padding: 0.7rem;
  border: 1px solid var(--good);
  border-radius: var(--radius-sm);
  background: var(--good-soft);
  color: var(--ink);
  font-weight: 600;
}

.rival-turn-modal .modal-actions {
  margin-top: 1rem;
}

@media (max-width: 600px) {
  .modal-back .modal-content:has(.rival-turn-modal) {
    width: calc(100vw - 1.5rem);
    max-width: 760px;
    padding: 1rem;
    max-height: 90vh;
  }

  .rival-action-row {
    grid-template-columns: 1.8rem 1fr;
  }

  .rival-action-cards {
    grid-column: 2;
    flex-wrap: wrap;
  }

  .rival-action-card {
    width: min(112px, 42vw);
  }

  .card-preview-wrap {
    width: calc(100vw - 2rem);
  }

  .card-preview {
    min-height: min(400px, calc(100vh - 2rem));
  }
}

/* ===== Card preview modal ===== */
.card-preview-backdrop {
  position: fixed;
  inset: 0;
  background: var(--overlay);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
  z-index: 400;
  padding: 1rem;
}

.card-preview-backdrop.open {
  opacity: 1;
  pointer-events: auto;
}

.card-preview-wrap {
  position: relative;
  width: min(360px, calc(100vw - 2rem));
  max-width: 100%;
  max-height: calc(100vh - 2rem);
  animation: previewPop 0.15s ease;
}

@keyframes previewPop {
  from {
    transform: scale(0.92);
    opacity: 0;
  }

  to {
    transform: scale(1);
    opacity: 1;
  }
}

.preview-close {
  position: absolute;
  top: -28px;
  right: -8px;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--ink);
  color: var(--bg);
  border: none;
  font-size: 1.2rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10;
  box-shadow: var(--shadow-sm);
}

.preview-close:hover {
  filter: brightness(1.1);
}

.card-preview {
  /* Deliberately does NOT re-declare --card-glow. Doing so pinned the top band to
     cyan while the border resolved from --card-route, so the band and the frame
     disagreed. Inheriting the base chain keeps both on the route colour. */
  width: 100%;
  min-height: min(420px, calc(100vh - 2rem));
  max-height: calc(100vh - 2rem);
  box-sizing: border-box;
  border-radius: var(--radius);
  border: 2px solid var(--card-route);
  background: linear-gradient(150deg, color-mix(in srgb, var(--card-route), var(--surface) 80%), var(--surface) 58%, color-mix(in srgb, var(--surface), var(--bg) 38%));
  color: var(--ink);
  box-shadow: var(--shadow-md), inset 0 0 0 4px var(--surface), inset 0 0 0 5px var(--border);
  overflow: hidden;
  padding: 1rem 0.85rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.35rem;
}

.card-preview .card-art {
  font-size: 3.6rem;
  margin: 1.2rem 0 0.6rem;
  filter: drop-shadow(0 3px 8px var(--black-20));
}

.card-preview .card-name {
  color: var(--ink);
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1.25;
}

.card-preview .card-description {
  color: var(--ink-soft);
  font-size: 0.9rem;
  line-height: 1.5;
  margin: 0.3rem 0 0.75rem;
}

.preview-meta {
  font-size: 0.75rem;
  color: var(--ink-soft);
  margin: 0.5rem 0 0.75rem;
  padding: 0.5rem 0.75rem;
  background: var(--bg);
  border-radius: var(--radius-sm);
  width: 90%;
  text-align: left;
  line-height: 1.5;
}

.preview-meta b {
  color: var(--ink);
}

.card-preview .card-top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  padding: 0 0.75rem;
  font-family: var(--font-mono);
  font-size: 0.65rem;
  color: var(--ink-soft);
  margin-top: auto;
}

.preview-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  justify-content: center;
  width: 100%;
  padding: 0.5rem 0.75rem 0;
}

.preview-actions button {
  flex: 1 1 45%;
  min-width: 110px;
}

/* ===== Hand limit discard modal ===== */
.discard-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 1rem 0;
}

.discard-grid .card {
  width: 80px;
  min-height: 100px;
  font-size: 0.65rem;
}

/* ===== Responsive ===== */
@media (max-width: 768px) {
  .job-goal {
    flex-direction: row;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: flex-start;
  }

  .need {
    font-size: 0.7rem;
    padding: 0.3rem 0.5rem;
  }

  .guide {
    font-size: 0.8rem;
    padding: 0.5rem 0.75rem;
  }
}

@media (max-width: 600px) {
  .card {
    width: clamp(104px, 28vw, 132px);
    min-height: 158px;
    padding: 0.55rem;
  }

  .card-preview-wrap .card {
    width: 74vw;
  }

  .card-art {
    font-size: 1.8rem;
  }

  .card-name {
    font-size: 0.76rem;
  }

  .card-type {
    font-size: 0.58rem;
  }

  .market,
  .hand {
    gap: 0.4rem;
  }

  .controls {
    flex-direction: column;
    align-items: stretch;
  }

  .left-actions,
  .right-actions {
    justify-content: center;
  }

  .left-actions button,
  .right-actions button {
    flex: 1;
    min-width: 0;
  }

  .legend {
    gap: 0.5rem;
    font-size: 0.7rem;
  }

  .legend .dot {
    width: 8px;
    height: 8px;
  }

  .rivals {
    grid-template-columns: 1fr;
  }

  .rival-board-head {
    flex-direction: column;
    gap: 0.45rem;
  }

  .rival-head {
    align-items: flex-start;
    gap: 0.35rem;
  }

  .rival-stats {
    font-size: 0.68rem;
  }

  .preview-actions button {
    flex: 1 1 100%;
    min-width: 0;
  }
}

@media (max-width: 1200px) {

  .market,
  .hand {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

@media (max-width: 600px) {

  .market,
  .hand {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 480px) {

  .market,
  .hand {
    grid-template-columns: 1fr;
  }

  .card {
    width: clamp(100px, 27vw, 116px);
    min-height: 150px;
  }

  .card-preview-wrap .card {
    width: 80vw;
    margin: auto;
  }

  .card-art {
    font-size: 1.65rem;
  }

  .card-name {
    font-size: 0.72rem;
  }

  .job-title {
    font-size: 1.1rem;
  }

  .job-desc {
    font-size: 0.8rem;
  }

  .turnbar {
    font-size: 0.75rem;
  }

  .section-head h3 {
    font-size: 1rem;
  }

  .section-head small {
    font-size: 0.6rem;
  }

  .btn,
  .primary-btn,
  .quiet-btn {
    padding: 0.5rem 0.8rem;
    font-size: 0.8rem;
  }

  .modal-back .modal-content {
    padding: 1rem;
    margin: 0.5rem;
  }

  .preview-close {
    top: -24px;
    right: -4px;
    width: 28px;
    height: 28px;
  }
}

/* Any-route cards belong to no route, so they must not borrow a route colour.
   --accent reads as a brown that sits next to the Live Project Brief orange, and
   it was only setting the border, leaving these cards with a coloured fill and a
   differently coloured edge. Both channels now go neutral, matching wildcards,
   and they are marked by a dashed edge instead of a hue. */
.card.route-flexible-card {
  --card-route: color-mix(in srgb, var(--border), var(--ink) 22%);
  --card-cat: color-mix(in srgb, var(--surface), var(--ink) 6%);
  border-color: var(--card-route);
  border-style: dashed;
  border-width: 2px;
  box-shadow: none;
}

.card .any-route {
  color: var(--accent);
  font-weight: 600;
  font-size: 0.8em;
}

.card .skill-badge {
  color: var(--gold);
  font-weight: 600;
  font-size: 0.8em;
}

/* Drag-and-drop card movement: clear targets, with popup/button alternatives. */
.card[draggable="true"] {
  cursor: grab;
  touch-action: none;
}

.card.dragging-card {
  opacity: 0.42;
  cursor: grabbing;
}

/* .hand.drag-over is the market -> hand drop target, so it stays. */
.hand.drag-over {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  background-color: color-mix(in srgb, var(--surface), var(--accent) 16%);
}

.panel.market.drag-over {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  background-color: color-mix(in srgb, var(--surface), var(--accent) 12%);
}

/* ===== Rival sets modal ===== */
.rival-banked-list {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin: 0.5rem 0 1rem;
}

.rival-banked-row {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0.35rem;
  padding: 0.55rem 0.5rem;
  border-bottom: 1px solid var(--border);
}

.rival-banked-row strong {
  font-size: 0.9rem;
}

.rival-banked-row small {
  color: var(--ink-soft);
  font-style: italic;
}

.rival-set-tags {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}

.rival-banked-set {
  display: grid;
  gap: 0.22rem;
  padding: 0.45rem 0.55rem;
  border-radius: var(--radius-sm);
  font-size: 0.75rem;
  background: color-mix(in srgb, var(--accent), transparent 70%);
}

.rival-banked-set > span {
  display: flex;
  flex-wrap: wrap;
  gap: 0.2rem 0.35rem;
  align-items: baseline;
}

.rival-banked-set small {
  color: var(--ink-soft);
}

.rival-banked-set.taken {
  background: color-mix(in srgb, var(--bad), transparent 70%);
}

.rival-banked-set.available {
  background: color-mix(in srgb, var(--accent), transparent 70%);
}

.rival-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
}

.rival-head strong {
  flex: 1;
}

.rival-bank-count {
  font-size: 0.8rem;
  color: var(--accent);
  font-weight: bold;
  min-width: 1.4rem;
  text-align: center;
}

.small-btn {
  font-size: 0.68rem;
  padding: 0.2rem 0.5rem;
}

.card-skill {
  font-family: var(--font-mono);
  font-size: 0.58rem;
  color: var(--gold);
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  text-transform: uppercase;
  letter-spacing: 0.035em;
  margin-top: 0.25rem;
}

.card-skill i {
  font-size: 0.75rem;
}

.game-over-overlay {
  position: fixed;
  inset: 0;
  background: color-mix(in srgb, var(--surface) 75%, #000 25%);
  backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
  padding: 1rem;
}

.game-over-card {
  /* Was var(--surface-2), which is not a defined token in this project, so the
     background resolved to nothing and the dark overlay showed through. */
  background: var(--surface-raised, var(--surface));
  color: var(--ink);
  border: 2px solid var(--accent);
  border-radius: var(--radius);
  padding: 2rem;
  max-width: 520px;
  text-align: center;
  box-shadow: 0 0 40px var(--accent);
}

.game-over-card h2 {
  font-size: 1.5rem;
  margin: 0 0 1rem;
}

.game-over-card .win-icon {
  font-size: 3rem;
  margin-bottom: 0.5rem;
}

.game-over-card p {
  color: var(--ink-soft);
  line-height: 1.5;
  margin: 0.5rem 0;
}

.game-over-card .final-stats {
  display: flex;
  gap: 1.5rem;
  justify-content: center;
  margin: 1.5rem 0;
  font-size: 0.85rem;
}

.game-over-card .final-stats span {
  color: var(--ink-soft);
}

.game-over-card .final-stats strong {
  color: var(--ink);
}

.game.game-over {
  filter: blur(2px) brightness(0.7);
  pointer-events: none;
}

.need.skill-needed {
  color: var(--gold);
  font-weight: 700;
  animation: pulse-alert 2s ease-in-out infinite;
}

.need.skill-needed small {
  color: var(--gold);
}

/* Role-fit highlight inside the card preview */
.preview-rolefit {
  margin: 0 0 0.6rem;
  padding: 0.5rem 0.6rem;
  border-radius: var(--radius-sm);
  font-size: 0.7rem;
  line-height: 1.45;
  color: var(--ink);
}

.preview-rolefit.fit {
  border: 1px solid color-mix(in srgb, var(--accent), transparent 45%);
  background: color-mix(in srgb, var(--accent), transparent 88%);
}

.preview-rolefit.done {
  border: 1px dashed var(--border);
  background: color-mix(in srgb, var(--surface-raised, var(--surface)), transparent 40%);
  color: var(--ink-soft);
}

.preview-rolefit b {
  display: block;
  font-size: 0.72rem;
  margin-bottom: 0.15rem;
}

.rolefit-note {
  color: var(--ink-soft);
  font-size: 0.65rem;
}

/* Cards that grant the target role's required skill */
.card-skill-key {
  color: var(--gold) !important;
}

/* "Needed for this role" is marked with a gold ring, NOT a border colour. This rule
   has the same specificity as the .card.set-* rules but comes later in the file, so
   setting border-color here would beat every route colour. */
.card.card-key-skill {
  box-shadow: 0 0 0 2px var(--gold), 0 0 14px color-mix(in srgb, var(--gold), transparent 55%);
}

.preview-rolefit.key {
  border: 1px solid var(--gold);
  background: color-mix(in srgb, var(--gold), transparent 82%);
  color: var(--ink);
}

.preview-rolefit.key b {
  color: var(--gold);
}

.card.invalid-card {
  opacity: 0.35;
  border-style: dashed;
}

/* Card face: one skill, extras collapsed to +N, required marker */
.card-skill {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  flex-wrap: nowrap;
  min-width: 0;
  overflow: hidden;
}

.card-skill-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.card-skill i {
  flex: 0 0 auto;
}

.card-skill-more {
  flex: 0 0 auto;
  font-weight: 700;
  color: var(--ink-soft);
  background: color-mix(in srgb, var(--ink-soft), transparent 80%);
  border-radius: 3px;
  padding: 0 0.25rem;
  font-size: 0.55rem;
}

.card-skill-need {
  position: absolute;
  top: -0.1rem;
  left: -0.8rem;
  z-index: 2;
  transform: rotate(-45deg);
  transform-origin: center;
  margin-left: -0.45rem;
  background: var(--card-glow);
  color: var(--bg);
  font-family: var(--font-mono);
  font-size: 0.5rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0.9em 1rem;
  border-radius: 9px;
  pointer-events: none;
  white-space: nowrap;
}

/* Explicit "open this card" affordance: works on touch, no double-click needed */
.card-inspect {
  position: absolute;
  top: 0.3rem;
  right: 0.3rem;
  z-index: 3;
  width: 1.5rem;
  height: 1.5rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: color-mix(in srgb, var(--surface), transparent 25%);
  color: var(--ink-soft);
  font-size: 0.7rem;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s ease;
}

.card:hover .card-inspect,
.card-inspect:focus-visible {
  opacity: 1;
}

.card-inspect:hover {
  color: var(--accent);
  border-color: var(--accent);
}

@media (hover: none) {
  .card-inspect {
    opacity: 1;
  }
}

/* Highlight for the header helper-hints toggle when hints are visible */
.icon-btn.is-active {
  color: var(--accent);
  border-color: var(--accent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent), transparent 70%);
}

/* Hand reordering: insertion indicator while dragging over the hand */
#hand .card.drop-before {
  box-shadow: -4px 0 0 0 var(--accent), 0 0 0 1px var(--border);
}

#hand .card.drop-after {
  box-shadow: 4px 0 0 0 var(--accent), 0 0 0 1px var(--border);
}

#hand .card.dragging-card {
  opacity: 0.4;
}

#hand {
  min-height: 60px;
}

/* End-of-round quiz and prize result */
.challenge-options {
  flex-direction: column;
  align-items: stretch;
}

.challenge-options .btn {
  text-align: left;
  line-height: 1.4;
  padding: 0.6rem 0.8rem;
}

.challenge-options .btn.wrong {
  border-color: var(--bad);
  color: var(--bad);
  opacity: 0.7;
}

.challenge-q {
  font-size: 1rem;
  line-height: 1.5;
  margin: 0.5rem 0 1rem;
}

.challenge-feedback:empty {
  display: none;
}

.wrong-note {
  color: var(--ink);
  font-size: 0.8rem;
  line-height: 1.5;
  margin: 0.75rem 0 0.25rem;
}

.wrong-hint {
  color: var(--ink-soft);
  font-size: 0.72rem;
  margin: 0;
}

.prize-win {
  color: var(--ink);
  font-size: 0.85rem;
  line-height: 1.5;
  margin: 0.75rem 0 0;
  padding: 0.5rem 0.7rem;
  border: 1px solid var(--gold);
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--gold), transparent 85%);
}

/* ===== Tooltips (js/tooltip.js) ===== */
.rttr-tooltip {
  position: absolute;
  z-index: 700;
  /* Wider now that route and skill tips list several bullet steps. */
  max-width: 320px;
  padding: 0.45rem 0.6rem;
  border-radius: var(--radius-sm, 6px);
  /* Pinned rather than themed: the tooltip is a dark popover in both themes. */
  background: #14161f;
  color: #eceaf5;
  border: 1px solid rgba(255, 255, 255, 0.12);
  font-family: var(--font-mono, monospace);
  font-size: 0.68rem;
  line-height: 1.45;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.35);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.12s ease;
}

.rttr-tooltip.is-visible {
  opacity: 1;
}

/* Formatted tooltip content */
.rttr-tooltip b {
  color: #fff;
  font-weight: 700;
}

.rttr-tooltip ul {
  margin: 0.25rem 0 0.4rem;
  padding-left: 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.rttr-tooltip li {
  line-height: 1.4;
}

.rttr-tooltip .tip-head {
  display: block;
  margin-top: 0.4rem;
  font-size: 0.58rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  opacity: 0.7;
}

.rttr-tooltip .tip-dim {
  opacity: 0.75;
}

.rttr-tooltip .tip-fit {
  display: inline-block;
  padding: 0 0.25rem;
  border: 1px solid currentColor;
  border-radius: 2px;
  font-size: 0.55rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  opacity: 0.85;
}

.rttr-tooltip .tip-why {
  display: block;
  margin-top: 0.35rem;
}

.rttr-tooltip .tip-reward {
  display: block;
  margin-top: 0.35rem;
  opacity: 0.85;
}

.rttr-tooltip[hidden] {
  display: none;
}

/* ============================================= */
/* Game board: three columns, fits one screen   */
/* ============================================= */
/* The board is a fixed-height grid so the play area never scrolls. Reference
   material and race state live in tabbed rails; the centre column is always
   visible because it is the part the player actually acts on.
   The app fills the viewport so the board can use the leftover height. */
/* min-height, not height: the app fills the viewport when it can, but grows past
   it when the board needs more room, so the page scrolls instead of clipping a
   card. Pinning this to height:100% is what made the rows shorter than a card. */
html,
body {
  /* min-height, not height: the page must still scroll when the board is taller
     than the viewport. The rail is height-capped on its own instead. */
  min-height: 100%;
}

body {
  display: flex;
  flex-direction: column;
}
/* Only the game locks the page scroll. The industry picker and setup screens are
   normal flow and must still scroll if they are taller than the viewport. */
body.game-active {
  /* Scroll is allowed, so the board can extend below the fold. */
  overflow: visible;
}

.container {
  display: flex;
  flex-direction: column;
  flex: 1;
  /* min-height:0 lets the board shrink below its content, which is what keeps the
     pinned action bar on screen on a short viewport. */
  min-height: 0;
}

.game:not(.hidden) {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.board {
  flex: 1;
  min-height: 0;
  display: grid;
  /* The right rail is a pull-out drawer, so the board is two columns and the
     play area gets the space it used to. */
  grid-template-columns: 250px minmax(0, 1fr);
  gap: 0.75rem;
}

/* ---------- Rails ---------- */
.rail {
  display: flex;
  flex-direction: column;
  min-height: 0;
  /* Never wider than its grid track, and never wider than this. */
  max-width: 260px;
  /* Sticky, so the rail stays in view while the page scrolls and the tabs, body and
     action bar never separate.
     A fixed height, not a max-height: with max-height the rail shrank to fit short
     tabs, so the action bar sat at different heights depending on which tab was
     open. .rail-body (flex:1) then scrolls between the tabs and the pinned bar. */
  position: sticky;
  top: 0;
  /* Adjustable via --app-chrome in styles.css. Everything above the rail
     (header plus page padding) is subtracted from the viewport. */
  height: calc(100vh - var(--app-chrome, 10rem));
  height: calc(100dvh - var(--app-chrome, 10rem));
  background: color-mix(in srgb, var(--surface), var(--bg) 50%);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

.rail-tabs {
  display: flex;
  flex: 0 0 auto;
  border-bottom: 1px solid var(--border);
  background: color-mix(in srgb, var(--surface), var(--bg) 30%);
}

.rail-tab {
  flex: 1;
  appearance: none;
  border: 0;
  border-bottom: 2px solid transparent;
  background: transparent;
  color: var(--ink-soft);
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 0.55rem 0.3rem;
  cursor: pointer;
  transition: color 0.15s ease, border-color 0.15s ease;
}

.rail-tab:hover {
  color: var(--ink);
}

.rail-tab.is-active {
  color: var(--accent);
  border-bottom-color: var(--accent);
  font-weight: 600;
}

.rail-tab:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}


.rail-panel {
  padding: 0.8rem 0.85rem 1rem;
  min-height: 0;
}

.rail-panel[hidden] {
  display: none;
}

.rail-panel h3 {
  font-size: 0.85rem;
  margin: 0 0 0.5rem;
}

.rail-subhead {
  margin-top: 1rem;
  padding-top: 0.7rem;
  border-top: 1px solid var(--border);
  font-size: 0.75rem !important;
  color: var(--ink-soft);
}

.rail-panel .help {
  font-size: 0.75rem;
}

.rail-panel .job-goal {
  font-size: 0.8rem;
}

.legend-compact {
  font-size: 0.68rem;
  gap: 0.4rem;
}

.storage-count {
  font-size: 0.7rem;
  margin-bottom: 0.4rem;
}

.rail-panel-feed {
  padding: 0.5rem;
  height: 100%;
}

/* No inner scroller: the Feed tab scrolls as one area, so the career log and the
   completed-roles history below it are both reachable by scrolling the tab. */
.rail-panel-feed .log {
  max-height: none;
  height: auto;
  overflow: visible;
}

/* ============================================= */
/* Right rail: pull-out drawer                    */
/* ============================================= */
.rail-right {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  /* Full height. It shares the .rail base, which now sets a height for the side
     panel; on a fixed element an explicit height beats top/bottom, so without this
     the drawer would stop short of the bottom of the screen. */
  height: 100vh;
  height: 100dvh;
  width: min(320px, 86vw);
  z-index: 260;
  border-radius: 0;
  border-right: 0;
  border-top: 0;
  border-bottom: 0;
  box-shadow: -14px 0 40px rgba(0, 0, 0, 0.4);
  transform: translateX(100%);
  visibility: hidden;
  transition: transform 0.24s ease, visibility 0.24s ease;
}

.rail-right.is-open {
  transform: translateX(0);
  visibility: visible;
}

.drawer-scrim {
  position: fixed;
  inset: 0;
  z-index: 250;
  background: rgba(6, 7, 14, 0.5);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.24s ease, visibility 0.24s ease;
}

.drawer-scrim.is-open {
  opacity: 1;
  visibility: visible;
}

.drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  flex: 0 0 auto;
  padding: 0.6rem 0.85rem;
  border-bottom: 1px solid var(--border);
}

.drawer-title {
  font-family: var(--font-display);
  font-size: 0.95rem;
  font-weight: 600;
  margin: 0;
}

.drawer-close {
  appearance: none;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--ink-soft);
  width: 1.7rem;
  height: 1.7rem;
  border-radius: 50%;
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}

.drawer-close:hover {
  color: var(--accent);
  border-color: var(--accent);
}

@media (max-width: 1000px) {

  /* Stacked layout: the drawer sits over the whole board. */
  .rail-right {
    width: min(320px, 92vw);
  }
}

/* ---------- Centre column ---------- */
.board-main {
  display: flex;
  flex-direction: column;
  min-height: 0;
  gap: 0.6rem;
}

.board-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  flex: 0 0 auto;
}

/* Eyebrow and title share one line so the header costs a single row, and a long
   role name truncates rather than wrapping and pushing the board down. */
.board-role {
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
  min-width: 0;
}

.board-role .eyebrow {
  flex: 0 0 auto;
  margin: 0;
}

.board-head .job-title {
  font-size: 1.05rem;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The role description now lives in the Needs rail. */
.rail-panel .job-desc {
  font-size: 0.75rem;
  line-height: 1.45;
  margin: 0 0 0.7rem;
}

.board-head .turnbar {
  margin: 0;
  flex: 0 0 auto;
}

.guide {
  flex: 0 0 auto;
  font-size: 0.78rem;
  padding: 0.5rem 0.7rem;
}

/* Market and hand sit side by side so the play area is one screen tall. */
.tables {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  /* Rows, not columns: one column so the market sits above your hand, with each
     spanning the full play-area width. */
  grid-template-columns: minmax(0, 1fr);
  /* Rows fit the cards they hold rather than absorbing every spare pixel, which on
     a tall display stretched the panels and the cards inside them. */
  grid-template-rows: minmax(0, 1fr) minmax(0, 1fr);
  gap: 0.6rem;
}

/* Cards never grow past a natural size, however much room the row has, but they
 * still stretch to the tallest card in their row. align-self:start here would size
 * each card to its own text, so the market and hand cards would end up different
 * heights. */
.tables .panel .card,
.tables .card {
  max-height: var(--card-max-height, 15rem);
  align-self: stretch;
}

.tables .table {
  display: flex;
  flex-direction: column;
}

.tables .section-head {
  flex: 0 0 auto;
}

.tables .panel {
  flex: 1;
  min-height: 0;
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: var(--card-glow) transparent;
}

/* Custom horizontal scrollbar */
.tables .panel::-webkit-scrollbar {
  height: 8px;
}
.tables .panel::-webkit-scrollbar-track {
  background: transparent;
  border-radius: 4px;
}
.tables .panel::-webkit-scrollbar-thumb {
  background: var(--card-glow);
  border-radius: 4px;
  border: 2px solid transparent;
  background-clip: content-box;
}
.tables .panel::-webkit-scrollbar-thumb:hover {
  background: var(--accent);
  background-clip: content-box;
}
.tables .panel::-webkit-scrollbar-corner {
  background: transparent;
}

.set-builder-status {
  flex: 0 0 auto;
}

.board-main .controls {
  flex: 0 0 auto;
  margin-top: 0;
}

/* Market and hand are a single non-wrapping row. The hand cap is 6 and the
   market holds 6, but a narrow screen or a partly-drawn hand must never wrap to a
   second row, so this is a flex row with no wrap. Cards past the sixth slide
   left over their neighbour instead. */
.tables .hand {
  --card-gap: 0.5rem;
  --card-max: 172px;
  /* One expression for the card width, used for both the card and its stack
     offset. A percentage in margin-left resolves against the same containing
     block as width, so the overlap stays exactly half the rendered card even
     when --card-max clamps it. */
  --hand-card-w: min(calc((100% - 5 * var(--card-gap)) / 6), var(--card-max));
  display: flex;
  flex-wrap: nowrap;
  align-items: stretch;
  gap: var(--card-gap);
}

/* The market is a free surface: cards are absolutely positioned into slots, so a
   card can be dragged anywhere on the panel and dropped onto another to stack. */
.tables .market {
  position: relative;
  min-height: 178px;
  /* The market's cards are absolutely positioned and resolve against the padding
     box, so this inset is what keeps the outer cards off the border. The panel
     already contributes 10px; this is the extra the absolute layout needs. */
  padding: 10px;
}
.tables .market.stacking { cursor: copying; }
.tables .market .card { cursor: grab; }
.tables .market .card:active { cursor: grabbing; }

/* The card you would drop onto. */
.tables .market .card.drop-target {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
  z-index: 90 !important;
}
/* Hovering a buried card raises it above the pile so you can see what it is
   before clicking. */
.tables .market .card:hover,
.tables .market .card:focus-visible {
  z-index: 60;
}

/* Every card in a stack is clickable: the top one opens, and the ones beneath
   are lifted to the top when clicked. Only the sliver of each buried card is
   reachable, which is what makes the pile readable. */
.tables .market .card.is-stacked:not(.stack-top) { cursor: pointer; }
.tables .market .card.stack-top { z-index: 50; }
.tables .market .card.dragging-card { opacity: 0.5; z-index: 100; }

.tables .hand .card {
  flex: 0 0 auto;
  /* Six across fills the row; --card-max keeps them from ballooning on a wide
     monitor, and the clamp stops them going below the six-across size. */
  width: var(--hand-card-w);
  min-width: 0;
  align-self: stretch;
}

/* Past the sixth card each one pulls left over the card before it, so the row
   stays a single card tall. Later DOM order wins the paint order, which gives
   the "one on the right sits over the one on its left" effect. */
/* Past the hand cap, cards overlay at 50% so the card below stays readable, the
   same as the market. A bonus prize that draws a 7th or 8th card lands here. */
.tables .hand .card:nth-child(n + 7) {
  margin-left: calc(0.5rem - var(--hand-card-w) / 2);
  z-index: 1;
}
/* A small vertical stagger so a hand pile reads as a stack, not a flat fan. */
.tables .hand .card:nth-child(7) { margin-top: 3px; }
.tables .hand .card:nth-child(8) { margin-top: 6px; }
.tables .hand .card:nth-child(9) { margin-top: 9px; }

/* Hovering or dragging lifts a card clear of the ones it overlaps, so a buried
   card can be read and picked up. */
.tables .hand .card:hover,
.tables .hand .card:focus-visible,
.tables .hand .card.dragging-card,
.tables .hand .card.ready-to-select {
  z-index: 40;
}

/* Narrow screens: shrink the overlap so more of each buried card shows. */
@media (max-width: 1100px) {
  .tables .hand { --card-max: 100%; }
}

/* ---------- Rivals inside the rail ---------- */
.rail-panel .rival-board {
  border: 0;
  padding: 0;
  background: transparent;
}

.rail-panel .rival-board-head {
  display: block;
  margin-bottom: 0.5rem;
}

.rail-panel .rival-board-head p {
  display: none;
}

.rail-panel .rival-turn-order {
  font-size: 0.6rem;
}

.rail .rivals {
  grid-template-columns: 1fr;
  gap: 0.4rem;
}

/* ---------- Responsive ---------- */
@media (max-width: 1200px) {
  .board {
    grid-template-columns: 220px minmax(0, 1fr);
  }
}

@media (min-width: 1001px) {
  /* Wide enough for both columns, so the toggle that opens the left rail as a drawer
     is meaningless and is hidden. */
  .rail-toggle { display: none; }
}

@media (max-width: 1000px) {
  /* Below this the board is height-locked, so a stacked left rail would sit above the
     fold with no way to reach it. It becomes a drawer instead, opened from the
     header, mirroring the right-hand drawer. */
  .board {
    grid-template-columns: 1fr;
  }

  .rail-left {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    width: min(320px, 88vw);
    z-index: 270;
    border-radius: 0;
    border-left: 0;
    border-top: 0;
    border-bottom: 0;
    box-shadow: 14px 0 40px rgba(0, 0, 0, 0.4);
    transform: translateX(-100%);
    visibility: hidden;
    transition: transform 0.24s ease, visibility 0.24s ease;
    /* The drawer is its own height, so the action bar is always reachable. */
    max-height: 100dvh;
  }
  .rail-left.is-open {
    transform: translateX(0);
    visibility: visible;
  }

  .board-main {
    min-height: 0;
  }
}

/* Completed roles inside the Feed rail. The wide-screen history styles assumed a
   centred column; this narrows it for the rail. */
.rail-panel-feed .history {
  margin-top: 0.9rem;
  padding-top: 0.7rem;
  border-top: 1px solid var(--border);
}

.rail-panel-feed .history-header {
  margin-bottom: 0.4rem;
}

.rail-panel-feed .completed-role {
  gap: 0.5rem;
  padding: 0.35rem 0;
}

.rail-panel-feed .completed-role-info strong {
  font-size: 0.78rem;
}

.rail-panel-feed .completed-role-info small {
  font-size: 0.58rem;
}

.rail-panel-feed .completed-role-date {
  font-size: 0.58rem;
}

.rail-panel-feed .history-empty {
  font-size: 0.7rem;
  padding: 0.8rem;
}

/* Round counters beside the hand heading. */
.section-head .hand-count {
  font-family: var(--font-mono);
  font-size: 0.6rem;
  color: var(--ink-soft);
  text-align: right;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Tooltip switch. Colour carries the state: dim and grey when tooltips are off,
   lit gold when they are on. */
.tip-toggle {
  color: var(--ink-soft);
  border-color: var(--border);
  transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}

.tip-toggle i {
  transition: color 0.15s ease, transform 0.15s ease;
}

.tip-toggle:hover {
  color: var(--ink);
  border-color: var(--ink-soft);
}

/* Off */
.tip-toggle.is-off {
  color: var(--ink-soft);
  opacity: 0.6;
  background: var(--bg);
}

.tip-toggle.is-off i {
  color: var(--ink-soft);
}

/* On */
.tip-toggle.is-active {
  color: var(--gold, #ffcb70);
  border-color: var(--gold, #ffcb70);
  background: color-mix(in srgb, var(--gold, #ffcb70), transparent 88%);
  opacity: 1;
}

.tip-toggle.is-active:hover {
  color: var(--gold, #ffcb70);
  border-color: var(--gold, #ffcb70);
}

.tip-toggle.is-active i {
  color: var(--gold, #ffcb70);
}

/* ============================================= */
/* Left rail: pinned action bar + custom scrollbar */
/* ============================================= */
/* The action bar sits outside .rail-body, so it stays put while the rail's
   content scrolls. Sticky rather than fixed: it tracks the bottom of the rail as
   the page scrolls, without detaching from the panel it belongs to. */
.rail-actions {
  flex: 0 0 auto;
  /* In normal flow: the rail above is already sticky, so this rides along with it. */
  position: static;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  padding: 0.6rem 0.7rem;
  background: color-mix(in srgb, var(--surface), var(--bg) 30%);
  border-top: 1px solid var(--border);
  z-index: 2;
}

.rail-actions .primary-btn {
  width: 100%;
}

/* Custom scrollbar for the rail body, so the scroll affordance is visible and
   does not overlap the pinned bar. */
.rail-body {
  /* The single scroll area for every tab in this rail. overflow-x is hidden
     explicitly: with overflow-y set, a visible overflow-x computes to auto and the
     rail grew a sideways scrollbar instead of wrapping. */
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--ink-soft), transparent 45%) transparent;
}
.rail-body::-webkit-scrollbar { width: 10px; }
.rail-body::-webkit-scrollbar-track { background: transparent; }
.rail-body::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--ink-soft), transparent 50%);
  border: 3px solid transparent;
  background-clip: content-box;
  border-radius: 999px;
}
.rail-body::-webkit-scrollbar-thumb:hover {
  background: color-mix(in srgb, var(--ink-soft), transparent 25%);
  background-clip: content-box;
}
/* Rails sit side by side, so only the one under the pointer needs a visible bar. */
.rail-body:hover::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--ink-soft), transparent 45%);
  background-clip: content-box;
}

.rail-body::-webkit-scrollbar {
  width: 10px;
}

.rail-body::-webkit-scrollbar-track {
  background: transparent;
}

.rail-body::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--ink-soft), transparent 50%);
  border: 3px solid transparent;
  background-clip: content-box;
  border-radius: 999px;
}

.rail-body::-webkit-scrollbar-thumb:hover {
  background: color-mix(in srgb, var(--ink-soft), transparent 25%);
  background-clip: content-box;
}

/* Same treatment for any other panel that scrolls, so it is consistent. */
.rail-panel .log,
.rail-body .set-list {
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--ink-soft), transparent 45%) transparent;
}

.rail-body .set-list::-webkit-scrollbar,
.rail-panel .log::-webkit-scrollbar {
  width: 8px;
}

.rail-body .set-list::-webkit-scrollbar-track,
.rail-panel .log::-webkit-scrollbar-track {
  background: transparent;
}

.rail-body .set-list::-webkit-scrollbar-thumb,
.rail-panel .log::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--ink-soft), transparent 55%);
  border: 2px solid transparent;
  background-clip: content-box;
  border-radius: 999px;
}

/* Rail action buttons: a bank label can name a long route ("Bank Industry
   Partnership (4/4)"), so allow wrapping and keep all three the same height. */
.rail-actions>button {
  min-height: 2.4rem;
  line-height: 1.25;
  white-space: normal;
  text-align: center;
  font-size: 0.78rem;
  padding: 0.4rem 0.5rem;
}

.rail-actions>button:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.rail-actions #bankBtn:not(:disabled) {
  border-color: var(--gold);
  color: var(--gold);
}
/* Quiz feedback: a prize, or the note that it was already claimed. */
.quiz-note {
  font-size: 0.72rem;
  color: var(--ink-soft);
  margin: 0.5rem 0 0;
  line-height: 1.45;
}
.prize-none {
  color: var(--ink-soft);
  font-size: 0.82rem;
  line-height: 1.5;
  margin: 0.75rem 0 0;
}

/* Quiz: a prize, or the note that one was already claimed this run. */
.quiz-note {
  font-size: 0.72rem;
  color: var(--ink-soft);
  margin: 0.5rem 0 0;
  line-height: 1.45;
}
.prize-none {
  color: var(--ink-soft);
  font-size: 0.82rem;
  line-height: 1.5;
  margin: 0.75rem 0 0;
}

.legend-note {
  margin: 0.5rem 0 0;
  font-size: 0.68rem;
  line-height: 1.45;
  color: var(--ink-soft);
}
.legend-note b { color: var(--ink); }

/* Card type dot, bottom-right. The card's colour already says which route it
/* Cards with a bottom "needed" ribbon need the dot lifted clear of it. */

/* Card type dot, bottom-right. The card's colour already says which route it
   belongs to, so the type is a small discrete marker. */
/* Card type marker, bottom-right. The card's colour already shows which route it
   belongs to, so the type is a small shape: square, triangle, star, diamond or
   half moon. Shape and colour together, so it reads without relying on hue. */
.card-type-dot {
  position: absolute;
  right: 0.4rem;
  bottom: 0.4rem;
  width: 0.72rem;
  height: 0.72rem;
  border-radius: 50%;
  background: var(--card-cat);
  opacity: 0.95;
  /* No box-shadow: clip-path and mask both cut it away, which would leave the
     shapes sitting on whatever is behind the card. Each type sets its own shape
     below. */
}
/* A card carrying the "needed" ribbon needs the dot lifted clear of it. */
.card:has(.card-skill-need) .card-type-dot { bottom: 0.9rem; }

/* The same five shapes, sized for the legend key. They mirror the markers on the
   card face so the key and the cards read identically. */
.legend .dot {
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 50%;
  display: inline-block;
  flex: 0 0 auto;
}
.legend .dot-square { border-radius: 2px; }
.legend .dot-triangle { clip-path: polygon(50% 0%, 100% 100%, 0% 100%); border-radius: 0; }
.legend .dot-diamond { clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%); border-radius: 0; }
/* Proof is a plain dot: no clip needed, just a full round. */
.legend .dot-plain { border-radius: 50%; clip-path: none; }
/* Wildcard is the star, sized up to match the weight of the other shapes. */
.legend .dot-star {
  clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
  border-radius: 0;
  width: 0.86rem;
  height: 0.86rem;
}

/* The "Card types" heading reads solid black in day mode, so the key looks like a
   heading rather than muted secondary text. Scoped to that heading only, since
   .rail-subhead is shared with the other rail sections. */
html[data-theme="light"] .card-types-head,
.card-types-head { color: #000; font-weight: 700; }

/* ===== Card stacking (opt-in) =====
 * Stacking is off by default: the market and hand lay the cards out in an
 * ordinary row and the panels scroll. The stacking rules below only apply once
 * the setting is switched on, which adds .stacking-on to <html>.
 */

/* Off: the market and hand are single non-wrapping rows. Six cards fill the
   width; any beyond that extend past the panel, which then scrolls sideways
   rather than clipping them or stacking them. */
html:not(.stacking-on) .tables .market,
html:not(.stacking-on) .tables .hand {
  /* The gap lives in a variable because the card width formula below depends on it.
     They were defined separately, drifted apart, and six cards overflowed. */
  --card-gap: 1rem;
  --card-count: 6;
  --card-max: 172px;
  --card-max-wide: 172px;
  display: flex;
  flex-wrap: nowrap;
  align-items: stretch;
  gap: var(--card-gap);
  min-height: 0;
  /* The stacking rule adds an inset for absolutely positioned cards; the plain row
     only needs the panel's own padding, so the extra is dropped here. */
  padding-left: 1rem;
  padding-right: 1rem;
  padding-top: 0;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x proximity;
  padding-bottom: 0.35rem;
}
html:not(.stacking-on) .tables .market .card,
html:not(.stacking-on) .tables .hand .card {
  position: relative;
  flex: 0 0 auto;
  /* Six across: subtract the gaps between them, then cap so cards stay a sensible
     size on a wide monitor instead of stretching. Derived from the same variables
     the row uses, so the two can never disagree again. */
  width: min(
    calc((100% - (var(--card-count) - 1) * var(--card-gap)) / var(--card-count)),
    var(--card-max)
  );
  min-width: 0;
  scroll-snap-align: start;
  /* box-sizing so padding and borders cannot alter the width maths */
  box-sizing: border-box;
  margin: 10px 0;
}

html:not(.stacking-on) .tables .hand .card:nth-child(n + 7) {
  margin-left: 0;
  margin-top: 0;
  z-index: auto;
}
/* With stacking off, both card panels scroll rather than compressing. */
html:not(.stacking-on) .tables .panel {
  overflow-y: auto;
}

/* Horizontal scrollbar, matching the rail's. */
html:not(.stacking-on) .tables .market,
html:not(.stacking-on) .tables .hand {
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--ink-soft), transparent 45%) transparent;
}
html:not(.stacking-on) .tables .market::-webkit-scrollbar,
html:not(.stacking-on) .tables .hand::-webkit-scrollbar { height: 9px; }
html:not(.stacking-on) .tables .market::-webkit-scrollbar-track,
html:not(.stacking-on) .tables .hand::-webkit-scrollbar-track { background: transparent; }
html:not(.stacking-on) .tables .market::-webkit-scrollbar-thumb,
html:not(.stacking-on) .tables .hand::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--ink-soft), transparent 50%);
  border: 2px solid transparent;
  background-clip: content-box;
  border-radius: 999px;
}

/* Tutorial replay, inside the How to Play modal */
.learn-replay {
  margin-top: 1.2rem;
  padding-top: 1rem;
  border-top: 1px solid var(--border);
}
.learn-hint {
  margin: 0.4rem 0 0;
  font-size: 0.72rem;
  color: var(--ink-soft);
  line-height: 1.45;
}

/* The Card types key is shape-only. Its markers are grey: a card's colour already
   means "route", and five different hues here read as a second colour scheme. */
.legend-shapes .dot {
  background: color-mix(in srgb, var(--ink), transparent 35%);
}

/* End-of-round quiz: close control, footer note and a Close button. */
.round-quiz { position: relative; padding-right: 2rem; }
.quiz-close {
  position: absolute;
  top: -0.35rem;
  right: 0;
  width: 1.9rem;
  height: 1.9rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: transparent;
  color: var(--ink-soft);
  font-size: 1.15rem;
  line-height: 1;
  cursor: pointer;
}
.quiz-close:hover { color: var(--accent); border-color: var(--accent); }
.quiz-footer {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin-top: 1rem;
  padding-top: 0.8rem;
  border-top: 1px solid var(--border);
}
.quiz-footer .quiz-note { margin: 0; }
.quiz-footer .btn { align-self: flex-start; }

/* Close control added by openModal(). Absolutely positioned so it clears whatever
   content a modal renders, and given a real hit area for touch. */
.modal-content { position: relative; }
.modal-dismiss {
  position: absolute;
  top: 0.5rem;
  right: 0.6rem;
  z-index: 5;
  width: 1.9rem;
  height: 1.9rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: var(--surface);
  color: var(--ink-soft);
  font-size: 0.8rem;
  line-height: 1;
  cursor: pointer;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.modal-dismiss:hover { color: var(--accent); border-color: var(--accent); }
.modal-dismiss:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ============================================= */
/* Card rows on narrow screens                     */
/* ============================================= */
/* Between 380px and 1280px the market and hand wrap into rows instead of scrolling
   sideways, because a single scrolling row on a phone hides most of the hand.
   Cards per row rises with the available width: 2, then 3, then 4. */
@media (max-width: 1280px) {
  html:not(.stacking-on) .tables .market,
  html:not(.stacking-on) .tables .hand {
    flex-wrap: wrap;
    overflow-x: visible;
    overflow-y: auto;
    row-gap: 0.35rem;
  }
  html:not(.stacking-on) .tables .market .card,
  html:not(.stacking-on) .tables .hand .card {
    width: calc((100% - 1rem) / 2);
    max-width: none;
  }
}
@media (min-width: 761px) and (max-width: 1280px) {
  html:not(.stacking-on) .tables .market .card,
  html:not(.stacking-on) .tables .hand .card {
    width: calc((100% - 2rem) / 3);
  }
}
@media (min-width: 1101px) and (max-width: 1280px) {
  html:not(.stacking-on) .tables .market .card,
  html:not(.stacking-on) .tables .hand .card {
    width: calc((100% - 3rem) / 4);
  }
}
@media (max-width: 380px) {
  /* One card per row on the narrowest phones, so nothing is clipped. */
  html:not(.stacking-on) .tables .market .card,
  html:not(.stacking-on) .tables .hand .card {
    width: 100%;
  }
}

/* ============================================= */
/* Left rail: nothing may force a sideways scroll */
/* ============================================= */
.rail,
.rail-body,
.rail-panel,
.rail-panel * {
  min-width: 0;
  max-width: 100%;
}
.rail-body {
  overflow-wrap: anywhere;
  word-break: break-word;
}
/* Long identifiers can still push a flex row wide without this. */
.rail-panel .set-row > *,
.rail-panel .skill-line > *,
.rail-panel .cv-row > * {
  min-width: 0;
  overflow-wrap: anywhere;
}
/* Route and skill names wrap instead of being cut off. */
.rail-panel .set-name,
.rail-panel .skill-name,
.rail-panel .skill-routes {
  white-space: normal;
  overflow-wrap: anywhere;
}

/* ============================================= */
/* Dealing animation                              */
/* ============================================= */
/* Cards arrive one at a time rather than appearing all at once. The delay comes from
   --i, set per card by dealCards(), so there is no JS timer per card. */
@keyframes dealIn {
  from {
    opacity: 0;
    transform: translateY(-14px) scale(0.9) rotate(-2deg);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes dealInFromSide {
  from {
    opacity: 0;
    transform: translateX(26px) rotate(4deg);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.market.is-dealing > .card {
  animation: dealInFromSide 0.36s cubic-bezier(0.2, 0.8, 0.3, 1) backwards;
  animation-delay: calc(var(--i, 0) * 55ms);
}
.hand.is-dealing > .card {
  animation: dealIn 0.36s cubic-bezier(0.2, 0.8, 0.3, 1) backwards;
  animation-delay: calc(500ms + var(--i, 0) * 55ms);
}

/* The hand is dealt after the market so the market reads as the source. */
.hand.is-dealing > .card { animation-delay: calc(320ms + var(--i, 0) * 55ms); }

/* Respect both the in-game toggle and the OS preference. */
html.card-animations-off .market.is-dealing > .card,
html.card-animations-off .hand.is-dealing > .card {
  animation: none;
}
@media (prefers-reduced-motion: reduce) {
  .market.is-dealing > .card,
  .hand.is-dealing > .card {
    animation: none;
  }
}

/* The left rail's close control only appears when the rail is a drawer. */
.rail-drawer-head { display: none; }
@media (max-width: 1000px) {
  .rail-drawer-head { display: flex; }
}

/* ============================================= */
/* Large displays                                    */
/* ============================================= */
/* On a 4K screen there is far more room than six cards need, so rather than
 * stretching one row of cards to fill it, each container is given room for two
 * rows. The cards themselves keep their natural size (see --card-max-height). */
@media (min-width: 1800px), (min-height: 1100px) {
  :root {
    --card-max-height: 17rem;
  }
  .tables {
    /* Two card rows per container, plus the gap, so 12 cards would sit comfortably
     without the row growing the cards. */
    grid-auto-rows: auto;
    align-content: start;
  }
  .tables .table {
    min-height: calc(2 * var(--card-max-height) + 3rem);
  }
  .tables .panel {
    align-content: start;
  }
}

/* On a very large board the six-across cap leaves the row mostly empty, so let the
 * cards grow with the extra width. Adjust --card-max-wide to taste. */
@media (min-width: 1900px) {
  html:not(.stacking-on) .tables .market,
  html:not(.stacking-on) .tables .hand { --card-max: 210px; }
}
@media (min-width: 2400px) {
  html:not(.stacking-on) .tables .market,
  html:not(.stacking-on) .tables .hand { --card-max: 250px; }
}
@media (min-width: 3000px) {
  html:not(.stacking-on) .tables .market,
  html:not(.stacking-on) .tables .hand { --card-max: 300px; }
}
