/* ═══════════════════════════════════════════════════════════
   PixelDex — Game Boy–inspired design system for Soul Link
   ═══════════════════════════════════════════════════════════ */

:root {
  /* ── Game Boy palette (positional — the source of truth) ── */
  --d0: #0a1a0a;
  --d1: #1a2e1a;
  --d2: #3a5a3a;
  --l1: #8a9e6a;
  --l2: #9aae7a;
  --white: #c0d0a0;
  --amber: #d4b14a;
  --green-glow: #5fd45f;
  --crimson: #c75a5a;

  /* ── Semantic aliases (Step 25 canon — preferred for new work) ── */
  --shadow: var(--d0);    /* deepest bg */
  --ink: var(--d1);       /* primary border, dark text */
  --shade: var(--d2);     /* mid-dark bg, dim text */
  --moss: var(--l1);      /* mid-light bg */
  --canvas: var(--l2);    /* light page bg */
  --paper: var(--white);  /* hi-contrast text on dark */
  --accent: var(--green-glow);
  --success: var(--green-glow);
  --danger: var(--crimson);

  /* ── Danger family (Step 25 — replaces 3 hardcoded hexes) ── */
  --danger-bg: #4a1c1c;
  --danger-border: #6b2c2c;
  --danger-fg: #e8a0a0;

  /* ── Borders ── */
  --border: 3px solid var(--ink);
  --border-thin: 2px solid var(--ink);
  --border-double: 4px double var(--ink);

  /* ── Spacing scale (Step 25 — 8 steps, 2-px grid) ── */
  --s-1: 4px;
  --s-2: 6px;
  --s-3: 8px;
  --s-4: 10px;
  --s-5: 12px;
  --s-6: 14px;
  --s-7: 16px;
  --s-8: 22px;

  /* ── Type scale (Step 25 — 7 steps) ── */
  --t-micro: 7px;
  --t-xs: 8px;
  --t-sm: 9px;
  --t-md: 10px;
  --t-body: 11px;
  --t-lg: 13px;
  --t-xl: 16px;

  /* ── Letter-spacing scale ── */
  --ls-tight: 0.5px;
  --ls-default: 1px;
  --ls-wide: 0.1em;

  /* ── Line-height scale ── */
  --lh-tight: 1;
  --lh-snug: 1.4;
  --lh-body: 1.6;
}

/* Team-builder save-status colors. Class set by team_builder_controller.js
   showStatus(text, modifier) — `modifier` is one of the three below. */
.team-builder-status { font-size: 11px; line-height: 1.6; }
.team-builder-status--saving { color: var(--accent); }
.team-builder-status--saved  { color: var(--l1); }
.team-builder-status--error  { color: #e8a0a0; }

/* Emulator page layout. Single-column stack on narrow viewports so the
   sidebars don't squeeze the canvas to negative width below ~900px;
   three-column desktop layout above. */
.emulator-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
  align-items: stretch;
}

@media (min-width: 900px) {
  .emulator-grid {
    grid-template-columns: 280px minmax(0, 1fr) 280px;
  }
}

/* YOU-badge marker for the run-roster card whose discord_user_id matches
   the current player. Applied by roster_you_marker_controller.js after
   each Turbo Stream broadcast replaces the frame's contents. */
.gb-card--current-user {
  border-width: 4px;
}

html { scroll-behavior: smooth; }

body {
  background: var(--d1);
  color: var(--d1);
  font-family: 'Press Start 2P', monospace;
  font-size: 19px;
  line-height: 1.8;
  min-height: 100vh;
  image-rendering: pixelated;
  display: flex;
  flex-direction: column;
}

/* ── CRT scanline overlay ── */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  background: repeating-linear-gradient(
    0deg,
    transparent 0px,
    transparent 3px,
    rgba(15, 56, 15, 0.025) 3px,
    rgba(15, 56, 15, 0.025) 6px
  );
  pointer-events: none;
  z-index: 100;
}

::selection {
  background: var(--d1);
  color: var(--l2);
}

/* ═══════════════════════════════════════════════════════════
   NAVIGATION
   ═══════════════════════════════════════════════════════════ */

.gb-nav {
  background: var(--d2);
  border-bottom: var(--border);
  padding: 8px 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
  flex-wrap: wrap;
  gap: 8px;
}

.gb-nav-left {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}

.gb-nav-logo {
  font-size: 16px;
  color: var(--l2);
  letter-spacing: 0.08em;
  white-space: nowrap;
}

.gb-nav-link {
  font-size: 11px;
  color: var(--l1);
  text-decoration: none;
  letter-spacing: 0.05em;
  transition: color 0.05s;
  white-space: nowrap;
}

.gb-nav-link:hover {
  color: var(--l2);
  text-decoration: underline;
}

.gb-nav-right {
  display: flex;
  align-items: center;
  gap: 10px;
}

.gb-nav-user {
  font-size: 11px;
  color: var(--white);
}

.gb-nav-avatar {
  width: 24px;
  height: 24px;
  border: var(--border-thin);
}

.gb-nav-logout {
  font-size: 10px;
  color: var(--l1);
  background: none;
  border: var(--border-thin);
  padding: 2px 6px;
  cursor: pointer;
  font-family: 'Press Start 2P', monospace;
  transition: all 0.05s;
}

.gb-nav-logout:hover {
  background: var(--d1);
  color: var(--l2);
}

/* ═══════════════════════════════════════════════════════════
   FLASH MESSAGES
   ═══════════════════════════════════════════════════════════ */

.gb-flash {
  padding: 8px 12px;
  font-size: 11px;
  line-height: 1.6;
  border: var(--border-thin);
  margin-bottom: 8px;
}

.gb-flash-alert {
  background: var(--danger-bg);
  color: var(--danger-fg);
  border-color: var(--danger-border);
}

.gb-flash-notice {
  background: var(--d2);
  color: var(--l2);
}

/* ═══════════════════════════════════════════════════════════
   PIXELDEX TITLE BAR
   ═══════════════════════════════════════════════════════════ */

.title-bar {
  background: var(--d2);
  color: var(--l2);
  padding: 10px 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: var(--border);
  flex-shrink: 0;
}

.title-left {
  display: flex;
  align-items: center;
  gap: 12px;
}

.title-logo { font-size: 18px; }

.title-text {
  font-size: 18px;
  letter-spacing: 0.08em;
}

.title-sub {
  font-size: 13px;
  color: var(--l1);
  letter-spacing: 0.05em;
}

.title-right {
  display: flex;
  align-items: center;
  gap: 16px;
}

.title-stat { text-align: center; }

.title-stat-num {
  font-size: 21px;
  color: var(--l2);
}

.title-stat-label {
  font-size: 11px;
  color: var(--l1);
}

/* ═══════════════════════════════════════════════════════════
   TAB BAR
   ═══════════════════════════════════════════════════════════ */

.tab-bar {
  display: flex;
  background: var(--d1);
  border-bottom: var(--border);
  flex-shrink: 0;
}

.tab-item {
  flex: 1;
  padding: 10px 8px;
  text-align: center;
  font-size: 13px;
  color: var(--l1);
  cursor: pointer;
  border-right: 2px solid var(--d2);
  font-family: 'Press Start 2P', monospace;
  background: var(--d2);
  border-top: none;
  border-bottom: none;
  border-left: none;
  transition: background 0.05s;
  letter-spacing: 0.05em;
}

.tab-item:last-child { border-right: none; }
.tab-item:hover { background: var(--d1); color: var(--l2); }
.tab-item.active { background: var(--d1); color: var(--l2); }

.tab-icon {
  display: block;
  font-size: 20px;
  margin-bottom: 4px;
}

/* ═══════════════════════════════════════════════════════════
   THREE-PANEL LAYOUT
   ═══════════════════════════════════════════════════════════ */

.pc-layout {
  flex: 1;
  display: grid;
  grid-template-columns: 280px 1fr 300px;
  min-height: 0;
  background: var(--l2);
  animation: screenFlash 0.3s ease-out;
}

.panel {
  border-right: var(--border);
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--d2) var(--l1);
}

.panel:last-child { border-right: none; }

.panel::-webkit-scrollbar { width: 10px; }
.panel::-webkit-scrollbar-track { background: var(--l1); }
.panel::-webkit-scrollbar-thumb { background: var(--d2); border: 2px solid var(--d1); }

.panel-header {
  background: var(--d1);
  color: var(--l2);
  padding: 8px 12px;
  font-size: 13px;
  letter-spacing: 0.1em;
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.panel-header-sub {
  font-size: 10px;
  color: var(--l1);
}

.panel-body { padding: 10px; }

/* ═══════════════════════════════════════════════════════════
   TEAM PANEL (LEFT)
   ═══════════════════════════════════════════════════════════ */

.team-slot {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 8px;
  border: var(--border-thin);
  background: var(--l1);
  margin-bottom: 6px;
  cursor: pointer;
  transition: background 0.05s;
}

.team-slot:hover {
  background: var(--d2);
  color: var(--l2);
}

.team-slot:hover .team-nick { color: var(--l1); }
.team-slot:hover .team-types .type-text { border-color: var(--l1); }

.team-slot-num {
  font-size: 18px;
  color: var(--d2);
  width: 20px;
  text-align: center;
  flex-shrink: 0;
}

.team-slot:hover .team-slot-num { color: var(--l1); }

.team-sprite {
  width: 36px;
  height: 36px;
  background: var(--l2);
  border: var(--border-thin);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 25px;
  flex-shrink: 0;
  overflow: hidden;
}

.team-sprite img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  image-rendering: pixelated;
}

.team-info { flex: 1; min-width: 0; }

.team-name {
  font-size: 14px;
  letter-spacing: 0.03em;
}

.team-nick {
  font-size: 10px;
  color: var(--d2);
}

.team-types {
  display: flex;
  gap: 3px;
  margin-top: 3px;
}

.hp-bar {
  width: 56px;
  height: 8px;
  border: 2px solid var(--d1);
  background: var(--l2);
  overflow: hidden;
  flex-shrink: 0;
}

.hp-fill {
  height: 100%;
  background: var(--d1);
}

.hp-fill.dead { background: transparent; }

.team-slot-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px 8px;
  border: var(--border-thin);
  border-style: dashed;
  background: var(--l1);
  margin-bottom: 6px;
  opacity: 0.35;
  font-size: 11px;
  color: var(--d2);
}

/* ═══════════════════════════════════════════════════════════
   PC BOX (CENTER)
   ═══════════════════════════════════════════════════════════ */

.box-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 6px;
}

.box-cell {
  aspect-ratio: 1;
  border: var(--border-thin);
  background: var(--l1);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  cursor: pointer;
  transition: background 0.05s;
  position: relative;
  padding: 4px;
}

.box-cell:hover {
  background: var(--d2);
  color: var(--l2);
}

.box-cell:hover .box-cell-name { color: var(--l2); }
.box-cell:hover .box-cell-loc { color: var(--l1); }

.box-cell-sprite {
  font-size: 35px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

.box-cell-sprite img {
  width: 40px;
  height: 40px;
  image-rendering: pixelated;
}

.box-cell-name {
  font-size: 9px;
  text-align: center;
  letter-spacing: 0.03em;
  line-height: 1.3;
}

.box-cell-loc {
  font-size: 8px;
  color: var(--d2);
  text-align: center;
  line-height: 1.2;
}

.box-cell.dead { opacity: 0.4; }

.box-cell.dead .box-cell-name { text-decoration: line-through; }

.box-cell.dead::after {
  content: 'X';
  position: absolute;
  top: 2px;
  right: 4px;
  font-size: 10px;
  color: var(--d1);
  font-weight: bold;
}

.box-cell.empty {
  border-style: dashed;
  opacity: 0.3;
}

.box-cell.on-team::before {
  content: '\2605';
  position: absolute;
  top: 2px;
  left: 4px;
  font-size: 10px;
  color: var(--d1);
}

.box-cell:not(.empty) {
  cursor: grab;
}

.box-cell:not(.empty):active {
  cursor: grabbing;
}

.box-cell.sortable-ghost {
  opacity: 0.3;
}

.box-cell.sortable-drag {
  opacity: 0.9;
  outline: 3px solid var(--d1);
  z-index: 10;
}

.box-cell.selected {
  background: var(--d2);
  color: var(--l2);
  outline: 3px solid var(--d1);
  outline-offset: -1px;
}

.box-cell.selected .box-cell-name { color: var(--l2); }
.box-cell.selected .box-cell-loc { color: var(--l1); }

.pokemon-detail-bar {
  border: var(--border-double);
  background: var(--l2);
  padding: 10px 12px;
  margin-top: 12px;
}

.box-grid-wide {
  grid-template-columns: repeat(3, 1fr);
}

.box-grid-wide .box-cell {
  aspect-ratio: auto;
  padding: 6px 8px;
  align-items: flex-start;
  min-height: 80px;
}

.box-cell-players {
  display: flex;
  flex-direction: column;
  gap: 1px;
  width: 100%;
}

.box-section-label {
  font-size: 11px;
  color: var(--d2);
  padding: 6px 0 4px;
  letter-spacing: 0.08em;
  border-bottom: 2px solid var(--d2);
  margin-bottom: 8px;
}

/* ═══════════════════════════════════════════════════════════
   RIGHT PANEL: MAP / ROUTE / GYM
   ═══════════════════════════════════════════════════════════ */

.route-card {
  background: var(--l1);
  border: var(--border-thin);
  padding: 10px;
  margin-bottom: 8px;
}

.route-label {
  font-size: 10px;
  color: var(--d2);
  letter-spacing: 0.1em;
  margin-bottom: 4px;
}

.route-name {
  font-size: 15px;
  margin-bottom: 2px;
}

.route-detail {
  font-size: 10px;
  color: var(--d2);
  line-height: 1.8;
}

.badge-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
  margin-top: 6px;
}

.badge-cell {
  aspect-ratio: 1;
  border: var(--border-thin);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
}

.badge-earned {
  background: var(--d2);
  color: var(--l2);
}

.badge-empty {
  background: var(--l2);
  color: var(--d2);
  font-size: 13px;
}

.gym-list-item {
  font-size: 11px;
  padding: 4px 0;
  border-bottom: 1px solid var(--d2);
  display: flex;
  align-items: center;
  gap: 6px;
  line-height: 1.6;
}

.gym-list-item:last-child { border-bottom: none; }

.gym-check {
  flex-shrink: 0;
  width: 14px;
  text-align: center;
  font-size: 13px;
}

.gym-next-highlight {
  background: var(--d2);
  color: var(--l2);
  padding: 6px 8px;
  margin: 4px -6px;
  font-size: 11px;
}

.map-area {
  background: var(--l1);
  border: var(--border-thin);
  padding: 10px;
  margin-bottom: 8px;
  font-size: 9px;
  line-height: 1.4;
  color: var(--d2);
  white-space: pre;
  overflow-x: auto;
}

.map-you { color: var(--d1); font-weight: bold; }

/* ═══════════════════════════════════════════════════════════
   TYPE TEXT BADGES
   ═══════════════════════════════════════════════════════════ */

.type-text {
  font-size: 10px;
  display: inline-block;
  padding: 1px 4px;
  border: 2px solid var(--d2);
  margin: 0 1px;
  line-height: 1.6;
  font-family: 'Press Start 2P', monospace;
}

/* ═══════════════════════════════════════════════════════════
   STATS
   ═══════════════════════════════════════════════════════════ */

.stat-row {
  display: flex;
  justify-content: space-between;
  padding: 3px 0;
  font-size: 11px;
  border-bottom: 1px dotted var(--d2);
}

.stat-row:last-child { border-bottom: none; }
.stat-val { font-size: 14px; }

/* ═══════════════════════════════════════════════════════════
   DIALOG BOX
   ═══════════════════════════════════════════════════════════ */

.dialog {
  border: var(--border-double);
  background: var(--l2);
  padding: 10px 12px;
  margin-top: 10px;
  font-size: 13px;
  line-height: 1.8;
  position: relative;
}

.dialog::after {
  content: '\25BC';
  position: absolute;
  bottom: 6px;
  right: 10px;
  font-size: 10px;
  animation: dialogBlink 1s step-end infinite;
}

@keyframes dialogBlink {
  50% { opacity: 0; }
}

/* ═══════════════════════════════════════════════════════════
   SITE-WIDE UTILITY CLASSES
   ═══════════════════════════════════════════════════════════ */

/* ── Cards ── */
.gb-card {
  background: var(--l1);
  border: var(--border);
  padding: 12px;
  margin-bottom: 10px;
}

.gb-card-dark {
  background: var(--d2);
  color: var(--l2);
  border: var(--border);
  padding: 12px;
  margin-bottom: 10px;
}

/* ── Buttons ── */
.gb-btn {
  font-family: 'Press Start 2P', monospace;
  font-size: 11px;
  padding: 8px 14px;
  border: var(--border-thin);
  cursor: pointer;
  transition: all 0.05s;
  background: var(--l1);
  color: var(--d1);
  letter-spacing: var(--ls-tight);
  line-height: 1.4;
}

.gb-btn:hover {
  background: var(--d2);
  color: var(--l2);
}

.gb-btn-primary {
  font-family: 'Press Start 2P', monospace;
  font-size: 11px;
  padding: 8px 14px;
  border: var(--border-thin);
  cursor: pointer;
  transition: all 0.05s;
  background: var(--d1);
  color: var(--l2);
  letter-spacing: var(--ls-tight);
  line-height: 1.4;
}

.gb-btn-primary:hover {
  background: var(--d2);
  color: var(--l2);
}

.gb-btn-danger {
  font-family: 'Press Start 2P', monospace;
  font-size: 11px;
  padding: 8px 14px;
  border: 2px solid var(--danger-border);
  cursor: pointer;
  transition: all 0.05s;
  background: var(--danger-bg);
  color: var(--danger-fg);
  letter-spacing: var(--ls-tight);
  line-height: 1.4;
}

.gb-btn-danger:hover {
  background: var(--danger-border);
  color: #f0c0c0;
}

.gb-btn-sm {
  font-size: 10px;
  padding: 4px 8px;
}

/* ── Form Inputs ── */
.gb-input {
  font-family: 'Press Start 2P', monospace;
  font-size: 11px;
  padding: 8px 10px;
  border: var(--border-thin);
  background: var(--l2);
  color: var(--d1);
  width: 100%;
  outline: none;
  line-height: 1.4;
}

.gb-input::placeholder {
  color: var(--d2);
  opacity: 0.6;
}

.gb-input:focus {
  border-color: var(--d1);
  box-shadow: 0 0 0 2px var(--d2);
}

.gb-select {
  font-family: 'Press Start 2P', monospace;
  font-size: 11px;
  padding: 8px 10px;
  border: var(--border-thin);
  background: var(--l2);
  color: var(--d1);
  width: 100%;
  outline: none;
  cursor: pointer;
  line-height: 1.4;
}

.gb-select:focus {
  border-color: var(--d1);
  box-shadow: 0 0 0 2px var(--d2);
}

.gb-label {
  display: block;
  font-size: 10px;
  color: var(--d2);
  margin-bottom: 4px;
  letter-spacing: 0.05em;
}

/* ── Modal ── */
.gb-modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(15, 56, 15, 0.75);
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
}

.gb-modal {
  background: var(--l1);
  border: var(--border);
  border-width: 4px;
  padding: 16px;
  width: 100%;
  max-width: 420px;
  margin: 16px;
  position: relative;
  max-height: calc(100vh - 32px);
  overflow-y: auto;
}

.gb-modal-title {
  font-size: 14px;
  color: var(--d1);
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: var(--border-thin);
}

.gb-modal-close {
  position: absolute;
  top: 8px;
  right: 12px;
  font-size: 18px;
  color: var(--d2);
  background: none;
  border: none;
  cursor: pointer;
  font-family: 'Press Start 2P', monospace;
  line-height: 1;
}

.gb-modal-close:hover { color: var(--d1); }

/* ── Links ── */
.gb-link {
  color: var(--d1);
  text-decoration: underline;
  transition: color 0.05s;
  font-size: inherit;
}

.gb-link:hover {
  color: var(--d2);
}

/* ── Status indicators ── */
.gb-status-dead {
  background: var(--danger-bg);
  border-color: var(--danger-border);
  color: var(--danger-fg);
}

.gb-status-caught {
  background: var(--l1);
}

/* ── Section pattern ── */
.gb-section {
  margin-bottom: 16px;
}

.gb-section-header {
  background: var(--d1);
  color: var(--l2);
  padding: 8px 12px;
  font-size: 13px;
  letter-spacing: 0.1em;
  margin-bottom: 8px;
}

/* ── Drag and drop ── */
.gb-drag-zone {
  border: var(--border-thin);
  border-style: dashed;
  background: var(--l2);
  min-height: 60px;
  padding: 8px;
  transition: background 0.05s;
}

.gb-drag-zone.sortable-ghost {
  background: var(--d2);
}

.gb-drag-item {
  background: var(--l1);
  border: var(--border-thin);
  padding: 8px 10px;
  margin-bottom: 4px;
  cursor: grab;
  transition: background 0.05s;
}

.gb-drag-item:active { cursor: grabbing; }

.gb-drag-item:hover {
  background: var(--d2);
  color: var(--l2);
}

/* ── Grid utilities ── */
.gb-grid-2 {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
}

.gb-grid-3 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}

.gb-grid-4 {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
}

/* ── Page container for non-dashboard pages ── */
.gb-page {
  background: var(--l2);
  flex: 1;
  padding: 16px;
}

.gb-page-inner {
  max-width: 1100px;
  margin: 0 auto;
}

.gb-page-title {
  font-size: 18px;
  color: var(--d1);
  margin-bottom: 4px;
}

.gb-page-subtitle {
  font-size: 11px;
  color: var(--d2);
  margin-bottom: 16px;
}

/* ── Scrollbar for gb-page ── */
.gb-page::-webkit-scrollbar { width: 10px; }
.gb-page::-webkit-scrollbar-track { background: var(--l1); }
.gb-page::-webkit-scrollbar-thumb { background: var(--d2); border: 2px solid var(--d1); }

/* ── Type coverage block ── */
.type-coverage-gap {
  background: var(--d2);
  color: var(--l2);
  padding: 2px 6px;
  display: inline-block;
  font-size: 10px;
}

.type-coverage-gap .type-text {
  border-color: var(--l1);
}

/* ═══════════════════════════════════════════════════════════
   ANIMATIONS
   ═══════════════════════════════════════════════════════════ */

@keyframes screenFlash {
  0% { background: var(--d1); }
  15% { background: var(--l2); }
  100% { background: var(--l2); }
}

/* ═══════════════════════════════════════════════════════════
   ── R4 Map ──
   Step 23 — standalone /map redesign per
   handoff/2026-05-04-ui-audit-mockup-map.html. All selectors are
   namespaced under `.map-r4` so existing timeline / route surfaces
   are not affected. Mockup CSS is transcribed verbatim except for
   the namespace prefix. Mockup-document chrome (`.page`,
   `.page-banner`, `.legend`, `.section-anchor`, `.annotation`,
   `.phone`, `.phone-bezel`) is intentionally dropped — those style
   the mockup HTML itself, not the production component.
   ═══════════════════════════════════════════════════════════ */

.map-r4 { display: block; }

/* ── Map header — Step 27 rebases to gb-page-title + gb-page-subtitle
   form. No boxed background; the title and subtitle alone carry the
   surface. The badge-strip is hoisted into its own gb-section below. ── */
.map-r4 .map-head {
  margin-bottom: var(--s-6);
}
.map-r4 .map-head h2 {
  font-family: 'Press Start 2P', monospace;
  font-size: 18px; color: var(--white);
  margin: 0 0 var(--s-1); letter-spacing: 0.1em;
}
.map-r4 .map-head .sub {
  color: var(--l1);
  font-size: 11px;
  margin-bottom: 0;
}

/* Badge strip — Step 27: keep 28×28 dimensions (badges literally need
   to be visible badges). Drop hover translate, drop earned-state glow.
   Active = bg swap to --accent only. */
.map-r4 .badge-strip-section {
  margin-bottom: var(--s-6);
}
.map-r4 .badge-strip-section .gb-section-header {
  margin-bottom: var(--s-3);
}
.map-r4 .badge-strip {
  display: flex; gap: var(--s-1); align-items: center;
  flex-wrap: wrap;
}
.map-r4 .badge-strip .badge {
  width: 28px; height: 28px;
  border: var(--border-thin);
  display: flex; align-items: center; justify-content: center;
  font-family: 'Press Start 2P', monospace; font-size: 10px;
  cursor: pointer;
  background: var(--l2); color: var(--d1);
  transition: background 0.05s, color 0.05s, border-color 0.05s;
}
.map-r4 .badge-strip .badge.earned {
  background: var(--accent); color: var(--d0); border-color: var(--accent);
}
.map-r4 .badge-strip .badge:hover { background: var(--d2); color: var(--l2); }

/* ── Status bar — Step 27: rebased to a single gb-card-dark-shape row.
   JUMP TO NOW button is gb-btn-primary form, static (no subtleBlink). ── */
.map-r4 .status-bar {
  background: var(--d2);
  border: var(--border);
  padding: var(--s-3) var(--s-6);
  margin-bottom: var(--s-6);
  display: flex; align-items: center; gap: var(--s-6);
  flex-wrap: wrap;
  font-size: 13px;
  color: var(--l2);
}
.map-r4 .status-bar .item .lbl {
  font-family: 'Press Start 2P', monospace;
  font-size: 8px; color: var(--l1);
  letter-spacing: 1px; margin-right: var(--s-2);
}
.map-r4 .status-bar .item .val { color: var(--white); }
.map-r4 .status-bar .jump-btn {
  margin-left: auto;
  background: var(--d1); color: var(--l2);
  border: var(--border-thin);
  padding: var(--s-3) var(--s-6); cursor: pointer;
  font-family: 'Press Start 2P', monospace;
  font-size: 11px; letter-spacing: var(--ls-tight);
  line-height: 1.4;
  transition: all 0.05s;
}
.map-r4 .status-bar .jump-btn:hover { background: var(--d2); color: var(--l2); }
.map-r4 .status-bar .jump-btn.hidden { display: none; }

/* ── Layout grid: timeline + sticky sheet ── */
.map-r4 .layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 380px;
  gap: 22px;
  align-items: flex-start;
}

/* ── Timeline track ── */
.map-r4 .timeline-frame {
  background: var(--d1);
  border: var(--border);
  padding: 0;
  margin-bottom: 14px;
  position: relative;
  overflow: hidden;
}
/* Step 27: dropped left/right gradient-fade overlays — the horizontal
   scroll already implies more content per canon § 11.2. */

.map-r4 .timeline-scroll {
  overflow-x: auto;
  overflow-y: visible;
  padding: 22px 12px 16px;
  scrollbar-width: thin;
  scrollbar-color: var(--d2) var(--d1);
}
.map-r4 .timeline-track {
  display: flex; align-items: flex-start; gap: 0;
  min-width: max-content;
}

.map-r4 .timeline-line {
  height: 3px; flex-shrink: 0;
  margin-top: 32px;
  align-self: flex-start;
}
.map-r4 .timeline-line.done { width: 24px; background: var(--green-glow); }
.map-r4 .timeline-line.todo { width: 24px; background: var(--d2); }

.map-r4 .timeline-segment-divider {
  width: 2px; min-height: 100px;
  background: var(--d2);
  margin: 0 18px;
  position: relative;
  flex-shrink: 0;
}
.map-r4 .timeline-segment-divider::after {
  content: attr(data-segment);
  position: absolute; top: -16px; left: 50%;
  transform: translateX(-50%);
  background: var(--d2); color: var(--l1);
  font-family: 'Press Start 2P', monospace;
  font-size: 7px; padding: 2px 6px;
  letter-spacing: 1px;
  white-space: nowrap;
}

/* ── Node ── */
.map-r4 .node {
  flex-shrink: 0;
  display: flex; flex-direction: column; align-items: center;
  gap: 4px;
  min-width: 84px;
  cursor: pointer;
  background: none; border: none; padding: 0;
  font-family: 'VT323', monospace;
  position: relative;
}
.map-r4 .node .glyph {
  width: 56px; height: 56px;
  border: 2px solid var(--d0);
  display: flex; align-items: center; justify-content: center;
  transition: border-color 0.05s;
  position: relative;
}
/* Step 27: dropped translateY hover lift + box-shadow drop. Border
   colour swap is the entire affordance per canon § 11.2. */
.map-r4 .node:hover .glyph {
  border-color: var(--accent);
}
.map-r4 .node:focus-visible .glyph {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

.map-r4 .node.caught .glyph { background: var(--d2); border-color: var(--green-glow); color: var(--white); }
.map-r4 .node.dead .glyph { background: #4a1c1c; border-color: var(--crimson); color: var(--white); }
.map-r4 .node.uncaught .glyph { background: var(--l2); border-color: var(--d2); color: var(--d2); opacity: 0.85; }
.map-r4 .node.special .glyph { background: var(--d1); border-color: var(--accent); color: var(--accent); }
/* Step 27: NEXT marker keeps the 3 px accent inner border (the single
   canonical "next" cue). Outer 5 px ring + glow + pulseNext animation
   dropped per canon § 11.2. */
.map-r4 .node.next .glyph {
  border-color: var(--accent); border-width: 3px;
}
.map-r4 .node.selected .glyph {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

.map-r4 .node.gym .glyph {
  width: 64px; height: 64px;
  background: var(--accent); color: var(--d0);
  border-color: var(--d0); border-width: 3px;
  font-family: 'Press Start 2P', monospace; font-size: 16px;
}
.map-r4 .node.gym.beaten .glyph { background: var(--d1); color: var(--accent); border-color: var(--accent); }

.map-r4 .node .label {
  font-family: 'Press Start 2P', monospace;
  font-size: 8px;
  color: var(--l2);
  text-align: center;
  line-height: 1.4;
  max-width: 84px;
  word-break: break-word;
  letter-spacing: 0.5px;
  margin-top: 2px;
}
.map-r4 .node.uncaught .label { color: var(--d2); }
.map-r4 .node.dead .label { color: var(--crimson); }

.map-r4 .node .nick {
  font-size: 13px; color: var(--white);
  line-height: 1.2; margin-top: 2px;
  max-width: 84px; word-break: break-word;
  text-align: center;
}
.map-r4 .node.dead .nick { color: var(--crimson); text-decoration: line-through; }

/* Step 27: static "↓ NOW" pin — dropped the box-shadow glow per
   canon § 11.2. Position + colour treatment unchanged. */
.map-r4 .node-now-pin {
  position: absolute; top: -16px; left: 50%;
  transform: translateX(-50%);
  background: var(--accent); color: var(--d0);
  font-family: 'Press Start 2P', monospace;
  font-size: 7px; padding: 2px 6px;
  letter-spacing: 1px;
  white-space: nowrap;
  z-index: 6;
}
.map-r4 .node-now-pin::after {
  content: ''; position: absolute;
  bottom: -5px; left: 50%; transform: translateX(-50%);
  width: 0; height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid var(--accent);
}

/* ── Special encounters bar ── */
.map-r4 .special-bar {
  margin-top: 28px;
  background: var(--d1);
  border: var(--border-thin);
  padding: 14px 16px;
}
.map-r4 .special-bar h3 {
  font-family: 'Press Start 2P', monospace;
  font-size: 10px; color: var(--white);
  margin: 0 0 10px; letter-spacing: 1px;
}
.map-r4 .special-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
}
.map-r4 .special-cell {
  background: var(--d2);
  border: var(--border-thin);
  padding: 10px 12px;
  cursor: pointer;
  transition: border-color 0.05s;
  font-family: 'VT323', monospace;
  text-align: left;
}
/* Step 27: dropped translateY hover lift; one-frame border-colour
   swap is the entire affordance per canon § 11.2. */
.map-r4 .special-cell:hover { border-color: var(--accent); }
.map-r4 .special-cell .head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 4px;
}
.map-r4 .special-cell .name {
  font-family: 'Press Start 2P', monospace;
  font-size: 10px; color: var(--white); letter-spacing: 0.5px;
}
.map-r4 .special-cell .glyph-mini {
  font-family: 'Press Start 2P', monospace;
  font-size: 9px; color: var(--accent);
}
.map-r4 .special-cell .body { color: var(--l1); font-size: 13px; }

/* ── Right rail (sheet) ── */
.map-r4 .sheet {
  background: var(--d1);
  border: var(--border);
  padding: 0;
  position: sticky; top: 16px;
}
/* Step 27: sheet-head restyled to gb-section-header form
   (--d1 bg, --l2 text, 8 × 12 padding, 13 px caps). Close button
   rebased to gb-btn-sm-style (10 px font, 4 × 8 padding, 2 px border). */
.map-r4 .sheet-head {
  background: var(--d1);
  padding: var(--s-3) var(--s-5);
  display: flex; align-items: center; justify-content: space-between;
  border-bottom: var(--border-thin);
}
.map-r4 .sheet-head h3 {
  font-family: 'Press Start 2P', monospace;
  font-size: 13px; color: var(--l2);
  margin: 0; letter-spacing: 0.1em;
}
.map-r4 .sheet-head .close {
  background: var(--l1); color: var(--d1);
  border: var(--border-thin);
  padding: 4px 8px; cursor: pointer;
  font-family: 'Press Start 2P', monospace;
  font-size: 10px; letter-spacing: var(--ls-tight);
  line-height: 1.4;
  transition: all 0.05s;
}
.map-r4 .sheet-head .close:hover {
  background: var(--danger-bg); color: var(--danger-fg);
  border-color: var(--danger-border);
}

.map-r4 .sheet-body { padding: 16px; }
.map-r4 .sheet-body > .hidden { display: none; }

.map-r4 .sheet-status {
  display: flex; align-items: center; gap: 6px;
  font-family: 'Press Start 2P', monospace;
  font-size: 8px; letter-spacing: 1px;
  color: var(--l1);
  margin-bottom: 10px;
}
.map-r4 .sheet-status .pill {
  background: var(--green-glow); color: var(--d0);
  padding: 3px 6px;
}
.map-r4 .sheet-status .pill.dead { background: var(--crimson); color: var(--white); }
.map-r4 .sheet-status .pill.uncaught { background: var(--l2); color: var(--d0); }

.map-r4 .empty-state {
  color: var(--l1); font-size: 14px;
  padding: 18px 4px;
}

.map-r4 .form-row { margin-bottom: 12px; position: relative; }
.map-r4 .form-row label {
  display: block;
  font-family: 'Press Start 2P', monospace;
  font-size: 8px; color: var(--l1);
  letter-spacing: 1px; margin-bottom: 4px;
}
.map-r4 .form-row input,
.map-r4 .form-row select {
  width: 100%;
  background: var(--d0); color: var(--white);
  border: 2px solid var(--d2);
  padding: 6px 10px;
  font-family: 'VT323', monospace;
  font-size: 16px;
}
.map-r4 .player-row {
  display: grid;
  grid-template-columns: 80px 1fr;
  gap: 10px;
  margin-bottom: 8px;
  align-items: center;
}
.map-r4 .player-row .pname {
  font-family: 'Press Start 2P', monospace;
  font-size: 8px; color: var(--l1);
  letter-spacing: 0.5px;
}
.map-r4 .player-row .pinput {
  display: flex; align-items: center; gap: 6px;
  position: relative;
}
.map-r4 .player-row .preview {
  width: 28px; height: 28px;
  background: var(--d0);
  border: 1px solid var(--d2);
  display: flex; align-items: center; justify-content: center;
  color: var(--l2);
  font-family: 'Press Start 2P', monospace; font-size: 7px;
  flex-shrink: 0;
}
.map-r4 .player-row input { flex: 1; padding: 4px 8px; font-size: 14px; }
.map-r4 .player-row .species-dropdown {
  position: absolute; left: 34px; right: 0; top: 100%;
  z-index: 10;
  margin-top: 2px; max-height: 180px; overflow-y: auto;
  background: var(--l2); border: var(--border-thin);
}
.map-r4 .player-row .species-dropdown.hidden { display: none; }
.map-r4 .player-row .species-dropdown > div {
  padding: 4px 8px; color: var(--d1); font-size: 13px; cursor: pointer;
}
.map-r4 .player-row .species-dropdown > div:hover {
  background: var(--accent); color: var(--d0);
}

/* Step 27: submit-btn rebased to gb-btn-primary form. Dropped the
   filter-brightness hover in favour of a 1-frame bg/colour swap. */
.map-r4 .submit-btn {
  width: 100%;
  background: var(--d1); color: var(--l2);
  border: var(--border-thin);
  padding: var(--s-3) var(--s-6);
  font-family: 'Press Start 2P', monospace;
  font-size: 11px; letter-spacing: var(--ls-tight);
  line-height: 1.4;
  cursor: pointer;
  margin-top: var(--s-3);
  transition: all 0.05s;
}
.map-r4 .submit-btn:hover { background: var(--d2); color: var(--l2); }
.map-r4 .submit-btn.danger {
  background: var(--danger-bg); color: var(--danger-fg);
  border: 2px solid var(--danger-border);
}
.map-r4 .submit-btn.danger:hover { background: var(--danger-border); color: #f0c0c0; }
.map-r4 .submit-btn.muted { background: var(--d2); color: var(--l2); }

.map-r4 .form-status {
  display: block; margin-top: 6px;
  font-size: 12px; color: var(--l1);
}

.map-r4 .group-card {
  background: var(--d0);
  border: 2px solid var(--green-glow);
  padding: 12px;
  margin-bottom: 14px;
}
.map-r4 .group-card.dead { border-color: var(--crimson); }
.map-r4 .group-card .head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 8px;
}
.map-r4 .group-card .head .nickname {
  font-family: 'Press Start 2P', monospace;
  font-size: 12px; color: var(--white); letter-spacing: 1px;
}
.map-r4 .group-card .head .pill {
  font-family: 'Press Start 2P', monospace;
  font-size: 8px; color: var(--green-glow);
  border: 1px solid var(--green-glow);
  padding: var(--s-1) var(--s-2); letter-spacing: 1px;
}
.map-r4 .group-card.dead .head .pill {
  color: var(--crimson); border-color: var(--crimson);
}
.map-r4 .group-card .actions {
  display: flex; gap: 6px; margin-top: 12px;
  padding-top: 10px; border-top: 1px dashed var(--d2);
}
.map-r4 .group-card .actions .submit-btn { margin-top: 0; }

.map-r4 .dupes-btn {
  width: 100%;
  background: transparent; color: var(--l1);
  border: 1px dashed var(--d2);
  padding: 10px;
  font-family: 'Press Start 2P', monospace;
  font-size: 9px; cursor: pointer; letter-spacing: 1px;
  margin-top: 8px;
}
.map-r4 .dupes-btn:hover { border-color: var(--accent); color: var(--accent); }

/* ── Mobile accordion ── */
.map-r4 .accordion-frame { display: none; }

.map-r4 .accordion-segment {
  background: var(--d1);
  border: var(--border-thin);
  margin-bottom: 8px;
}
.map-r4 .accordion-segment summary {
  background: var(--d2);
  padding: 10px 14px;
  cursor: pointer;
  list-style: none;
  display: flex; align-items: center; justify-content: space-between;
  font-family: 'Press Start 2P', monospace;
  font-size: 9px; color: var(--white);
  letter-spacing: 1px;
}
.map-r4 .accordion-segment summary::-webkit-details-marker { display: none; }
.map-r4 .accordion-segment summary::after { content: "\25BE"; color: var(--l1); }
.map-r4 .accordion-segment[open] summary::after { content: "\25B4"; }
.map-r4 .accordion-segment[open] summary { background: var(--accent); color: var(--d0); }
.map-r4 .accordion-segment .seg-progress {
  font-size: 7px; color: var(--l1);
  margin-left: auto; padding-right: 8px;
}
.map-r4 .accordion-segment[open] .seg-progress { color: var(--d0); }

.map-r4 .acc-rows { padding: 6px 8px; }
.map-r4 .acc-row {
  display: grid;
  grid-template-columns: 36px 1fr auto;
  gap: 8px;
  align-items: center;
  padding: 8px;
  border-bottom: 1px dashed var(--d2);
  cursor: pointer;
  background: none; border-left: none; border-right: none; border-top: none;
  width: 100%;
  font-family: 'VT323', monospace;
  text-align: left;
}
.map-r4 .acc-row:last-child { border-bottom: none; }
.map-r4 .acc-row:hover { background: var(--d2); }
.map-r4 .acc-row .glyph {
  width: 36px; height: 36px;
  border: 2px solid var(--d0);
  display: flex; align-items: center; justify-content: center;
  font-family: 'Press Start 2P', monospace; font-size: 10px;
}
.map-r4 .acc-row .glyph.caught { background: var(--d2); border-color: var(--green-glow); color: var(--white); }
.map-r4 .acc-row .glyph.dead { background: #4a1c1c; border-color: var(--crimson); color: var(--white); }
.map-r4 .acc-row .glyph.uncaught { background: var(--l2); border-color: var(--d2); color: var(--d2); }
.map-r4 .acc-row .glyph.special { background: var(--d1); border-color: var(--accent); color: var(--accent); }
/* Step 27: dropped pulseNext animation. Border-color swap is the
   static "next" affordance per canon § 11.2. */
.map-r4 .acc-row .glyph.next { border-color: var(--accent); }
.map-r4 .acc-row .meta .loc {
  font-family: 'Press Start 2P', monospace;
  font-size: 9px; color: var(--white);
  letter-spacing: 0.5px; margin-bottom: 2px;
}
.map-r4 .acc-row .meta .nick { font-size: 12px; color: var(--l1); }
.map-r4 .acc-row .meta .nick.dead { color: var(--crimson); text-decoration: line-through; }
.map-r4 .acc-row .chev { color: var(--d2); font-family: 'Press Start 2P', monospace; font-size: 10px; }

/* ═══════════════════════════════════════════════════════════
   ── R2 PC Box ──
   Step 22 — dashboard PC BOX tab redesign per
   handoff/2026-05-04-ui-audit-mockup-pc-box.html. All selectors are
   namespaced under `.pc-box-r2` so the existing `.box-grid` / `.box-cell`
   rules used by `_pc_box_panel.html.erb` (sidebar) and other surfaces are
   not affected. Mockup CSS is transcribed verbatim except for the
   namespace prefix and a few project conventions called out inline.
   ═══════════════════════════════════════════════════════════ */

.pc-box-r2 { display: block; }

/* Review tray for auto-detected catches.
   Step 27: rebased to gb-card-dark form (3 px ink border, 12 px padding).
   The tray is a card, not a special accented zone. */
.pc-box-r2 .review-tray {
  background: var(--d2); color: var(--l2);
  border: var(--border);
  padding: var(--s-5);
  margin-bottom: var(--s-8);
}
.pc-box-r2 .review-tray-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: var(--s-4);
  flex-wrap: wrap; gap: var(--s-3);
}
.pc-box-r2 .review-tray-head h3 {
  font-family: 'Press Start 2P', monospace;
  font-size: 11px; color: var(--white);
  margin: 0; letter-spacing: 1px;
}
/* Step 27: count chip becomes plain text, no accent bg. */
.pc-box-r2 .review-tray-head .count {
  font-family: 'Press Start 2P', monospace;
  font-size: 8px; color: var(--l1);
  letter-spacing: 1px;
}

/* Step 27: badge-legend collapsed into a single inline strip — plain
   --l1 text, no boxed border, no per-badge color coding. The kind
   (1ST / TRADE-IN / EVENT / OFF-FEED) reads from the label text. */
.pc-box-r2 .badge-legend {
  padding: 0;
  margin-bottom: var(--s-5);
  font-size: 13px;
  color: var(--l1);
  line-height: 1.6;
}
.pc-box-r2 .badge-legend .row { display: inline; margin-right: var(--s-5); }

/* Step 27: all 4 inline badges (1ST / TRADE / EVENT / OFFFEED) get the
   same pill--ghost-style treatment: 1 px --l1 border, transparent bg,
   --l1 text. Information lives in the LABEL, not the colour. */
.pc-box-r2 .badge {
  display: inline-block;
  font-family: 'Press Start 2P', monospace;
  font-size: 8px;
  padding: var(--s-1) var(--s-2);
  letter-spacing: 1px;
  border: 1px solid var(--l1);
  background: transparent;
  color: var(--l1);
}

/* A single review row.
   Step 27: padding/margin snapped to canon (10 → s-3, 14 → s-6). */
.pc-box-r2 .review-row {
  display: grid;
  grid-template-columns: 56px 1fr auto;
  gap: var(--s-6); align-items: center;
  background: var(--d1);
  border: var(--border-thin);
  padding: var(--s-3) var(--s-6);
  margin-bottom: var(--s-3);
}
.pc-box-r2 .review-row.first { border-color: var(--green-glow); border-width: 3px; padding: var(--s-3) var(--s-5); }
.pc-box-r2 .review-row.dismissed { opacity: 0.4; }

.pc-box-r2 .review-row .sprite {
  width: 56px; height: 56px;
  background: var(--d0);
  border: 1px solid var(--d2);
  display: flex; align-items: center; justify-content: center;
  color: var(--l2);
  font-family: 'Press Start 2P', monospace;
  font-size: 9px;
}
.pc-box-r2 .review-row .meta .name {
  font-family: 'Press Start 2P', monospace;
  font-size: 12px;
  color: var(--white);
  letter-spacing: 1px;
  margin-bottom: 4px;
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
}
.pc-box-r2 .review-row .meta .loc   { color: var(--l1); font-size: 14px; }
.pc-box-r2 .review-row .meta .stats { color: var(--d2); font-size: 13px; margin-top: 2px; }
.pc-box-r2 .review-row .meta .stats span { color: var(--l1); }

.pc-box-r2 .review-row .actions {
  display: flex; flex-direction: column; gap: var(--s-2);
}
/* Step 27: rebased to gb-btn-sm form (10 px font, 4 × 8 padding, 2 px
   border-thin). Single accent — primary uses --d1 bg / --l2 text
   (gb-btn-primary), other actions stay neutral gb-btn light-bg. */
.pc-box-r2 .review-row .actions button {
  background: var(--l1); color: var(--d1);
  border: var(--border-thin);
  padding: 4px 8px;
  cursor: pointer;
  font-family: 'Press Start 2P', monospace;
  font-size: 10px; letter-spacing: var(--ls-tight);
  line-height: 1.4;
  min-width: 92px;
  transition: all 0.05s;
}
.pc-box-r2 .review-row .actions button:hover { background: var(--d2); color: var(--l2); }
.pc-box-r2 .review-row .actions button.primary { background: var(--d1); color: var(--l2); }
.pc-box-r2 .review-row .actions button.primary:hover { background: var(--d2); color: var(--l2); }

/* Empty review-tray bar (Screen 3).
   Step 27: rebased to gb-flash-notice form (--d2 bg, --l2 text). The
   .check glyph becomes inline (✓) in the message text. */
.pc-box-r2 .empty-tray-bar {
  background: var(--d2); color: var(--l2);
  border: var(--border-thin);
  padding: var(--s-3) var(--s-6);
  margin-bottom: var(--s-7);
  font-size: 13px;
}

/* Filter chip bar.
   Step 27: chips rebased to gb-btn-sm form. Active = bg swap to --d1 +
   --l2 text (matches .tab-item.active). No accent green bg. The
   dim-on-non-active opacity behavior is dropped — bg swap is enough. */
.pc-box-r2 .filter-bar {
  display: flex; align-items: center; gap: var(--s-3);
  margin-bottom: var(--s-6);
  flex-wrap: wrap;
}
.pc-box-r2 .filter-chip {
  background: var(--l1); color: var(--d1);
  border: var(--border-thin);
  padding: 4px 8px;
  cursor: pointer;
  font-family: 'Press Start 2P', monospace;
  font-size: 10px; letter-spacing: var(--ls-tight);
  line-height: 1.4;
  transition: all 0.05s;
}
.pc-box-r2 .filter-chip:hover:not(.active) { background: var(--d2); color: var(--l2); }
.pc-box-r2 .filter-chip.active {
  background: var(--d1); color: var(--l2);
  border-color: var(--d1);
}
.pc-box-r2 .filter-search {
  margin-left: auto;
  flex: 1; min-width: 200px;
}
.pc-box-r2 .filter-search input {
  width: 100%;
  background: var(--d0); color: var(--white);
  border: 2px solid var(--d2);
  padding: 6px 10px;
  font-family: 'VT323', monospace;
  font-size: 16px;
}
.pc-box-r2 .filter-search input::placeholder { color: var(--d2); }

/* Pokemon grid layout (namespace shadows the legacy .box-grid / .box-cell
   used by _pc_box_panel.html.erb — those rules are unchanged). */
.pc-box-r2 .box-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 280px;
  gap: 22px;
  align-items: flex-start;
}
.pc-box-r2 .box-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
}
.pc-box-r2 .box-cell {
  background: var(--d2);
  border: 2px solid var(--d0);
  padding: 8px;
  text-align: center;
  cursor: pointer;
  position: relative;
  transition: border-color 0.05s;
}
/* Step 27: dropped translateY hover lift; one-frame border colour swap
   is the entire affordance per canon § 11.2. */
.pc-box-r2 .box-cell:hover { border-color: var(--accent); }
.pc-box-r2 .box-cell.team { background: var(--d1); border-color: var(--green-glow); }
.pc-box-r2 .box-cell.dead { background: #2a1a1a; border-color: #4a1c1c; opacity: 0.7; }
.pc-box-r2 .box-cell .nick {
  font-family: 'Press Start 2P', monospace;
  font-size: 9px;
  color: var(--white);
  letter-spacing: 0.5px;
  margin-bottom: 6px;
  word-break: break-word;
}
.pc-box-r2 .box-cell .sprite {
  width: 40px; height: 40px;
  margin: 0 auto;
  background: var(--d0);
  border: 1px solid var(--d2);
  display: flex; align-items: center; justify-content: center;
  color: var(--l2);
  font-family: 'Press Start 2P', monospace;
  font-size: 8px;
}
.pc-box-r2 .box-cell .loc {
  color: var(--l1); font-size: 12px; margin-top: 6px;
  word-break: break-word; line-height: 1.3;
}
.pc-box-r2 .box-cell .group-marker {
  position: absolute; top: 4px; left: 4px;
  font-size: 9px; color: var(--accent);
  font-family: 'Press Start 2P', monospace;
}
.pc-box-r2 .box-cell.dead .group-marker { color: var(--crimson); }
.pc-box-r2 .box-cell.team .group-marker { color: var(--green-glow); }

.pc-box-r2 .box-cell.search-hidden,
.pc-box-r2 .box-cell.filter-hidden { display: none; }

/* Type-coverage rail */
.pc-box-r2 .type-coverage {
  background: var(--d2);
  border: var(--border-thin);
  padding: 14px;
}
.pc-box-r2 .type-coverage h3 {
  font-family: 'Press Start 2P', monospace;
  font-size: 10px; color: var(--white);
  margin: 0 0 10px; letter-spacing: 1px;
}
.pc-box-r2 .type-coverage .sub {
  font-family: 'Press Start 2P', monospace;
  font-size: 7px; color: var(--l1);
  letter-spacing: 1px; margin: 10px 0 6px;
}
.pc-box-r2 .type-coverage.dimmed { opacity: 0.6; }
.pc-box-r2 .type-coverage .dimmed-explainer {
  display: none;
  font-size: 11px; color: var(--d2); line-height: 1.4;
  margin-bottom: 8px;
}
.pc-box-r2 .type-coverage.dimmed .dimmed-explainer { display: block; }

.pc-box-r2 .type-pill {
  display: inline-block;
  font-family: 'Press Start 2P', monospace;
  font-size: 8px;
  padding: 3px 6px;
  margin: 2px;
  letter-spacing: 1px;
  border: 1px solid;
}
.pc-box-r2 .type-pill.covered { background: var(--green-glow); color: var(--d0); border-color: var(--green-glow); }
.pc-box-r2 .type-pill.gap     { color: var(--crimson); border-color: var(--crimson); border-style: dashed; }
.pc-box-r2 .type-pill.weak    { background: var(--crimson); color: var(--white); border-color: var(--crimson); }

/* ═══════════════════════════════════════════════════════════
   ── R3 Save Slots ──
   Step 21 — emulator left sidebar redesign + roster-card restyle.
   Mockup: handoff/2026-05-04-ui-audit-mockup-save-slots.html.
   Mockup CSS copied verbatim except `.slot.overwriteTarget` is renamed
   `.slot.overwrite-target` (kebab-case, project convention).
   ═══════════════════════════════════════════════════════════ */

/* Banner that announces overwrite-pending mode. Step 27: rebased to
   gb-flash-alert-style notice (danger-family palette). The icon-glyph
   was dropped from the markup; the message text carries the full cue. */
.pending-banner {
  background: var(--danger-bg); color: var(--danger-fg);
  border: var(--border-thin); border-color: var(--danger-border);
  padding: var(--s-3) var(--s-4); margin-bottom: var(--s-4);
  font-family: 'Press Start 2P', monospace;
  font-size: 9px; line-height: 1.5;
  display: flex; align-items: center; gap: var(--s-3);
}
.pending-banner button {
  margin-left: auto;
  background: var(--l1); color: var(--d1);
  border: var(--border-thin);
  padding: 4px 8px; cursor: pointer;
  font-family: 'Press Start 2P', monospace;
  font-size: 8px; letter-spacing: 1px;
}
.pending-banner button:hover { background: var(--d2); color: var(--l2); }

/* A single slot card. Step 27: rebased to gb-card-dark form (3 px ink
   border, 12 px padding). The .slot.active 4 px green-glow border is
   the canonical "active save target" affordance — kept (canon § 11.3). */
.slot {
  background: var(--d2); color: var(--l2);
  border: var(--border);
  padding: var(--s-5);
  margin-bottom: var(--s-4);
  position: relative;
}
.slot.active { border: 4px solid var(--green-glow); padding: 11px; }
.slot.overwrite-target { border-color: var(--accent); cursor: pointer; }
.slot.empty .slot-meta { color: var(--d2); }

.slot-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 6px;
}
.slot-num {
  font-family: 'Press Start 2P', monospace;
  font-size: 10px; color: var(--l2);
  letter-spacing: 1px;
}

/* State pills — used on slot cards AND on roster cards. */
.state-pill {
  font-family: 'Press Start 2P', monospace;
  font-size: 7px;
  padding: var(--s-1) var(--s-2);
  letter-spacing: 1px;
  border: 1px solid;
}
.state-pill.empty { color: var(--d2); border-color: var(--d2); }
.state-pill.saved { color: var(--l2); border-color: var(--l2); background: var(--d2); }
.state-pill.active { color: var(--d0); border-color: var(--green-glow); background: var(--green-glow); }
.state-pill.target { color: var(--d0); border-color: var(--accent); background: var(--accent); }
.state-pill.confirm { color: var(--white); border-color: var(--crimson); background: var(--crimson); }

.slot-meta { color: var(--l1); font-size: 14px; line-height: 1.5; }
.slot-meta .row { display: flex; gap: 8px; flex-wrap: wrap; }
.slot-meta .row .lbl { color: var(--d2); font-size: 11px; font-family: 'Press Start 2P', monospace; letter-spacing: 0.5px; }
.slot-meta .row .val { color: var(--white); }
.slot-meta strong { color: var(--white); font-size: 16px; }

.slot-actions {
  display: flex; gap: var(--s-2);
  margin-top: var(--s-4);
  padding-top: var(--s-3);
  border-top: 1px dashed var(--d2);
}
/* Step 27: rebased to gb-btn-sm form (10 px font, 4 × 8 padding, 2 px
   border-thin). Per canon § 4 directive: at most ONE accent-bg button
   per cluster; primary/danger/confirm now use `gb-btn` light-bg with
   meaningful colour ON THE TEXT, not a full-bg flood. */
.slot-actions button,
.slot-actions a {
  flex: 1;
  background: var(--l1); color: var(--d1);
  border: var(--border-thin);
  padding: 4px 8px; cursor: pointer;
  font-family: 'Press Start 2P', monospace;
  font-size: 10px; letter-spacing: var(--ls-tight);
  line-height: 1.4;
  text-decoration: none; text-align: center;
  display: inline-block;
  transition: all 0.05s;
}
.slot-actions button:hover,
.slot-actions a:hover { background: var(--d2); color: var(--l2); }
/* Single accent-bg primary action (MAKE ACTIVE — promotes a slot). */
.slot-actions button.primary { background: var(--d1); color: var(--l2); }
.slot-actions button.primary:hover { background: var(--d2); color: var(--l2); }
/* DELETE = colour on text only, neutral bg per canon directive. */
.slot-actions button.danger { color: var(--danger); }
.slot-actions button.danger:hover {
  background: var(--danger-bg); color: var(--danger-fg);
  border-color: var(--danger-border);
}
/* DELETE FOREVER (the actual destructive confirm) keeps gb-btn-danger fill. */
.slot-actions button.confirm {
  background: var(--danger-bg); color: var(--danger-fg);
  border: 2px solid var(--danger-border);
}

/* Inline confirmation row (DELETE / CLEAR ALL SLOTS). Rendered hidden
   by default; revealed by save_slots_controller.js. Step 27: rebased
   to a quieter dark-card form — the buttons inside carry the danger
   colour, not the container. The .q heading is restyled to match
   gb-section-header. */
.confirm-inline {
  background: var(--d2); color: var(--l2);
  border: var(--border-thin);
  padding: var(--s-4);
  margin-top: var(--s-4);
}
.confirm-inline .q {
  background: var(--d1); color: var(--l2);
  padding: var(--s-3) var(--s-5);
  margin: calc(var(--s-4) * -1) calc(var(--s-4) * -1) var(--s-3);
  font-family: 'Press Start 2P', monospace;
  font-size: 13px;
  letter-spacing: 0.1em;
}
.confirm-inline .body {
  font-size: 14px; color: var(--l1);
  margin-bottom: var(--s-3);
}
.confirm-inline .actions { display: flex; gap: var(--s-2); }
.confirm-inline .actions button {
  flex: 1;
  background: var(--l1); color: var(--d1);
  border: var(--border-thin);
  padding: 4px 8px; cursor: pointer;
  font-family: 'Press Start 2P', monospace;
  font-size: 10px; letter-spacing: var(--ls-tight);
  line-height: 1.4;
  transition: all 0.05s;
}
.confirm-inline .actions button:hover { background: var(--d2); color: var(--l2); }
.confirm-inline .actions button.confirm {
  background: var(--danger-bg); color: var(--danger-fg);
  border: 2px solid var(--danger-border);
}

.footer-actions {
  margin-top: var(--s-6);
  padding-top: var(--s-5);
  border-top: 1px dashed var(--d2);
}
.footer-actions button {
  width: 100%;
  background: transparent; color: var(--danger);
  border: 1px dashed var(--danger);
  padding: var(--s-3) var(--s-4); cursor: pointer;
  font-family: 'Press Start 2P', monospace;
  font-size: 9px; letter-spacing: 1px;
}
.footer-actions button:hover {
  background: var(--danger-bg); color: var(--danger-fg);
  border: 2px solid var(--danger-border);
}

/* Roster card redesign. */
.roster-card {
  background: var(--d1);
  border: var(--border-thin);
  padding: 12px 14px;
  margin-bottom: 10px;
}
.roster-card.you { border: 4px solid var(--accent); padding: 10px 12px; }
.roster-card .head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 8px;
}
.roster-card .name {
  font-family: 'Press Start 2P', monospace;
  font-size: 12px; color: var(--white);
  letter-spacing: 1px;
}
.roster-card .name .you-badge {
  background: var(--accent); color: var(--d0);
  font-size: 7px; padding: 2px 4px; margin-left: 6px;
  letter-spacing: 1px;
}
.roster-card .stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
  margin-bottom: 8px;
}
.roster-card .stat {
  background: var(--d0);
  border: 1px solid var(--d2);
  padding: 6px;
  text-align: center;
}
.roster-card .stat .lbl {
  font-family: 'Press Start 2P', monospace;
  font-size: 7px; color: var(--l1);
  letter-spacing: 1px; margin-bottom: 2px;
}
.roster-card .stat .val {
  color: var(--white); font-size: 16px;
}
.roster-card details {
  margin-top: 6px;
  border-top: 1px dashed var(--d2); padding-top: 6px;
}
.roster-card summary {
  font-family: 'Press Start 2P', monospace;
  font-size: 8px; color: var(--l2);
  letter-spacing: 1px; cursor: pointer;
  list-style: none; user-select: none;
}
.roster-card summary::after { content: "  ▾"; color: var(--d2); }
.roster-card details[open] summary::after { content: "  ▴"; }
.roster-card .extra { color: var(--l1); font-size: 14px; margin-top: 6px; }
.roster-card .extra .row { display: flex; justify-content: space-between; }
.roster-card .extra .row .lbl { font-family: 'Press Start 2P', monospace; font-size: 8px; color: var(--d2); letter-spacing: 0.5px; }
.roster-card .seed {
  font-family: monospace;
  font-size: 11px; color: var(--d2);
  background: var(--d0);
  border: 1px solid var(--d2);
  padding: 4px 6px;
  margin-top: 6px;
  word-break: break-all;
  cursor: copy;
  position: relative;
}
.roster-card .seed:hover { color: var(--l1); }
.roster-card .seed::after {
  content: "click to copy"; position: absolute;
  right: 6px; top: 50%; transform: translateY(-50%);
  background: var(--d0); color: var(--accent);
  font-family: 'Press Start 2P', monospace; font-size: 7px;
  padding: 2px 4px;
  opacity: 0; transition: opacity 0.15s;
}
.roster-card .seed:hover::after { opacity: 1; }

.conflict-warning {
  background: #4a3a1c; color: var(--amber);
  border: 1px solid var(--amber);
  padding: 6px 8px;
  margin-top: 6px;
  font-family: 'Press Start 2P', monospace;
  font-size: 8px; line-height: 1.5;
  letter-spacing: 0.5px;
}

.hof-pill {
  display: inline-block;
  background: var(--accent); color: var(--d0);
  font-family: 'Press Start 2P', monospace; font-size: 7px;
  padding: var(--s-1) var(--s-2); letter-spacing: 1px;
  margin-left: 4px;
}

/* ═══════════════════════════════════════════════════════════
   ── R1 Dashboard ──
   Step 24 — slim title bar + ARIA tablist + 3-col layout w/
   consolidated right status rail. Every selector namespaced
   under `.dash-r1` so Step 19/20/21/22/23 styles are untouched.
   Step 28 — visual rebuild against the PixelDex source spec
   (designs/04-pixeldex.html): title-bar gets the --d2 band,
   tab-bar cells stack icon-above-label, the 3-col grid drops the
   gap and shares ink borders, and the right rail flattens to a
   plain panel with a horizontal mini tab-bar at the top.
   No new design tokens — the existing :root palette covers it.
   ═══════════════════════════════════════════════════════════ */

/* ── Title bar — Step 28: PixelDex --d2 band, full-width single line,
   ink border-bottom, .title-left flex-aligned against .title-right. ── */
.dash-r1 .title-bar {
  background: var(--d2);
  color: var(--l2);
  border-bottom: var(--border);
  padding: 10px 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
}
.dash-r1 .title-left {
  display: flex; align-items: center; gap: var(--s-5);
  flex-wrap: wrap;
}
.dash-r1 .title-right {
  display: flex; align-items: center; gap: 16px;
}
.dash-r1 .title-block .player {
  font-family: 'Press Start 2P', monospace;
  font-size: 18px; color: var(--l2);
  letter-spacing: 0.08em;
}
.dash-r1 .title-block .meta {
  color: var(--l1); font-size: 11px; margin-top: 0;
  letter-spacing: 0.05em;
}

/* ── Run pill — Step 28: rebased to a label-on-d2-band form so it
   reads as part of the title bar, not as a stamped-on button. The
   button is transparent over the --d2 band, --l2 text, with a thin
   --l1 underline as the affordance. Dropdown menu untouched. ── */
.dash-r1 .run-pill-wrap {
  position: relative;
}
.dash-r1 .run-pill {
  background: transparent;
  color: var(--l2);
  border: none;
  border-bottom: 2px solid var(--l1);
  padding: 4px 6px;
  display: inline-flex; align-items: center; gap: var(--s-2);
  font-family: 'Press Start 2P', monospace;
  font-size: 11px; letter-spacing: var(--ls-tight);
  line-height: 1.4;
  cursor: pointer;
  transition: background 0.05s, color 0.05s;
}
.dash-r1 .run-pill:hover {
  background: rgba(155, 188, 15, 0.15);
  color: var(--l2);
}
.dash-r1 .run-pill .chev { margin-left: var(--s-1); color: var(--l1); }
.dash-r1 .run-pill[aria-expanded="true"] .chev { transform: rotate(180deg); display: inline-block; }

.dash-r1 .run-pill-menu {
  position: absolute; top: calc(100% + 4px); left: 0;
  z-index: 30;
  background: var(--d1);
  border: var(--border);
  padding: 8px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
  min-width: 280px;
}
.dash-r1 .run-pill-menu.hidden { display: none; }
.dash-r1 .run-pill-menu .run-option {
  display: flex; align-items: center; justify-content: space-between;
  padding: 6px 10px;
  text-decoration: none;
  cursor: pointer;
  color: inherit;
}
.dash-r1 .run-pill-menu .run-option .label {
  font-family: 'Press Start 2P', monospace;
  font-size: 9px; color: var(--l1);
  letter-spacing: 0.5px;
}
.dash-r1 .run-pill-menu .run-option .dates {
  color: var(--d2); font-size: 12px;
}
.dash-r1 .run-pill-menu .run-option.active {
  background: var(--d0);
  border: 2px solid var(--green-glow);
  margin-bottom: 4px;
}
.dash-r1 .run-pill-menu .run-option.active .label { color: var(--white); font-size: 10px; }
.dash-r1 .run-pill-menu .run-option.active .dates { color: var(--l1); }
.dash-r1 .run-pill-menu .run-option:hover,
.dash-r1 .run-pill-menu .run-option:focus {
  outline: none;
  background: var(--d2);
}
/* Step 27: run-option status indicator becomes inline plain text in
   the .label span ([ACTIVE] / [HOF] / [PAST]) — no coloured bg pill. */
.dash-r1 .run-pill-menu .run-option .pill {
  font-family: 'Press Start 2P', monospace;
  font-size: 7px; padding: 0; margin-left: var(--s-2);
  letter-spacing: 1px;
  background: transparent; color: var(--l1);
  border: none;
}
.dash-r1 .run-pill-menu .start-row {
  margin-top: 6px; padding-top: 6px;
  border-top: 1px dashed var(--d2);
}
.dash-r1 .run-pill-menu .start-row .start-btn {
  width: 100%;
  background: var(--d2); color: var(--l2);
  border: 1px dashed var(--l1);
  padding: 6px;
  cursor: pointer;
  font-family: 'Press Start 2P', monospace;
  font-size: 8px; letter-spacing: 1px;
}
.dash-r1 .run-pill-menu .start-row .start-btn:hover { background: var(--d0); color: var(--white); }

/* ── Stat strip — Step 28: PixelDex `.title-stat` block grid form.
   Each `.item` renders num-on-top label-below via column-reverse on
   a vertical flex (the LABEL <span> is first in DOM, the .val <span>
   second; column-reverse paints them in visual order top-to-bottom
   without changing DOM). The `·` separator <span>s are kept in DOM
   for accessibility but hidden — the gap does the spacing. ── */
.dash-r1 .stat-strip {
  display: flex;
  gap: 16px;
  font-family: 'Press Start 2P', monospace;
}
.dash-r1 .stat-strip .item {
  display: flex; flex-direction: column-reverse; align-items: center;
  gap: 0; text-align: center;
}
.dash-r1 .stat-strip .item .val {
  font-size: 21px; color: var(--l2);
}
.dash-r1 .stat-strip .item span:first-child {
  font-size: 11px; color: var(--l1); letter-spacing: 0.05em;
}
.dash-r1 .stat-strip .sep { display: none; }

/* ── Tab bar — Step 28: rebuilt to the PixelDex 2-line stacked form.
   Each `.tab-item` is a 2-line cell with `.tab-icon` (20 px glyph)
   stacked block-above the label (13 px caps). Active state and hover
   share the same bg+color swap (--d1 / --l2). The `.badge-dot` chrome
   is still replaced by the inline `*` text suffix (Step 27). ── */
.dash-r1 .tab-bar {
  display: flex;
  background: var(--d1);
  border-bottom: var(--border);
  flex-shrink: 0;
}
.dash-r1 .tab-item {
  flex: 1; min-width: 90px;
  background: var(--d2);
  border: none;
  border-right: 2px solid var(--d2);
  padding: 10px 8px;
  cursor: pointer;
  color: var(--l1);
  font-family: 'Press Start 2P', monospace;
  font-size: 13px;
  letter-spacing: 0.05em;
  text-align: center;
  transition: background 0.05s, color 0.05s;
}
.dash-r1 .tab-item:last-child { border-right: none; }
.dash-r1 .tab-item .tab-icon {
  display: block;
  font-size: 20px;
  margin-bottom: 4px;
  line-height: 1;
}
.dash-r1 .tab-item:hover { background: var(--d1); color: var(--l2); }
.dash-r1 .tab-item[aria-selected="true"] {
  background: var(--d1); color: var(--l2);
}

/* ── Three-col layout — Step 28: PixelDex shared-frame form. Drop the
   gap; let the title-bar + tab-bar sit flush above the grid; paint
   the layout bg with --l2 (the panels are transparent and inherit it
   via their light-card content). Each grid child carries a right-side
   ink border so the columns share a single 3px frame, and the last
   column drops it. Note: body-level scanline overlay (`body::after`)
   already covers the full viewport, so no `.pc-layout::after` here. ── */
.dash-r1 .pc-layout {
  display: grid;
  grid-template-columns: 280px minmax(0, 1fr) 320px;
  gap: 0;
  margin-top: 0;
  align-items: flex-start;
  background: var(--l2);
  animation: none;
  flex: initial;
  min-height: 0;
}
.dash-r1 .pc-layout > .panel,
.dash-r1 .pc-layout > .status-rail {
  border-right: var(--border);
}
.dash-r1 .pc-layout > *:last-child { border-right: none; }

/* ── Status rail — Step 28: drop the boxed outer container; the rail
   participates in the shared 3-col frame as a plain panel. The
   sub-tab strip rebuilds from a vertical caps-bar stack to a
   horizontal mini `.tab-bar` (PixelDex tab-item form), with the
   active panel below carrying its own `.panel-header`. ── */
.dash-r1 .status-rail {
  background: transparent;
  border: none;
  padding: 0;
}
.dash-r1 .side-tabs {
  display: flex; flex-direction: row;
  background: var(--d1);
  border-bottom: var(--border);
  margin-bottom: 0;
  gap: 0;
}
.dash-r1 .side-tab {
  flex: 1;
  background: var(--d2);
  color: var(--l1);
  border: none;
  border-right: 2px solid var(--d2);
  padding: 10px 8px;
  cursor: pointer;
  font-family: 'Press Start 2P', monospace;
  font-size: 13px; letter-spacing: 0.05em;
  text-align: center;
  transition: background 0.05s, color 0.05s;
}
.dash-r1 .side-tab:last-child { border-right: none; }
.dash-r1 .side-tab[aria-selected="true"],
.dash-r1 .side-tab:hover {
  background: var(--d1); color: var(--l2);
}

.dash-r1 .status-panel.hidden { display: none; }

/* PARTY sub-tab — Step 28: rebased to PixelDex light-card form
   (--l1 bg, 2 px ink border, --d1 text). The .you accent border is
   kept as the "this is you" affordance per canon § 11.3 on the
   lighter base. HOF stays as a 🏆 prefix in the name span; BADGES is
   plain inline text. The sprite-cell becomes --l2 bg with a 2 px
   ink border so the team mini-roster reads as a row of light tiles. */
.dash-r1 .player-card {
  background: var(--l1); color: var(--d1);
  border: var(--border-thin);
  margin-bottom: 8px; padding: 10px;
}
.dash-r1 .player-card:last-child { margin-bottom: 0; }
.dash-r1 .player-card.you {
  border-color: var(--accent); border-width: 2px;
}
.dash-r1 .player-card .head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: var(--s-2);
  gap: var(--s-3);
}
.dash-r1 .player-card .name {
  font-family: 'Press Start 2P', monospace;
  font-size: 9px; color: var(--d1);
  letter-spacing: 0.5px;
}
.dash-r1 .player-card .badges-text {
  font-family: 'Press Start 2P', monospace;
  font-size: 8px; color: var(--d2);
  letter-spacing: 1px;
}
.dash-r1 .player-card .sprites {
  display: flex; gap: var(--s-1);
}
.dash-r1 .player-card .sprite-cell {
  width: 28px; height: 28px;
  background: var(--l2); border: 2px solid var(--d1);
  display: flex; align-items: center; justify-content: center;
  color: var(--d1);
  font-family: 'Press Start 2P', monospace; font-size: 7px;
}
.dash-r1 .player-card .sprite-cell.empty {
  background: var(--l2); border: 2px dashed var(--d2);
}

/* GYMS sub-tab — Step 28: gym list rebased to PixelDex `.gym-list-item`
   form (single-line row, 11 px font, solid --d2 divider, glyph-prefix
   .num cell). The next-gym row becomes a `.gym-next-highlight` filled
   bar (--d2 bg + --l2 text), bleeding into the panel-body's negative
   space via a -6px horizontal margin. Upcoming rows fade via opacity. */
.dash-r1 .gym-list {
  font-family: 'Press Start 2P', monospace;
  color: var(--d1);
}
.dash-r1 .gym-list .gym-row {
  display: flex; align-items: center; gap: 6px;
  font-size: 11px;
  padding: 4px 0;
  border-bottom: 1px solid var(--d2);
  line-height: 1.6;
}
.dash-r1 .gym-list .gym-row:last-child { border-bottom: none; }
.dash-r1 .gym-list .gym-row .num {
  width: 14px; text-align: center;
  font-size: 13px;
  background: transparent; border: none;
  color: var(--d1);
  display: inline; padding: 0;
}
.dash-r1 .gym-list .gym-row .name {
  font-family: 'Press Start 2P', monospace;
  font-size: 11px; color: var(--d1);
  letter-spacing: 0.5px;
}
.dash-r1 .gym-list .gym-row.beaten .name { color: var(--accent); }
.dash-r1 .gym-list .gym-row.upcoming { opacity: 0.35; }
.dash-r1 .gym-list .gym-row .lvl {
  font-family: 'Press Start 2P', monospace;
  color: var(--d2); font-size: 10px; margin-left: auto;
}

/* Next-gym row — `.gym-next-highlight` filled-bar form. */
.dash-r1 .gym-list .gym-row.next {
  background: var(--d2); color: var(--l2);
  padding: 6px 8px; margin: 4px -6px;
  font-size: 11px; border: none;
}
.dash-r1 .gym-list .gym-row.next .num { color: var(--l2); }
.dash-r1 .gym-list .gym-row.next .name { color: var(--l2); }
.dash-r1 .gym-list .gym-row.next .lvl { color: var(--l1); }

/* Step 27: pulseNext keyframes retained as a no-op for any rule that
   may still reference it from external partials — the rules above are
   migrated to static-only. Map and dashboard both no longer animate. */
@keyframes pulseNext {
  0%, 100% { box-shadow: 0 0 0 0 rgba(95, 212, 95, 0.4); }
  50%      { box-shadow: 0 0 0 4px rgba(95, 212, 95, 0); }
}

/* Step 28: next-battle CTA block rebased to a `.route-card` light-card
   skin so it harmonises with the other right-rail cards. The
   `.draft-cta` button retains the gb-btn-primary form (--d1 bg, --l2
   text) — a dark CTA inside a light card. */
.dash-r1 .next-battle {
  background: var(--l1); color: var(--d1);
  border: var(--border-thin);
  padding: 10px;
  margin-top: 8px;
  margin-bottom: 0;
}
.dash-r1 .next-battle form { margin: 0; }
.dash-r1 .next-battle .label {
  font-family: 'Press Start 2P', monospace;
  font-size: 10px; color: var(--d2);
  letter-spacing: 0.1em; margin-bottom: 4px;
}
.dash-r1 .next-battle .leader {
  color: var(--d1); font-size: 13px;
}
.dash-r1 .next-battle .prep {
  color: var(--d2); font-size: 11px; margin-top: 2px;
}
.dash-r1 .next-battle .draft-cta {
  margin-top: var(--s-4); width: 100%;
  background: var(--d1); color: var(--l2);
  border: var(--border-thin);
  padding: 8px 14px;
  font-family: 'Press Start 2P', monospace;
  font-size: 11px; letter-spacing: var(--ls-tight);
  line-height: 1.4;
  cursor: pointer;
  transition: all 0.05s;
}
.dash-r1 .next-battle .draft-cta:hover { background: var(--d2); color: var(--l2); }
.dash-r1 .next-battle .read-only {
  margin-top: var(--s-4);
  background: var(--d2); color: var(--l1);
  padding: var(--s-3); text-align: center;
  font-family: 'Press Start 2P', monospace;
  font-size: 9px; letter-spacing: 1px;
}

/* MAP sub-tab — compact ASCII map + cards (reuses .route-card etc.) */
.dash-r1 .status-panel .map-area {
  font-size: 9px; line-height: 1.4;
  color: var(--l1);
  white-space: pre;
}

/* ═══════════════════════════════════════════════════════════
   RESPONSIVE
   ═══════════════════════════════════════════════════════════ */

@media (max-width: 900px) {
  .pc-layout {
    grid-template-columns: 1fr;
    grid-template-rows: auto;
  }
  .panel { border-right: none; border-bottom: var(--border); max-height: 500px; }
  .panel:last-child { border-bottom: none; }

  .title-bar { flex-direction: column; gap: 8px; text-align: center; }
  .title-right { flex-wrap: wrap; justify-content: center; }

  .gb-nav { flex-direction: column; align-items: flex-start; }
  .gb-nav-left { flex-wrap: wrap; }

  .gb-grid-3 { grid-template-columns: repeat(2, 1fr); }
  .gb-grid-4 { grid-template-columns: repeat(2, 1fr); }

  /* Step 22 R2 — type-coverage rail stacks below the grid on narrower viewports. */
  .pc-box-r2 .box-layout { grid-template-columns: 1fr; }

  /* Step 24 R1 / Step 28 — tablet collapse. Left party col disappears
     (its content lives in the PARTY main tab); main + right rail stack
     to 2 cols. The party-col is now the first `.panel` child of
     `.pc-layout` (Step 28 dropped the `.col-party` wrapper), so we
     hide it via `:nth-child(1)`. */
  .dash-r1 .pc-layout { grid-template-columns: minmax(0, 1fr) 280px; }
  .dash-r1 .pc-layout > .panel:first-child { display: none; }
  .dash-r1 .title-bar { flex-direction: column; align-items: flex-start; }
}

/* Step 23 R4 — timeline → accordion swap. The horizontal track is hidden
   below 720px and replaced by a per-segment accordion. The sticky sheet
   drops `position: sticky` and stacks under the accordion in-flow. */
@media (max-width: 720px) {
  .map-r4 .layout { grid-template-columns: 1fr; }
  .map-r4 .timeline-frame { display: none; }
  .map-r4 .accordion-frame { display: block; }
  .map-r4 .sheet { position: static; }

  /* Step 24 R1 / Step 28 — phone reflow. Single column; tab strip
     becomes horizontally scrollable (active tab stays clickable).
     Title bar wraps so the player block sits on top and stat strip
     on its own row. */
  .dash-r1 .pc-layout { grid-template-columns: 1fr; }
  .dash-r1 .tab-bar { overflow-x: auto; flex-wrap: nowrap; }
  .dash-r1 .tab-item { min-width: 80px; flex: 0 0 auto; }
  .dash-r1 .title-bar { flex-direction: column; align-items: flex-start; }
  .dash-r1 .title-right { width: 100%; }
  .dash-r1 .stat-strip {
    width: 100%; padding-top: 6px;
    border-top: 1px dashed var(--d2);
  }
}

@media (max-width: 520px) {
  .gb-grid-3 { grid-template-columns: 1fr; }
  .gb-grid-4 { grid-template-columns: 1fr; }

  /* Step 22 R2 — phone reflow per mockup Screen 4. */
  .pc-box-r2 .box-grid { grid-template-columns: repeat(3, 1fr); gap: 6px; }
  .pc-box-r2 .box-cell { padding: 6px; }
  .pc-box-r2 .review-row { grid-template-columns: 36px 1fr; padding: 8px 10px; }
  .pc-box-r2 .review-row .sprite { width: 36px; height: 36px; }
  .pc-box-r2 .review-row .actions { grid-column: 1 / -1; flex-direction: row; gap: 6px; margin-top: 6px; }
  .pc-box-r2 .review-row .actions button { flex: 1; min-width: 0; }
  .pc-box-r2 .badge-legend { grid-template-columns: 1fr; }

  /* Step 23 R4 — special-bar reflows from 4 columns to 2 on phones. */
  .map-r4 .special-grid { grid-template-columns: repeat(2, 1fr); }

  /* Step 24 R1 — preserve stat-strip readability on the smallest viewports. */
  .dash-r1 .stat-strip { font-size: 7px; gap: 8px; }
}

@media (min-width: 901px) and (max-width: 1200px) {
  .pc-layout {
    grid-template-columns: 240px 1fr 260px;
  }
}

/* ═══════════════════════════════════════════════════════════
   GYM DRAFT — STEP 14 SURFACES
   Avatar pile + candidate card + TCG coin-flip modal.
   ═══════════════════════════════════════════════════════════ */

/* ── Avatars (cached on SoulLinkRun#player_avatars) ── */
.gb-avatar {
  display: inline-block;
  border-radius: 50%;
  border: 2px solid var(--d1);
  background: var(--l1);
  vertical-align: middle;
  object-fit: cover;
}

.gb-avatar--32 {
  width: 32px;
  height: 32px;
  font-size: 12px;
  line-height: 28px;
  text-align: center;
}

.gb-avatar--24 {
  width: 24px;
  height: 24px;
  font-size: 10px;
  line-height: 20px;
  text-align: center;
}

/* Initial-letter fallback when no Discord avatar URL is cached. The
   four pastel colors (--c0..--c3) are seeded from discord_user_id %% 4
   so the same user always renders the same color across sessions. */
.gb-avatar--initial {
  font-family: 'Press Start 2P', monospace;
  color: var(--d1);
  letter-spacing: 0;
}

.gb-avatar--c0 { background: #f4cccc; }
.gb-avatar--c1 { background: #c9daf8; }
.gb-avatar--c2 { background: #d9ead3; }
.gb-avatar--c3 { background: #fff2cc; }

.gb-avatar-pile {
  display: inline-flex;
  align-items: center;
}

.gb-avatar-pile > .gb-avatar + .gb-avatar {
  margin-left: -8px;
}

/* ── Candidate card (gym-draft nominating phase) ── */
.gb-candidate-card {
  background: var(--l1);
  border: var(--border-thin);
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 140px;
  position: relative;
}

.gb-candidate-card--leading {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent);
}

.gb-candidate-card__name {
  font-size: 12px;
  color: var(--d1);
  font-weight: bold;
}

.gb-candidate-card__species {
  font-size: 10px;
  color: var(--d2);
}

.gb-candidate-card__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.gb-candidate-card__count {
  font-size: 11px;
  color: var(--d1);
  font-family: 'Press Start 2P', monospace;
}

/* ── TCG coin-flip modal — tiebreak reveal ── */
/* Primary attempt: pokeball / character two-face 3D coin. Fallback
   (`# TCG-coin fallback used; see brief Q4 escape hatch`) drops the
   character face for a generic gold "?" face — same animation. */
.tcg-coin-stage {
  perspective: 800px;
  height: 120px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.tcg-coin {
  width: 80px;
  height: 80px;
  position: relative;
  transform-style: preserve-3d;
}

.tcg-coin--flipping {
  animation: tcgCoinFlip 1.8s cubic-bezier(0.2, 0.8, 0.4, 1.0) forwards;
}

.tcg-coin__face {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  backface-visibility: hidden;
  box-shadow:
    inset 0 0 0 4px #d4a444,
    0 4px 12px rgba(0, 0, 0, 0.4);
}

.tcg-coin__face--pokeball {
  background:
    radial-gradient(circle at 50% 50%, #ffffff 0 8px, #1a1a1a 8px 12px, transparent 12px 100%),
    linear-gradient(to bottom, #ee1515 0 50%, #1a1a1a 50% 54%, #f0f0f0 54% 100%);
}

.tcg-coin__face--character {
  transform: rotateY(180deg);
  background:
    radial-gradient(circle at 50% 50%, #f7d358 0 30%, #d4a444 30% 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #6b3c0a;
  font-family: 'Press Start 2P', monospace;
  font-size: 28px;
  text-shadow: 1px 1px 0 #fff7d8;
}

.tcg-coin__face--character::before {
  content: "★";
}

@keyframes tcgCoinFlip {
  0%   { transform: rotateY(0deg) translateY(0); }
  85%  { transform: rotateY(1980deg) translateY(-12px); }
  100% { transform: rotateY(1980deg) translateY(0); }
}
