/* ============================================================
   LET'S PLAY PICO8 — production theme
   Tokens mirror the Paper file "PICO-CONSOLE - Retro 80s":
   palette = raw PICO-8 hex, roles = 1-level aliases max.
   Layout: TV-first console shelf (topbar / genres / grid+preview).
   ============================================================ */
:root {
  /* palette (raw PICO-8, never var()) */
  --color-black: #000000;
  --color-white: #ffffff;
  --color-dim: #c2c3c7;
  --color-muted: #83769c;
  --color-info: #29adff;
  --color-pink: #ff77a8;
  --color-green: #00e436;
  --color-orange: #ffa300;
  --color-peach: #ffccaa;
  --color-dark-grey: #5f574f;
  --color-dark-purple: #7e2553;
  --color-dark-green: #008751;
  --color-brown: #ab5236;
  --color-onyx: #291814;
  --color-midnight: #111d35;
  --color-eggplant: #49333b;
  --color-plum: #422136;
  --color-chocolate: #742f29;
  --color-forest: #125359;
  --color-beige: #a28879;
  --color-mauve: #754665;
  --color-royal: #065ab5;
  --color-jade: #00b543;
  --color-burgundy: #be1250;
  --color-pumpkin: #ff6c24;
  --color-lime: #a8e72e;
  --color-lemon: #f3ef7d;
  --color-coral: #ff6e59;
  --color-salmon: #ff9d81;

  /* roles */
  --bg: var(--color-black);
  --panel: var(--color-black);
  --ink: var(--color-white);
  --sub: var(--color-dim);
  --faint: var(--color-muted);
  --line: var(--color-midnight);
  --focus: var(--color-white);
  --action: var(--color-lime);
  --link: var(--color-info);
  --font-pixel: "Press Start 2P", "Courier New", ui-monospace, monospace;
  --font-body: "Azeret Mono", "Courier New", ui-monospace, monospace;
  /* TYPE SCALE — keep it here, nowhere else:
     pixel (Press Start 2P, 8px grid): 8 / 16 / 24 / 32 only, unsmoothed
     mono (Azeret Mono, small text): 16 / 20 only, smoothed */
  --gutter: 40px;
  --card-gap: 44px;
  --card: 256px;
}
body[data-grid="m"] { --card: 382px; }
body[data-grid="l"] { --card: 512px; }

* { box-sizing: border-box; }

html { background: var(--bg); overflow-x: clip; }

body {
  margin: 0;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 20px;
  line-height: 1.6;
}

/* crisp pixels only — mono body text stays smoothed */
.brand, .cat, .shoulder, .play-btn, .pv-title,
.player-title, .close-btn, .empty-title,
.player-stage .loading, .preview.is-empty .pv-title {
  -webkit-font-smoothing: none;
  font-smooth: never;
}

::selection { background: var(--focus); color: #000; }

/* ---------- top bar (fixed chrome: never scrolls) ---------- */
.topbar {
  flex: none;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 16px;
  padding: 20px var(--gutter);
  border-bottom: 2px solid var(--line);
  background: var(--bg);
}
/* segmented pill switches (grid size, player scale) */
.grid-switch, .scale-switch {
  display: flex;
  align-items: center;
  gap: 8px;
}
.grid-switch { margin-left: 8px; }
.scale-switch { margin-left: auto; }
.seg-label {
  font-family: var(--font-pixel);
  font-size: 8px;
  color: var(--faint);
}
.seg-btn {
  font-family: var(--font-pixel);
  font-size: 8px;
  padding: 10px 12px;
  background: transparent;
  color: var(--faint);
  border: 2px solid var(--line);
  border-radius: 999px;
  cursor: pointer;
  white-space: nowrap;
}
.seg-btn:hover { border-color: var(--faint); color: var(--ink); }
.seg-btn.active { border-color: var(--ink); color: var(--ink); }
.seg-btn:focus-visible { outline: 3px solid var(--ink); outline-offset: 3px; }
/* fullscreen toggle: same segmented pill language, far right of the topbar.
   Carries the pixel F-key glyph (ansdor sheet), kept in both input modes —
   there is no gamepad fullscreen glyph, and F is the hotkey everywhere. */
.fs-btn { flex: none; display: inline-flex; align-items: center; gap: 8px; }
.topbar .fs-btn { margin-left: 8px; }
.fs-btn.active { border-color: var(--action); color: var(--action); }
.player-top .fs-btn { flex: none; }
:root:fullscreen, :root:-webkit-full-screen { background: #000; }
body:fullscreen, body:-webkit-full-screen { background: var(--bg); }
.brand {
  font-family: var(--font-pixel);
  font-size: 20px;
  white-space: nowrap;
}
.brand-logo {
  height: 24px;
  width: auto;
  margin-right: 12px;
  image-rendering: pixelated;
  vertical-align: -6px;
}
.pad-status {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  color: var(--sub);
  font-size: 16px;
  white-space: nowrap;
}
.pad-status.on { color: var(--focus); }
/* legacy .pad-icon rule retired: #padIcon is now a .ico sprite (see below) */
.pad-status span {
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 32ch;
}

/* ---------- genre row (L1 | genres | R1) ---------- */
.genre-row {
  flex: none;
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 24px var(--gutter);
  border-bottom: 2px solid var(--line);
  background: var(--bg);
}
.cats {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  gap: 24px;
  padding: 0;
  border: 0;
}
/* shoulder bumpers: frameless icon-only buttons flanking the genres.
   Native tooltips only (title attr) — no custom ::after boxes. */
.shoulder {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 48px;
  min-height: 32px;
  padding: 6px;
  background: transparent;
  border: 0;
  border-radius: 0;
  cursor: pointer;
  align-self: center;
  opacity: 0.75;
}
.shoulder:hover { opacity: 1; }
/* full opacity once a real gamepad is connected (body.has-pad set by JS) */
body.has-pad .shoulder { opacity: 1; }
.shoulder:focus-visible { outline: 3px solid var(--ink); outline-offset: 3px; }
.cat {
  flex: 1 1 0;
  min-width: 0;
  font-family: var(--font-pixel);
  font-size: 20px;
  text-transform: uppercase;
  padding: 22px 8px;
  background: transparent;
  color: var(--faint);
  border: 0;
  border-radius: 0;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cat:hover { color: var(--ink); }
/* no frame: the active genre is plain white + underline */
.cat.active {
  background: transparent;
  border: 0;
  color: var(--ink);
  text-decoration: underline;
  text-decoration-thickness: 4px;
  text-underline-offset: 10px;
}
/* solid fill only while the genre row itself has keyboard focus */
.cats.focused .cat.active {
  background: var(--ink);
  border: 0;
  color: #000;
  text-decoration: none;
}
.cat:focus-visible { outline: 3px solid var(--ink); outline-offset: 3px; }

/* ---------- main split ---------- */
.layout {
  flex: 1 1 auto;
  display: flex;
  align-items: stretch;
  min-height: 0;
  min-width: 0;
}
/* the shelf is its own scroll region: header / genres / footer stay put */
.shelf-wrap {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  padding: var(--gutter);
  overflow-y: auto;
}

/* ---------- game grid ---------- */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, var(--card));
  justify-content: start;
  gap: 52px var(--card-gap);
}
/* layout containers never take visible focus — cards carry it */
.layout:focus,
.shelf-wrap:focus,
.grid:focus,
.preview:focus { outline: none; }
.card {
  appearance: none;
  background: transparent;
  border: 0;
  padding: 0;
  color: var(--ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
  min-width: 0;
}
.card-thumb {
  display: block;
  border: 8px solid transparent;
  border-bottom-width: 0;
  line-height: 0;
  background: #000;
}
.card-thumb img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  image-rendering: pixelated;
  display: block;
  background: #000;
}
.card-meta { padding: 14px 6px 16px; }
.card-title {
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 2;
  overflow-wrap: anywhere;
}
.card-author { color: var(--sub); font-size: 16px; }

/* mouse hover is visual only — never moves focus or the preview */
.card:hover .card-thumb { border-color: var(--faint); }
/* focused card: lime frame + lime info block, rounded corner */
.card.focused .card-thumb { border-color: var(--focus); }
.card.focused:hover .card-thumb { border-color: var(--focus); }
.card.focused .card-meta {
  background: var(--focus);
  color: #000;
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - 20px), calc(100% - 20px) 100%, 0 100%);
}
.card.focused .card-author { color: #000; }
.card:focus-visible { outline: 3px solid var(--ink); outline-offset: 4px; }

/* infinite-scroll sentinel (invisible) */
.sentinel { height: 2px; }

/* ---------- empty genre ---------- */
.empty { padding: 80px 20px; text-align: center; }
.empty.hidden { display: none; }
.hidden { display: none !important; }
.empty-title { font-family: var(--font-pixel); font-size: 16px; color: var(--sub); }
.empty-sub { color: var(--faint); }

/* ---------- preview panel ---------- */
.preview {
  flex: 0 0 clamp(440px, 33%, 592px);
  border-left: 2px solid var(--line);
  padding: var(--gutter);
  display: flex;
  flex-direction: column;
  gap: 22px;
  min-width: 0;
  min-height: 0;
  /* full-height panel with its own scroll: grid scrolls independently */
  align-self: stretch;
  overflow-y: auto;
}
.pv-media { line-height: 0; background: #000; }
.pv-media img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  image-rendering: pixelated;
  display: block;
  background: #000;
}
.play-btn {
  font-family: var(--font-pixel);
  font-size: 20px;
  padding: 26px 16px;
  background: var(--focus);
  color: #000;
  border: 0;
  border-radius: 0;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
}
/* PLAY carries a 2x glyph; on white it needs dark pixels */
.play-btn .ico { filter: invert(1); }
.play-btn:disabled .ico { filter: none; opacity: 0.5; }
.play-btn:hover { filter: brightness(1.08); }
.play-btn:disabled {
  background: transparent;
  color: var(--faint);
  border: 2px solid var(--line);
  cursor: default;
}
.play-btn:active { transform: translateY(2px); }
.play-btn:focus-visible { outline: 3px solid var(--ink); outline-offset: 3px; }
.pv-title {
  font-family: var(--font-pixel);
  font-size: 24px;
  line-height: 1.5;
  margin: 0;
  overflow-wrap: anywhere;
}
@media (min-width: 1400px) {
  .pv-title { font-size: 32px; }
}
.pv-by { color: var(--sub); font-size: 16px; }
.pv-pills { display: flex; flex-wrap: wrap; gap: 10px; }
.pill {
  font-size: 16px;
  padding: 4px 10px;
  border: 2px solid var(--faint);
  color: var(--sub);
}
.pill.lic { border-color: var(--link); color: var(--link); }
.pv-desc {margin: 0;font-size: 16px;line-height: 1.6;}
.pv-thread { color: var(--link); font-size: 16px; margin-top: auto; }

/* empty shelf: preview collapses to a single message */
.preview.is-empty { justify-content: center; }
.preview.is-empty .pv-media,
.preview.is-empty .play-btn,
.preview.is-empty .pv-by,
.preview.is-empty .pv-pills,
.preview.is-empty .pv-desc,
.preview.is-empty .pv-thread { display: none; }
.preview.is-empty .pv-title {
  text-align: center;
  font-size: 16px;
  line-height: 2;
  color: var(--sub);
}

/* ---------- scrollbars: chunky square natives, theme colors ----------
   Scoped to our scroll regions only. Firefox gets width + colors;
   WebKit gets the full square treatment. Gutter stays reserved so
   rows never shift when bars appear. */
.shelf-wrap, .preview, .layout {
  scrollbar-width: auto;
  scrollbar-color: var(--ink) #000;
  scrollbar-gutter: stable;
}
.shelf-wrap::-webkit-scrollbar,
.preview::-webkit-scrollbar,
.layout::-webkit-scrollbar { width: 12px; }
.shelf-wrap::-webkit-scrollbar-track,
.preview::-webkit-scrollbar-track,
.layout::-webkit-scrollbar-track {
  background: #000;
  border-left: 2px solid var(--line);
  border-radius: 0;
}
.shelf-wrap::-webkit-scrollbar-thumb,
.preview::-webkit-scrollbar-thumb,
.layout::-webkit-scrollbar-thumb {
  background: var(--ink);
  border: 2px solid #000;
  border-radius: 0;
}
.shelf-wrap::-webkit-scrollbar-corner,
.preview::-webkit-scrollbar-corner,
.layout::-webkit-scrollbar-corner { background: #000; border-radius: 0; }
.shelf-wrap::-webkit-scrollbar-button,
.preview::-webkit-scrollbar-button,
.layout::-webkit-scrollbar-button { display: none; }
.shelf-wrap::-webkit-scrollbar-thumb:hover,
.preview::-webkit-scrollbar-thumb:hover,
.layout::-webkit-scrollbar-thumb:hover { background: var(--action); }

/* ---------- help bar (fixed chrome: never scrolls) ---------- */
.helpbar {
  flex: none;
  z-index: 20;
  background: var(--bg);
  display: flex;
  gap: 28px;
  flex-wrap: wrap;
  padding: 16px var(--gutter);
  border-top: 2px solid var(--line);
  font-size: 16px;
}
.helpbar b { color: var(--ink); }
.helpbar .dim { color: var(--faint); }
/* ---------- pixel hint icons (ansdor 16x16 1-bit sprite sheets) ----------
   Always crisp 2x (32px): background-size locks the sheet to 2 * cell
   size; background-position is driven by cell coords (--cx/--cy,
   0-indexed) so no per-icon classes. image-rendering: pixelated keeps
   the 1-bit pixels sharp (no blur). */
.ico {
  display: inline-block;
  flex: none;
  width: 32px;
  height: 32px;
  background-repeat: no-repeat;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
  vertical-align: -9px;
}
.ico-kb {
  background-image: url("icons-keyboard-16x16-1bit-ansdor.webp");
  background-size: 384px 224px; /* 192x112 sheet @2x */
  background-position: calc(var(--cx, 0) * -32px) calc(var(--cy, 0) * -32px);
}
.ico-pad {
  background-image: url("icons-controller-16x16-1bit-ansdor.webp");
  background-size: 384px 192px; /* 192x96 sheet @2x */
  background-position: calc(var(--cx, 0) * -32px) calc(var(--cy, 0) * -32px);
}
/* icon groups in the footer: keep icons + verbs on one line */
.hint-kb, .hint-pad {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}
.hint-kb .sep, .hint-pad .sep { margin: 0 8px; color: var(--faint); }
/* shoulder pills + pad status now carry icons instead of letters */
.shoulder {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 48px;
  min-height: 32px;
}
#padIcon { width: 32px; height: 32px; opacity: 0.35; }
.pad-status.on #padIcon { opacity: 1; }
.hint-pad { display: none; }
body[data-input="gamepad"] .hint-kb { display: none; }
body[data-input="gamepad"] .hint-pad { display: inline-flex; }
/* input modality: hints jump between keyboard / gamepad sets */

/* ---------- player overlay ---------- */
.player {
  position: fixed;
  inset: 0;
  background: #000;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  z-index: 50;
}
.player.hidden { display: none; }
.player-top {
  flex: none;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 16px;
  padding: 14px 20px;
  border-bottom: 2px solid var(--line);
}
.player-title {
  font-family: var(--font-pixel);
  font-size: 16px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.close-btn {
  margin-left: auto;
  background: var(--action);
  color: #000;
  border: 0;
  font-family: var(--font-pixel);
  font-size: 8px;
  padding: 14px 18px;
  cursor: pointer;
}
.close-btn:focus-visible { outline: 3px solid var(--ink); outline-offset: 3px; }
.player-stage {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 12px;
  overflow: hidden;
}
/* integer-scaled pixels only — exact size set by applyScale() */
.player-stage canvas {
  width: 384px;
  height: 384px;
  background: #000;
  image-rendering: pixelated;
}
.player-stage .loading { color: var(--sub); font-size: 8px; }
.player-foot {
  flex: none;
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  padding: 12px 20px;
  color: var(--sub);
  font-size: 16px;
}
.player-foot a { color: var(--link); }

/* ---------- responsive ---------- */
@media (max-width: 1100px) {
  /* stacked: the whole split scrolls as one region */
  .layout { flex-direction: column; overflow-y: auto; }
  .shelf-wrap { overflow: visible; }
  .preview {
    flex-basis: auto;
    border-left: 0;
    border-top: 2px solid var(--line);
    overflow: visible;
  }
  .pv-thread { margin-top: 0; }
}
@media (max-width: 760px) {
  :root { --gutter: 20px; --card-gap: 24px; }
  .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .genre-row { gap: 12px; }
  .cats { flex-wrap: wrap; gap: 12px; }
  .cat { flex: 1 1 40%; }
}

@media (prefers-reduced-motion: reduce) {
  .play-btn:active { transform: none; }
}
