@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&family=Inter:wght@400;500;600;700;800&display=swap');

:root {
  --bg: #08090d;
  --bg-elevated: #101219;
  --bg-elevated-2: #161923;
  --border: #232838;
  --border-bright: #323a52;
  --text: #eceef4;
  --text-muted: #868da3;
  --accent: #22d3ee;
  --accent-dim: rgba(34, 211, 238, 0.12);
  --accent-2: #a855f7;
  --ok: #2be6a0;
  --ok-dim: rgba(43, 230, 160, 0.14);
  --warn: #fbbf24;
  --warn-dim: rgba(251, 191, 36, 0.14);
  --info: #22d3ee;
  --info-dim: rgba(34, 211, 238, 0.14);
  --danger: #f87171;
  --danger-dim: rgba(248, 113, 113, 0.14);
  --radius: 3px;
  --radius-lg: 6px;
  --sidebar-w: 220px;
  --mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --sans: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--sans);
  background:
    radial-gradient(ellipse 900px 500px at 15% -10%, rgba(34,211,238,0.06), transparent 60%),
    radial-gradient(ellipse 700px 500px at 100% 0%, rgba(168,85,247,0.05), transparent 55%),
    var(--bg);
  color: var(--text);
  line-height: 1.6;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
code, .mono { font-family: var(--mono); }

/* ---------- App shell: sidebar + content ---------- */
.app-shell { display: flex; min-height: 100vh; }

.sidebar {
  width: var(--sidebar-w);
  flex-shrink: 0;
  background: var(--bg-elevated);
  border-right: 1px solid var(--border);
  padding: 22px 16px;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.sidebar .brand {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--mono);
  font-weight: 700;
  font-size: 1rem;
  margin-bottom: 26px;
  padding: 0 8px;
}

.sidebar .brand img.logo-mark { width: 22px; height: 22px; flex-shrink: 0; }

/* .brand-text wraps "Steam Machine Lab" as one normal (non-flex) inline text
   run, so it reflows and wraps at word boundaries like ordinary text. Making
   the link itself the only flex container - just icon + this one text block
   - avoids the bug where "Steam Machine " and the nested .lab span each
   became their own flex item and wrapped independently of each other. */
.sidebar .brand a { display: flex; align-items: center; gap: 8px; }
.sidebar .brand a .brand-text { color: #ff8a4c; }
.sidebar .brand a .brand-text .lab { color: var(--text); }

.sidebar nav a {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border-radius: var(--radius);
  color: var(--text-muted);
  font-size: 0.86rem;
  font-weight: 500;
  margin-bottom: 2px;
}

.sidebar nav a:hover { background: var(--bg-elevated-2); color: var(--text); text-decoration: none; }
.sidebar nav a.active { background: var(--accent-dim); color: var(--accent); }

/* A plain nav link like the rest of the menu (same size, weight, hover
   behavior) - just keeps its small icon for a bit of brand recognition. */
.sidebar nav a.nav-kofi svg { width: 15px; height: 15px; flex-shrink: 0; }
/* The Instagram glyph (a nearly-full-bleed rounded square) reads visibly
   bigger than the coffee cup at the same box size, since it fills far more
   of its 24x24 viewBox - sized down to match perceived weight, not the
   literal box dimensions. */
.sidebar nav a.nav-instagram svg { width: 13px; height: 13px; flex-shrink: 0; }

.sidebar .search-box { margin: 16px 8px; }
.sidebar .search-box input {
  width: 100%;
  padding: 8px 10px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text);
  font-size: 0.82rem;
  font-family: var(--mono);
}

.content { flex: 1; min-width: 0; padding: 26px 30px 80px; }

.content-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 22px;
}

.content-header h1 {
  font-size: 1.3rem;
  margin: 0;
  letter-spacing: -0.2px;
}

.game-count {
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--ok);
  display: flex;
  align-items: center;
  gap: 6px;
}
.game-count::before { content:""; width:6px; height:6px; border-radius:50%; background: var(--ok); box-shadow: 0 0 5px var(--ok); }

.controls {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 20px;
  align-items: center;
  padding: 14px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}

.controls input[type="search"], .controls select {
  padding: 10px 14px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text);
  font-size: 0.88rem;
  font-family: var(--mono);
}
.controls input[type="search"] { flex: 1 1 240px; }
.controls select { font-size: 0.8rem; }
.controls input:focus, .controls select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-dim); }

/* View toggle (grid/list) lives at the end of the controls row and pushes
   itself flush right via margin-left:auto, same trick used elsewhere in
   this file for end-aligning one flex child without a wrapper div. */
.view-toggle { display: inline-flex; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; flex-shrink: 0; margin-left: auto; }
.view-toggle button {
  display: flex; align-items: center; gap: 6px; padding: 9px 13px; background: var(--bg);
  color: var(--text-muted); border: none; border-left: 1px solid var(--border);
  font-family: var(--sans); font-size: 0.82rem; cursor: pointer;
}
.view-toggle button:first-child { border-left: none; }
.view-toggle button:hover { color: var(--text); }
.view-toggle button.active { background: var(--accent-dim); color: var(--accent); }
.view-toggle svg { width: 14px; height: 14px; flex-shrink: 0; }

.result-count {
  color: var(--text-muted);
  font-size: 0.76rem;
  font-family: var(--mono);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 16px;
}

/* ---------- Grid / Cards ---------- */
.game-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 14px;
}

.game-card {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: border-color 0.15s ease, transform 0.15s ease;
  position: relative;
  color: inherit;
  text-decoration: none;
  cursor: pointer;
}
.game-card:hover { border-color: var(--border-bright); transform: translateY(-2px); text-decoration: none; }
.game-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.card-media {
  height: 130px;
  position: relative;
  display: flex; align-items: center; justify-content: center;
  background: repeating-linear-gradient(135deg, rgba(255,255,255,0.02) 0 2px, transparent 2px 14px), linear-gradient(135deg, var(--bg-elevated-2), var(--bg));
  border-bottom: 1px solid var(--border);
  overflow: hidden;
}
.card-media img { width: 100%; height: 100%; object-fit: cover; }
.card-media .monogram { font-family: var(--mono); font-weight: 700; font-size: 1.7rem; color: var(--text-muted); opacity: 0.55; }

.tier-pill {
  position: absolute; top: 8px; left: 8px;
  font-family: var(--mono); font-size: 0.65rem; font-weight: 700;
  padding: 3px 8px; border-radius: 2px; text-transform: uppercase; letter-spacing: 0.4px;
}
.tier-excellent { background: rgba(43,230,160,0.85); color: #052e20; }
.tier-great { background: rgba(34,211,238,0.85); color: #04303a; }
.tier-good { background: rgba(129,140,248,0.85); color: #1c1a3a; }
.tier-average { background: rgba(251,191,36,0.85); color: #3a2a04; }
.tier-below-average { background: rgba(248,113,113,0.85); color: #3a0a0a; }

.status-dot { position: absolute; top: 8px; right: 8px; width: 20px; height: 20px; border-radius: 50%; display:flex; align-items:center; justify-content:center; font-size: 0.7rem; }
.badge { display: inline-block; padding: 2px 9px; border-radius: 3px; font-weight: 700; }
.status-verified { background: var(--ok); color: #052e20; }
.status-playable { background: var(--info); color: #04303a; }
.status-needs-tweaks { background: var(--warn); color: #3a2a04; }
.status-unknown { background: #6b7284; color: #0d0f14; }

.metacritic-badge {
  font-family: var(--mono); font-weight: 700; font-size: 0.78rem;
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 4px;
}
.metacritic-badge.mc-high { background: rgba(43,230,160,0.85); color: #052e20; }
.metacritic-badge.mc-mid { background: rgba(251,191,36,0.85); color: #3a2a04; }
.metacritic-badge.mc-low { background: rgba(248,113,113,0.85); color: #3a0a0a; }
.metacritic-badge.card-mc { position: absolute; bottom: 8px; right: 8px; width: 24px; height: 24px; font-size: 0.7rem; z-index: 2; }

.card-body { padding: 12px 14px 14px; display: flex; flex-direction: column; gap: 8px; flex: 1; }
.game-card h3 {
  margin: 0; font-size: 0.96rem; font-weight: 700; color: var(--text);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; line-height: 1.3em; min-height: 2.6em;
}
.game-card:hover h3 { color: var(--accent); }
.card-body .fps-row { margin-top: auto; }

.fps-row {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px;
  font-family: var(--mono); font-size: 0.72rem; margin-top: 2px;
}
.fps-row div { text-align: center; }
.fps-row .val { font-weight: 700; font-size: 0.88rem; display:block; }
.fps-row .lbl { color: var(--text-muted); text-transform: uppercase; font-size: 0.62rem; }
/* Same 60+ green / 31-59 amber / 30-and-under red coding as the detail page's
   performance panel - see compat_fps_tone() in includes/functions.php. Also
   covers .row-fps (list view) - render_game_row() applies the exact same
   tone-* class, so both views need to share this color rule. */
.fps-row .val.tone-good, .row-fps .val.tone-good { color: var(--ok); }
.fps-row .val.tone-warn, .row-fps .val.tone-warn { color: var(--warn); }
.fps-row .val.tone-bad, .row-fps .val.tone-bad { color: var(--danger); }

.empty-state { color: var(--text-muted); padding: 50px 0; text-align: center; font-family: var(--mono); font-size: 0.9rem; }

/* ---------- List view (games.php alternative to .game-grid) ----------
   Column widths are fixed px (not %) so the title column - the only 1fr -
   simply absorbs whatever space is left on wide viewports, same approach
   as .admin-table. Verified against real-shaped cover art (Steam's
   header_image banner, ~460x215) before picking 64x30 for the thumb -
   a square or portrait box cropped out the title text and most of the art. */
.list-head {
  display: grid; grid-template-columns: 64px 1fr 96px 150px repeat(3, 56px);
  gap: 14px; padding: 0 14px 0 8px; margin: -6px 0 8px;
  font-family: var(--mono); font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-muted);
}
.list-head span:nth-child(n+5) { text-align: center; }

.game-list { display: flex; flex-direction: column; gap: 6px; }

.game-row {
  display: grid;
  grid-template-columns: 64px 1fr 96px 150px repeat(3, 56px);
  align-items: center;
  gap: 14px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 8px 14px 8px 8px;
  color: inherit;
  text-decoration: none;
}
.game-row:hover { border-color: var(--border-bright); background: var(--bg-elevated-2); text-decoration: none; }
.game-row:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.row-thumb {
  width: 64px; height: 30px; border-radius: var(--radius); overflow: hidden; flex-shrink: 0;
  background: var(--bg-elevated-2); display: flex; align-items: center; justify-content: center;
}
.row-thumb img { width: 100%; height: 100%; object-fit: cover; }
.row-thumb .monogram-mini { font-family: var(--mono); font-size: 0.7rem; font-weight: 700; color: var(--text-muted); opacity: 0.6; }

.row-title { min-width: 0; }
.row-title h3 { margin: 0; font-size: 0.9rem; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.game-row:hover .row-title h3 { color: var(--accent); }
.row-title .row-cat { font-family: var(--mono); font-size: 0.68rem; color: var(--text-muted); text-transform: uppercase; margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* .status-dot and .tier-pill are position:absolute by default (they're
   normally overlaid on .card-media) - reset that here since these list rows
   have no positioned ancestor of their own, which without this override
   made them escape to the corner of the viewport instead of sitting inline. */
.row-status { display: flex; align-items: center; gap: 8px; font-size: 0.78rem; color: var(--text-muted); }
.row-status .status-dot { position: static; top: auto; right: auto; flex-shrink: 0; }

.row-tier { display: flex; align-items: center; gap: 8px; }
.row-tier .tier-pill { position: static; top: auto; left: auto; }
.row-mc { width: 24px; height: 24px; font-size: 0.7rem; }

.row-fps { text-align: center; font-family: var(--mono); }
.row-fps .val { font-weight: 700; font-size: 0.86rem; display: block; }
.row-fps .lbl { color: var(--text-muted); text-transform: uppercase; font-size: 0.58rem; }

/* ---------- Homepage ---------- */
.home-hero-row { display: flex; gap: 36px; align-items: flex-start; flex-wrap: wrap; margin: 4px 0 40px; }
.home-hero { max-width: 620px; flex: 1 1 420px; }
.home-hero h1 { font-size: 2rem; line-height: 1.28; margin: 0 0 16px; letter-spacing: -0.4px; }
.home-hero .home-intro { color: var(--text-muted); font-size: 1rem; max-width: 620px; margin: 0 0 14px; }
.home-hero .home-intro:last-of-type { margin-bottom: 24px; }
.home-actions { display: flex; gap: 10px; flex-wrap: wrap; }

.home-section-intro { color: var(--text-muted); font-size: 0.88rem; margin: -6px 0 18px; max-width: 620px; }
.home-view-all { display: inline-flex; align-items: center; gap: 6px; font-family: var(--mono); font-size: 0.82rem; margin-top: 20px; }

/* Performance-breakdown chart panel, sat beside the hero copy. Each row is a
   full-width link (not just its text) to that tier's filtered game list -
   the hit target is the whole bar, not just the label. */
.home-chart-panel {
  flex: 0 1 300px; min-width: 260px;
  background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-lg);
  padding: 18px;
}
/* The total is a link to the full game list, styled to read as plain text
   (no underline/accent-blue) until hovered, like the tier bars below it. */
.home-chart-panel .chart-head { display: block; font-family: var(--mono); color: inherit; text-decoration: none; border-radius: var(--radius); margin: -6px -6px 12px; padding: 6px; }
.home-chart-panel .chart-head:hover { background: var(--bg-elevated-2); text-decoration: none; }
.home-chart-panel .chart-head strong { display: block; font-size: 1.6rem; color: var(--text); line-height: 1.2; }
.home-chart-panel .chart-head span { font-size: 0.72rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.5px; }
.home-chart-panel .chart-head:hover span { color: var(--text); }

.tier-bar-list { display: flex; flex-direction: column; gap: 3px; }
.tier-bar-row {
  display: flex; align-items: center; gap: 10px; padding: 6px 8px; margin: 0 -8px;
  border-radius: var(--radius); text-decoration: none; color: inherit;
}
.tier-bar-row:hover { background: var(--bg-elevated-2); text-decoration: none; }
.tier-bar-row .tier-bar-label { width: 96px; flex-shrink: 0; font-size: 0.74rem; color: var(--text-muted); font-family: var(--mono); }
.tier-bar-row:hover .tier-bar-label { color: var(--text); }
.tier-bar-row .tier-bar-track { flex: 1; height: 10px; background: var(--bg); border-radius: 5px; overflow: hidden; }
.tier-bar-row .tier-bar-fill { display: block; height: 100%; min-width: 2px; border-radius: 0 5px 5px 0; }
.tier-bar-row .tier-bar-value { width: 22px; flex-shrink: 0; text-align: right; font-family: var(--mono); font-weight: 700; font-size: 0.8rem; color: var(--text); }

/* ---------- Detail page ---------- */
/* Single column: eyebrow -> title -> cover banner -> description -> panels.
   The cover sits between the title and description, sized to match the
   compat/FPS panels below it rather than stretching the full content width. */
.detail-hero { margin-bottom: 30px; }
.detail-hero .cover-banner {
  width: 100%; max-width: 560px; height: 150px; border-radius: var(--radius-lg);
  background: var(--bg-elevated-2); border: 1px solid var(--border);
  display: flex; align-items: center; justify-content: center; overflow: hidden; margin-bottom: 16px;
}
/* object-fit: contain (not cover) - covers can come from two very different
   sources: a portrait title-card auto-generated via "Use as cover image"
   (which matches this box's aspect ratio and fills it edge-to-edge either
   way), or a landscape image pulled in from Steam's lookup feature (Steam's
   API only exposes wide banner images, no portrait cover art). Cropping the
   latter into this box would slice away most of the image - showing
   the whole image letterboxed on the gradient background looks right for
   both cases. */
.detail-hero .cover-banner img { width: 100%; height: 100%; object-fit: contain; }
.detail-hero .cover-banner .monogram { font-family: var(--mono); font-size: 2.8rem; color: var(--text-muted); opacity: 0.5; }

/* Bare (not scoped to .detail-hero) so the homepage hero can reuse the same
   eyebrow-tag treatment without a duplicated rule. */
.eyebrow { font-family: var(--mono); font-size: 0.76rem; text-transform: uppercase; letter-spacing: 1px; color: var(--accent); margin-bottom: 8px; }
.detail-hero h1 { font-size: 1.8rem; margin: 0 0 10px; letter-spacing: -0.3px; }
.detail-hero .desc { color: var(--text-muted); max-width: 560px; margin-bottom: 14px; }
.meta-line-detail { font-family: var(--mono); font-size: 0.8rem; color: var(--text-muted); margin-bottom: 14px; }

/* ---------- Compatibility panel (status / performance / metascore / features) ---------- */
.compat-panel {
  background: var(--bg-elevated-2); border: 1px solid var(--border); border-radius: var(--radius-lg);
  overflow: hidden; margin-bottom: 14px; max-width: 560px;
}
.compat-panel .panel-head {
  display: flex; align-items: center; gap: 8px; padding: 9px 14px; border-bottom: 1px solid var(--border);
  font-family: var(--mono); font-size: 0.72rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 1px;
}
.compat-panel .panel-head .dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.compat-panel .panel-grid { display: grid; grid-template-columns: 1fr 1fr; }
.compat-panel .panel-row {
  display: flex; align-items: center; gap: 9px; padding: 11px 14px;
  border-bottom: 1px solid var(--border); border-right: 1px solid var(--border);
  font-family: var(--mono); font-size: 0.82rem;
}
.compat-panel .panel-row:nth-child(even) { border-right: none; }
.compat-panel .panel-row .k { color: var(--text-muted); min-width: 92px; font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.5px; }
.compat-panel .panel-row .v { display: flex; align-items: center; gap: 6px; font-weight: 600; }
.compat-panel .panel-row .v svg { width: 15px; height: 15px; flex-shrink: 0; }
/* "Neutral" used to mean muted grey, but that read as disabled/washed-out for
   plain informational values (Metascore not rated, Cloud Saves unavailable,
   Proton version) - full-brightness text keeps them legible while the tone-*
   colors above still carry the pass/fail meaning where one applies. */
.compat-panel .panel-row .v.neutral { color: var(--text); font-weight: 500; }
.compat-panel .panel-row .v .stars { display: inline-flex; gap: 1px; margin-right: 1px; }
.compat-panel .panel-row .v .stars svg { width: 12px; height: 12px; flex-shrink: 0; }
/* Panel value colors use their own "tone-" classes rather than the
   status-, tier-, mc- names used for the card badges elsewhere - those
   classes carry their own background-color rules (for pill-shaped badges),
   which would leak through here and fight with this panel's text-only
   coloring (e.g. green text becoming invisible on a green badge background).
   text color on .v, background color on the panel-head .dot */
.compat-panel .v.tone-good, .fps-table-panel .v.tone-good { color: var(--ok); }
.compat-panel .v.tone-info, .fps-table-panel .v.tone-info { color: var(--info); }
.compat-panel .v.tone-indigo, .fps-table-panel .v.tone-indigo { color: #818cf8; }
.compat-panel .v.tone-warn, .fps-table-panel .v.tone-warn { color: var(--warn); }
.compat-panel .v.tone-bad, .fps-table-panel .v.tone-bad { color: var(--danger); }
.compat-panel .panel-head .dot.tone-good { background: var(--ok); box-shadow: 0 0 5px var(--ok); }
.compat-panel .panel-head .dot.tone-info { background: var(--info); }
.compat-panel .panel-head .dot.tone-warn { background: var(--warn); }
.compat-panel .panel-head .dot.tone-bad { background: var(--danger); }
.compat-panel .panel-head .dot.neutral { background: var(--text-muted); }

.action-row { display: flex; gap: 10px; margin-top: 4px; flex-wrap: wrap; }
.btn-link {
  font-family: var(--mono); font-size: 0.8rem; display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 14px; border-radius: var(--radius); border: 1px solid var(--border-bright);
  color: var(--text); text-decoration: none; background: var(--bg-elevated-2);
}
.btn-link svg { width: 14px; height: 14px; flex-shrink: 0; }
.btn-link:hover { text-decoration: none; }
.btn-link.steam:hover { border-color: var(--accent); color: var(--accent); }

/* FPS table - same grey-panel language as .compat-panel above it, evenly
   split into 3 columns instead of the compat-panel's 2. */
.fps-table-panel {
  background: var(--bg-elevated-2); border: 1px solid var(--border); border-radius: var(--radius-lg);
  overflow: hidden; margin: 14px 0; max-width: 560px;
}
.fps-table-panel .panel-head {
  display: flex; align-items: center; gap: 8px; padding: 7px 14px; border-bottom: 1px solid var(--border);
  font-family: var(--mono); font-size: 0.7rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 1px;
}
.fps-table-panel .panel-head .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ok); box-shadow: 0 0 5px var(--ok); flex-shrink: 0; }
.fps-table-panel .fps-grid { display: grid; grid-template-columns: repeat(3, 1fr); }
.fps-table-panel .fps-col { text-align: center; padding: 9px 10px; border-right: 1px solid var(--border); }
.fps-table-panel .fps-col:last-child { border-right: none; }
.fps-table-panel .fps-col .k { display: block; font-family: var(--mono); font-size: 0.64rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.6px; margin-bottom: 3px; }
/* No default color here - always paired with a tone-* class below (60fps+
   green, 31-59 amber, 30 and under red), same pattern as .compat-panel .v. */
.fps-table-panel .fps-col .v { font-family: var(--mono); font-size: 1.2rem; font-weight: 700; }
.fps-table-panel .fps-col .v small { font-size: 0.6rem; font-weight: 600; color: var(--text-muted); margin-left: 3px; }

section.ig-embed { margin: 20px 0; padding: 18px; background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-lg); }
section.ig-embed .ig-embed-label { font-family: var(--mono); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.6px; color: var(--text-muted); margin-bottom: 12px; }
section.ig-embed .ig-embed-frame { display: flex; justify-content: center; }
section.ig-embed .ig-embed-frame > blockquote.instagram-media { margin: 0 !important; }

.section-block { margin-top: 30px; max-width: 760px; }
.section-block h2 {
  font-size: 1rem; font-family: var(--mono); text-transform: uppercase; letter-spacing: 0.6px;
  padding: 10px 14px; background: var(--bg-elevated); border-left: 3px solid var(--accent); border-radius: 2px; margin-bottom: 14px;
}
/* Homepage sections hold a multi-column game grid, which needs the full
   content width rather than the detail page's single-column 760px measure -
   same heading treatment, just not width-capped. */
.section-block.wide { max-width: none; }
/* The table itself - not the heading above it - is what needs to scroll on
   narrow screens (settings tables regularly run wider than a phone). Giving
   the table its own scroll box, separate from .section-block, keeps the
   heading pinned at the section's actual width instead of both scrolling
   together, which made the heading look narrower than the table and let the
   last column (4K) end up flush against the edge with no room to spare. */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; padding-bottom: 2px; }

table.settings-table { width: 100%; border-collapse: collapse; margin: 10px 0 20px; font-size: 0.88rem; }
table.settings-table th, table.settings-table td { text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--border); }
table.settings-table tr:hover { background: rgba(255,255,255,0.015); }
table.settings-table th { color: var(--text-muted); font-weight: 600; font-family: var(--mono); font-size: 0.8rem; text-transform: uppercase; }
table.settings-table td.label { font-family: var(--sans); font-weight: 600; width: 32%; }
table.settings-table td.val { font-family: var(--mono); }

.back-link { display: inline-flex; align-items: center; gap: 6px; margin-top: 30px; font-family: var(--mono); font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.4px; }

footer.site-footer { padding: 24px 0; color: var(--text-muted); font-size: 0.78rem; font-family: var(--mono); border-top: 1px solid var(--border); margin-top: 40px; }

/* ---------- FAQ page ---------- */
.faq-list { display: flex; flex-direction: column; gap: 10px; margin-top: 20px; max-width: 760px; }
.faq-item {
  background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-lg);
  padding: 4px 18px;
}
.faq-item summary {
  cursor: pointer; padding: 14px 0; font-weight: 700; font-size: 0.96rem;
  list-style: none; display: flex; justify-content: space-between; align-items: center; gap: 12px;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after { content: "+"; font-family: var(--mono); color: var(--accent); font-size: 1.2rem; flex-shrink: 0; }
.faq-item[open] summary::after { content: "\2212"; }
.faq-item p { color: var(--text-muted); margin: 0 0 16px; max-width: 720px; }
/* Reference list for the performance star rating FAQ entry - same tone
   colors (var(--ok)/var(--info)/#818cf8/var(--warn)/var(--danger)) and star
   icon as the detail page's Performance row, see compat_tier_tone() /
   compat_tier_stars() / render_tier_star_legend() in includes/functions.php. */
.faq-tier-legend { display: flex; flex-direction: column; gap: 6px; margin: 0 0 16px; max-width: 360px; }
.faq-tier-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 8px 14px; background: var(--bg-elevated-2); border: 1px solid var(--border);
  border-radius: var(--radius); font-family: var(--mono); font-weight: 700; font-size: 0.84rem;
}
.faq-tier-row .faq-tier-stars { display: inline-flex; gap: 1px; }
.faq-tier-row .faq-tier-stars svg { width: 14px; height: 14px; flex-shrink: 0; }
.faq-tier-row.tone-good { color: var(--ok); }
.faq-tier-row.tone-info { color: var(--info); }
.faq-tier-row.tone-indigo { color: #818cf8; }
.faq-tier-row.tone-warn { color: var(--warn); }
.faq-tier-row.tone-bad { color: var(--danger); }

/* ---------- Admin ---------- */
.admin-body { background: var(--bg); color: var(--text); font-family: var(--sans); }
.admin-wrap { max-width: 1100px; margin: 0 auto; padding: 30px 24px 80px; }
.admin-topbar { display:flex; justify-content: space-between; align-items:center; margin-bottom: 24px; padding-bottom: 16px; border-bottom: 1px solid var(--border); }
.admin-topbar .brand { font-family: var(--mono); font-weight: 700; }
.btn {
  display: inline-flex; align-items:center; gap:6px; padding: 9px 16px; border-radius: var(--radius);
  background: var(--accent); color: #04303a; font-weight: 700; font-size: 0.86rem; border: none; cursor: pointer; font-family: var(--sans);
}
.btn:hover { text-decoration: none; opacity: 0.9; }
.btn.secondary { background: var(--bg-elevated); color: var(--text); border: 1px solid var(--border); }
.btn.danger { background: #f87171; color: #3a0a0a; }
/* Same orange as the "Steam Machine" wordmark in the sidebar brand (#ff8a4c) -
   used on the homepage's "Submit settings" CTA to stand out from the cyan
   primary/dark secondary buttons next to it. */
.btn.orange { background: #ff8a4c; color: #3a1c04; }
/* --accent-2 (purple) was already in the palette - it's the second color in
   the subtle page-background gradient - but wasn't used on any UI element
   yet. Giving "How we test" this solid fill (instead of the plain outlined
   .secondary style) makes the three homepage buttons read as one matched
   set of filled CTAs, each in its own color, rather than one plain button
   sitting next to two colorful ones. */
.btn.purple { background: var(--accent-2); color: #2e0f52; }
.admin-table { width: 100%; border-collapse: collapse; background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; }
.admin-table th, .admin-table td { padding: 10px 14px; border-bottom: 1px solid var(--border); text-align: left; font-size: 0.88rem; }
.admin-table th { font-family: var(--mono); font-size: 0.76rem; text-transform: uppercase; color: var(--text-muted); }
.admin-table tr:last-child td { border-bottom: none; }
.admin-table .actions { display:flex; gap:8px; align-items:center; }
.admin-table .actions a, .admin-table .actions button { font-size: 0.8rem; }
.admin-table .actions form { display: inline; }
/* Duplicate needs to be a real form submission (CSRF-protected POST, same
   as delete/dismiss elsewhere) rather than a plain <a>, but it lives among
   Edit/Generate/View - plain text links, no button chrome - so it strips
   all default <button> styling and reads exactly like its neighbors. */
.admin-table .actions .link-btn {
  background: none; border: none; padding: 0; margin: 0;
  font-family: inherit; font-size: inherit; color: var(--accent);
  cursor: pointer; text-decoration: none;
}
.admin-table .actions .link-btn:hover { text-decoration: underline; }

/* Plain <select> used standalone on admin pages (e.g. the dashboard's "Sort
   by" control) outside a .form-field - same dark input treatment as form
   fields, just not nested in that grid/label layout. */
.admin-select {
  padding: 7px 10px; border-radius: var(--radius); border: 1px solid var(--border);
  background: var(--bg); color: var(--text); font-family: var(--sans); font-size: 0.84rem;
}

.form-card { background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 24px; margin-bottom: 20px; }
.form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 16px; }
.form-field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
.form-field label { font-family: var(--mono); font-size: 0.76rem; text-transform: uppercase; letter-spacing: 0.4px; color: var(--text-muted); }
.form-field input, .form-field select, .form-field textarea {
  padding: 9px 12px; border-radius: var(--radius); border: 1px solid var(--border); background: var(--bg); color: var(--text); font-family: var(--sans); font-size: 0.9rem;
}
.form-field textarea { min-height: 70px; resize: vertical; font-family: var(--sans); }
.form-field.checkbox { flex-direction: row; align-items: center; gap: 8px; }
.form-field.checkbox label { text-transform: none; font-family: var(--sans); font-size: 0.88rem; }

/* ---------- Admin cover image preview ---------- */
.cover-preview-row { display: flex; gap: 18px; align-items: flex-start; flex-wrap: wrap; }
.cover-preview-row .form-grid { flex: 1; min-width: 240px; margin-bottom: 0; }
.cover-preview-box {
  width: 160px; height: 200px; flex-shrink: 0; border-radius: var(--radius-lg);
  background: linear-gradient(135deg, var(--bg-elevated-2), var(--bg)); border: 1px solid var(--border);
  display: flex; align-items: center; justify-content: center; overflow: hidden;
}
/* object-fit: contain, matching the public detail page's cover box - covers
   can be a portrait title-card, a landscape Steam banner, or anything in
   between, and this box shouldn't crop whichever shape shows up here. */
.cover-preview-box img { width: 100%; height: 100%; object-fit: contain; }
.cover-preview-box .empty { font-family: var(--mono); font-size: 0.76rem; color: var(--text-muted); text-align: center; padding: 0 12px; }

.settings-row-editor { border: 1px solid var(--border); border-radius: var(--radius); padding: 12px; margin-bottom: 10px; background: var(--bg); }
.settings-row-editor .row-grid { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr auto; gap: 8px; align-items: center; }
.settings-row-editor input { padding: 7px 10px; border-radius: var(--radius); border: 1px solid var(--border); background: var(--bg-elevated); color: var(--text); font-size: 0.84rem; }
.section-group { border: 1px dashed var(--border-bright); border-radius: var(--radius-lg); padding: 14px; margin-bottom: 16px; }
.section-group .section-name { margin-bottom: 10px; }
.section-group .section-name input { font-weight: 700; }

.steam-results { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; max-height: 260px; overflow-y: auto; }
.steam-result-item {
  display: flex; align-items: center; gap: 10px; text-align: left;
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 6px 10px; cursor: pointer; color: var(--text); font-family: var(--sans); font-size: 0.86rem;
}
.steam-result-item:hover { border-color: var(--accent); }
.steam-result-item img { width: 32px; height: 15px; object-fit: cover; border-radius: 2px; flex-shrink: 0; }

.login-card { max-width: 360px; margin: 80px auto; background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 30px; }
.flash { padding: 10px 14px; border-radius: var(--radius); font-size: 0.86rem; margin-bottom: 16px; }
.flash.error { background: rgba(248,113,113,0.12); color: #f87171; border: 1px solid rgba(248,113,113,0.3); }
.flash.success { background: var(--ok-dim); color: var(--ok); border: 1px solid rgba(43,230,160,0.3); }

/* Carousel generator canvases */
.carousel-preview-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 220px));
  gap: 16px; margin-top: 20px;
}
.carousel-card-frame { width: 100%; }
.carousel-card-frame .label { font-family: var(--mono); font-size: 0.72rem; color: var(--text-muted); margin-bottom: 6px; text-transform: uppercase; }
.carousel-card-thumb {
  width: 100%; border: 1px solid var(--border); border-radius: 6px; overflow: hidden;
  background: var(--bg-elevated-2);
}
.carousel-card-thumb canvas { display: block; width: 100% !important; height: auto !important; }

/* ---------- Mobile / small screens ---------- */

/* Tablet: sidebar narrows and stops being a full-height rail. */
@media (max-width: 900px) {
  .app-shell { flex-direction: column; }
  .sidebar {
    width: 100%; height: auto; position: sticky; top: 0; z-index: 20;
    padding: 12px 16px;
    display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
    border-right: none; border-bottom: 1px solid var(--border);
  }
  .sidebar .brand { margin-bottom: 0; }
  /* flex-wrap here matters: nav a has white-space: nowrap (so link labels
     never break mid-word), which means without wrapping the nav row itself
     can't shrink below its content's natural width - forcing the whole
     sidebar, and with it the whole page, wider than the viewport on narrow
     phones. */
  .sidebar nav { display: flex; gap: 4px; flex-wrap: wrap; align-items: center; }
  .sidebar nav a { margin-bottom: 0; padding: 8px 10px; white-space: nowrap; }
  .sidebar .search-box { margin: 0; flex: 1 1 160px; min-width: 140px; }
  .content { padding: 20px 18px 60px; }
}

/* Phones */
@media (max-width: 640px) {
  html { -webkit-text-size-adjust: 100%; }
  .sidebar { padding: 10px 12px; gap: 8px; }
  .sidebar .brand { font-size: 0.9rem; }
  .sidebar nav a { padding: 7px 8px; font-size: 0.8rem; }
  .sidebar .search-box { flex: 1 1 130px; max-width: 200px; min-width: 0; order: 3; }
  .sidebar .search-box input { padding: 6px 8px; font-size: 0.76rem; }

  .content-header { flex-direction: column; align-items: flex-start; gap: 6px; }
  .content-header h1 { font-size: 1.15rem; }

  .controls { flex-direction: column; align-items: stretch; padding: 12px; }
  /* .controls input[type="search"] carries flex: 1 1 240px for the desktop
     ROW layout, where flex-basis governs width. Once the container switches
     to flex-direction: column above, that same flex-basis governs HEIGHT
     instead - stretching the search box to ~240px tall. Reset it here so
     the box sizes to its natural single-line height on phones. */
  .controls input[type="search"], .controls select { width: 100%; flex: 0 0 auto; }

  .game-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
  .card-media { height: 100px; }
  .card-body { padding: 10px 10px 12px; }
  .game-card h3 { font-size: 0.86rem; }
  .fps-row .val { font-size: 0.8rem; }

  .view-toggle { margin-left: 0; align-self: flex-start; }

  /* List view on phones: drop the column header row and the status/tier
     columns (title + the three FPS numbers are the part visitors actually
     come to compare - same reasoning as the fps-table-panel note above
     about keeping 1080p/1440p/4K side by side rather than stacking). */
  .list-head { display: none; }
  .game-row { grid-template-columns: 44px 1fr repeat(3, 38px); gap: 8px; padding: 6px 10px 6px 6px; }
  .row-thumb { width: 44px; height: 21px; }
  .row-status, .row-tier { display: none; }
  .row-title h3 { font-size: 0.82rem; }
  .row-fps .val { font-size: 0.76rem; }
  .row-fps .lbl { font-size: 0.52rem; }

  .detail-hero .cover-banner { height: 130px; }
  .detail-hero h1 { font-size: 1.4rem; }
  /* 1080p/1440p/4K stay side by side even on phones - three short numbers
     comfortably fit three narrow columns, and stacking them made the panel
     harder to scan than just letting each column get narrower. */
  .fps-table-panel .fps-col { padding: 8px 4px; }
  .compat-panel .panel-grid { grid-template-columns: 1fr; }
  .compat-panel .panel-row { border-right: none; }
  .action-row { flex-wrap: wrap; gap: 10px; }

  table.settings-table { min-width: 480px; font-size: 0.82rem; }
  table.settings-table th, table.settings-table td { padding: 8px 10px; }
  /* Extra right padding on the last column only, inside the scroll box -
     without it the 4K column's own edge lands flush against the scroll
     container's edge with zero margin, which reads as "cut off" even though
     it's technically fully scrolled into view. */
  table.settings-table th:last-child, table.settings-table td:last-child { padding-right: 16px; }
  /* Pin the "Setting" column so it stays put while 1080p/1440p/4K scroll
     past underneath it - without this, scrolling right to see the 4K value
     also scrolls the row's label out of view, so there's no way to tell
     which setting a given 4K value even belongs to. Needs an opaque
     background (matching the page background the table sits on) since
     sticky cells otherwise let the scrolling columns show through. */
  table.settings-table th:first-child, table.settings-table td:first-child {
    position: sticky; left: 0; background: var(--bg); border-right: 1px solid var(--border); z-index: 1;
  }

  .admin-wrap { padding: 18px 14px 60px; }
  .admin-topbar { flex-wrap: wrap; gap: 10px; }
  .form-grid { grid-template-columns: 1fr; }
  .settings-row-editor .row-grid { grid-template-columns: 1fr; }
  .admin-table { display: block; overflow-x: auto; }
}
