/* ---------------------------------------------------
   Game Shelf — tokens
--------------------------------------------------- */
:root {
  --bg:            #1c1917;
  --bg-panel:      #241f1c;
  --bg-elevated:   #2e2723;
  --border:        #3c332d;
  --border-soft:   #342c27;
  --text:          #f0e9e4;
  --text-muted:    #a89a8f;
  --text-faint:    #6e6259;

  --accent:        #d97757;
  --accent-hover:  #c8674a;
  --accent-soft:   rgba(217, 119, 87, 0.15);

  --owned:         #8bab6f;
  --sold:          #8f8478;
  --wished:        #d9a857;

  --danger:        #c0604f;

  --wood-back:     #4f3a2c;
  --wood-top:      #7a5a44;
  --wood-edge:     #8a6a52;
  --wood:          #4a3629;
  --wood-frame:    #5f4636;
  --wood-wall:     #2e2119; /* light enough for shadows on it to read */
  /* Woodgrain overlays: SVG fractal noise stretched along one axis (dark
     streaks with alpha up to ~0.4), tiled seamlessly (stitchTiles). -h is
     2000px wide (wider than any shelf): its sideways stitch still showed
     as vertical seams across the back wall at 600px. Layered
     on top of the wood gradients; -h for horizontal boards, -v for upright. */
  --grain-h: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='2000' height='160'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.003 0.22' numOctaves='4' seed='7' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.8 0 0 0 -0.28'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
  --grain-v: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='600'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.22 0.003' numOctaves='4' seed='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.8 0 0 0 -0.28'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");

  --label-paper:   #e9dfc9;
  --label-ink:     #3a2a1e;

  --radius:        6px;
  --radius-lg:     10px;

  --font-display:  'Fraunces', Georgia, serif;
  --font-body:     'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.5;
}

button, input, select, textarea {
  font-family: inherit;
  font-size: inherit;
  color: inherit;
}

/* iOS Safari auto-zooms the viewport when focusing a form field with a
   font-size under 16px, and doesn't reliably zoom back out on blur —
   especially inside a modal. Keeping these at 16px prevents that. */
input, select, textarea {
  font-size: 16px;
}

a { color: var(--accent); }

.text-muted { color: var(--text-muted); }

/* ---------------------------------------------------
   Topbar
--------------------------------------------------- */
.topbar {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--bg-panel);
  border-bottom: 1px solid var(--border);
}

/* Row 1: brand, page navigation, Add game */
.topbar-inner {
  max-width: 1800px;
  margin: 0 auto;
  padding: 14px 24px;
  display: flex;
  align-items: center;
  gap: 32px;
}

.brand {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 22px;
  margin: 0;
  letter-spacing: 0.2px;
  white-space: nowrap;
}
.brand a { color: inherit; text-decoration: none; }

.page-nav {
  display: flex;
  gap: 20px;
  align-self: stretch;
}

.page-link {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--text-muted);
  text-decoration: none;
  font-weight: 500;
  /* span the row's full height so the underline sits on its bottom edge */
  margin: -14px 0;
  border-bottom: 2px solid transparent;
}
.page-link:hover { color: var(--text); }
body.is-list-view .page-link[data-page="list"],
body.is-stats-view .page-link[data-page="stats"] {
  color: var(--text);
  border-bottom-color: var(--accent);
}

.icon {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex-shrink: 0;
}

.add-btn {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 6px;
}

/* Row 2: list filters — only shown in the list view */
.toolbar {
  display: none;
  border-top: 1px solid var(--border);
}
body.is-list-view .toolbar { display: block; }

.toolbar-inner {
  max-width: 1800px;
  margin: 0 auto;
  padding: 10px 24px;
  display: flex;
  align-items: center;
  gap: 12px;
}

.status-tabs {
  display: flex;
  gap: 4px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 3px;
}

.filter-select,
#filterInput {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 6px 10px;
  color: var(--text);
  font-size: 14px;
}
.filter-select { max-width: 200px; }

#filterInput {
  flex: 0 1 300px;
  min-width: 0;
}

/* "More filters" button + its dropdown panel */
.more-filters { position: relative; }

.more-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 6px 10px;
  font-size: 14px;
}
.more-btn.has-active { border-color: var(--accent); color: var(--accent); }
.more-label-short { display: none; }
.more-btn[aria-expanded="true"] .icon { transform: rotate(180deg); }

.more-panel {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 20;
  width: 300px;
  display: grid;
  gap: 12px;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 14px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
}
.more-panel[hidden] { display: none; }
.more-panel label { margin: 0; }

.year-range {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

#clearFiltersBtn { margin-left: auto; }

.link-btn {
  background: none;
  border: none;
  padding: 0;
  color: var(--accent);
  cursor: pointer;
  font-size: 13px;
  font-weight: 500;
  white-space: nowrap;
}
.link-btn:hover { text-decoration: underline; }
.link-btn[hidden] { display: none; }

.tab {
  background: none;
  border: none;
  color: var(--text-muted);
  padding: 6px 14px;
  border-radius: 4px;
  cursor: pointer;
  font-size: 13.5px;
  font-weight: 500;
}

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

.tab.active {
  background: var(--bg-elevated);
  color: var(--text);
}

.tab-count {
  color: var(--text-faint);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  margin-left: 3px;
}
.tab.active .tab-count { color: var(--text-muted); }

.filter-select:focus, #filterInput:focus, input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--accent);
}

/* ---------------------------------------------------
   Buttons
--------------------------------------------------- */
.btn {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 8px 16px;
  border-radius: var(--radius);
  cursor: pointer;
  font-weight: 500;
  white-space: nowrap;
}

.btn:hover { border-color: var(--text-faint); }

.btn-accent {
  background: var(--accent);
  border-color: var(--accent);
  color: #221a15;
}

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

.btn-danger {
  background: transparent;
  border-color: var(--danger);
  color: var(--danger);
}
.btn-danger:hover { background: rgba(192, 96, 79, 0.12); }

.icon-btn {
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 8px;
}
.icon-btn:hover { color: var(--text); }

/* ---------------------------------------------------
   Main / list view
--------------------------------------------------- */
main {
  max-width: 1800px;
  margin: 0 auto;
  padding: 24px;
}

.empty-state {
  text-align: center;
  padding: 80px 20px;
  color: var(--text-muted);
}
.empty-state h2 {
  font-family: var(--font-display);
  font-weight: 500;
  color: var(--text);
}

table.game-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--bg-panel);
}

.table-wrap {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.game-table thead th {
  text-align: left;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-muted);
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
}

.game-table thead th.sortable {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
.game-table thead th.sortable:hover { color: var(--text); }

.sort-arrow {
  color: var(--accent);
  font-size: 10px;
  margin-left: 2px;
}


.game-table tbody tr {
  border-bottom: 1px solid var(--border-soft);
  cursor: pointer;
}
.game-table tbody tr:last-child { border-bottom: none; }
.game-table tbody tr:hover { background: var(--bg-elevated); }

.game-table td {
  padding: 12px 16px;
  vertical-align: middle;
}

.game-title-cell {
  display: flex;
  align-items: center;
  gap: 12px;
  font-weight: 500;
}

.game-title-cell img {
  width: 36px;
  height: 36px;
  object-fit: cover;
  border-radius: 4px;
  background: var(--bg-elevated);
  flex-shrink: 0;
}

.status-pill {
  display: inline-block;
  font-size: 12px;
  font-weight: 600;
  padding: 2px 9px;
  border-radius: var(--radius);
}
.status-pill.owned  { background: rgba(139,171,111,0.15); color: var(--owned); }
.status-pill.sold   { background: rgba(143,132,120,0.18); color: var(--sold); }
.status-pill.wished { background: rgba(217,168,87,0.15);  color: var(--wished); }

.score-cell { font-variant-numeric: tabular-nums; color: var(--text-muted); }

/* Mobile card list (replaces table on small screens) */
.game-cards { display: none; flex-direction: column; gap: 10px; }

.game-card {
  display: flex;
  gap: 12px;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 12px;
  cursor: pointer;
}
.game-card img {
  width: 52px;
  height: 52px;
  object-fit: cover;
  border-radius: 6px;
  background: var(--bg-elevated);
  flex-shrink: 0;
}
.game-card .card-title {
  font-weight: 600;
  margin: 0 0 2px;
}
.game-card .card-meta {
  color: var(--text-muted);
  font-size: 13px;
  margin: 0;
}

/* ---------------------------------------------------
   Detail view
--------------------------------------------------- */
.back-link {
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  font-size: 14px;
  padding: 0 0 16px;
}
.back-link:hover { color: var(--text); }

.detail-view {
  max-width: 900px;
  margin: 0 auto;
}

.detail-header {
  display: flex;
  gap: 28px;
  margin-bottom: 28px;
}

.detail-cover {
  height: 200px;
  width: auto;
  max-width: 380px;
  object-fit: contain;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  background: var(--bg-panel);
  flex-shrink: 0;
}

.detail-header-info h2 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 30px;
  margin: 0 0 8px;
}

.detail-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 14px;
}
.badge {
  display: inline-block;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  color: var(--text);
  font-size: 13px;
  font-weight: 500;
  padding: 4px 13px;
  border-radius: var(--radius);
}

.fact-table {
  margin: 0;
}
.fact-row {
  display: grid;
  grid-template-columns: 90px 1fr;
  gap: 4px 10px;
  padding: 3px 0;
  font-size: 14px;
}
.fact-row dt {
  margin: 0;
  color: var(--text-muted);
}
.fact-row dd {
  margin: 0;
  color: var(--text);
  font-weight: 500;
}

.screenshots-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin-bottom: 28px;
}
.screenshots-row img {
  width: 100%;
  aspect-ratio: 16/9;
  object-fit: cover;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  background: var(--bg-panel);
}

.detail-section {
  margin-bottom: 28px;
}
.detail-section h3 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 17px;
  margin: 0 0 10px;
  color: var(--text);
}
.detail-section p { color: var(--text-muted); line-height: 1.65; }

.edit-panel {
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 20px;
}

.edit-panel .form-grid { margin-bottom: 16px; }

.edit-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}
.edit-panel-header h3 { margin: 0; }

.status-select-label {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-muted);
}

.status-select {
  display: inline-block;
  width: auto;
  margin-top: 0;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 6px 10px;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--text);
}

.save-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin-top: 8px;
  flex-wrap: wrap;
}

.save-row-primary {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

#saveStatusMsg {
  font-size: 13px;
  color: var(--owned);
  opacity: 0;
  transition: opacity 0.2s;
}
#saveStatusMsg.show { opacity: 1; }

/* ---------------------------------------------------
   Forms (shared: add modal + detail edit panel)
--------------------------------------------------- */
label {
  display: block;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-muted);
  margin-bottom: 14px;
}

label > input,
label > select,
label > textarea {
  display: block;
  width: 100%;
  margin-top: 6px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 9px 12px;
  color: var(--text);
}

textarea { resize: vertical; font-family: var(--font-body); }

.form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

.form-error {
  background: rgba(192, 96, 79, 0.12);
  border: 1px solid var(--danger);
  color: var(--danger);
  border-radius: var(--radius);
  padding: 10px 12px;
  font-size: 13.5px;
  margin-bottom: 16px;
}
.form-error[hidden] { display: none; }

.form-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 6px;
}

/* ---------------------------------------------------
   Modal (add game)
--------------------------------------------------- */
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(10, 9, 7, 0.6);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 40px 16px;
  z-index: 100;
  overflow-y: auto;
}
.modal-backdrop[hidden] { display: none; }

.modal {
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  width: 100%;
  max-width: 560px;
}

.modal-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 18px 22px;
  border-bottom: 1px solid var(--border);
}
.modal-head h2 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 19px;
  margin: 0;
}

.modal-body { padding: 22px; }

.search-row {
  display: flex;
  gap: 10px;
  margin-bottom: 14px;
}
.search-row input {
  flex: 1;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 9px 12px;
  color: var(--text);
}

.search-results {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 320px;
  overflow-y: auto;
}

.search-result {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px;
  border-radius: var(--radius);
  cursor: pointer;
}
.search-result:hover { background: var(--bg-elevated); }
.search-result img {
  width: 44px;
  height: 44px;
  object-fit: cover;
  border-radius: 4px;
  background: var(--bg-elevated);
  flex-shrink: 0;
}
.search-result .r-title { font-weight: 500; margin: 0; }
.search-result .r-meta { font-size: 12.5px; color: var(--text-muted); margin: 0; }

.add-form-header {
  display: flex;
  gap: 14px;
  align-items: center;
  margin-bottom: 18px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--border-soft);
}
.add-cover {
  width: 56px;
  height: 56px;
  object-fit: cover;
  border-radius: 6px;
  background: var(--bg-elevated);
}
#addTitle {
  font-family: var(--font-display);
  font-weight: 500;
  margin: 0 0 2px;
  font-size: 18px;
}
#addMeta { margin: 0; font-size: 13px; }

/* ---------------------------------------------------
   Shelf view
--------------------------------------------------- */
.shelves {
  /* Box size follows the shelf width (cqw), so every full row fills it. */
  container-type: inline-size;
  /* horizontal space that isn't boxes or gaps: casing side face (18 =
     --plank-depth), casing padding (32), shelf padding (40), plus 1px slack
     so sub-pixel rounding never wraps the last box */
  --shelf-inset: 91px;
  --plank: 12px;
  --depth: 7px;         /* how far the boxes recede (top/side faces) */
  --plank-depth: 18px;  /* how far the plank's top surface recedes behind them */
  --set-back: 10px;     /* boxes stand this far behind the plank's front edge;
                           at most --plank-depth - --depth, or they'd poke
                           through the back wall */
  --box-gap: 22px;      /* between boxes on a shelf */
  --shelf-gap: 46px; /* from a row's plank front to the next row's box tops, incl. headroom */
}

/* --cols boxes per row; width shares the shelf width, height follows the
   art (IGDB cover_big is 264×374). Set on .bookcase, not .shelves: cqw and
   @container only resolve against .shelves from inside it. Columns step so
   boxes stay roughly 120–160px wide (at the 1800px layout: 11 per row). */
.bookcase {
  --cols: 11;
  --box-w: calc((100cqw - var(--shelf-inset) - (var(--cols) - 1) * var(--box-gap)) / var(--cols));
  --box-h: calc(var(--box-w) * 374 / 264);
}
@container (max-width: 1630px) { .bookcase { --cols: 10; } }
@container (max-width: 1488px) { .bookcase { --cols: 9; } }
@container (max-width: 1346px) { .bookcase { --cols: 8; } }
@container (max-width: 1204px) { .bookcase { --cols: 7; } }
@container (max-width: 1062px) { .bookcase { --cols: 6; } }
@container (max-width: 920px)  { .bookcase { --cols: 5; } }
@container (max-width: 778px)  { .bookcase { --cols: 4; } }

/* The casing: wooden frame (crown, side posts, base) around a dark back
   wall, seen from the same angle as the boxes (above-right). It is as deep
   as the planks (--plank-depth), so the planks reach the back wall:
   - ::after is the casing's top surface, ::before its outer right side,
     both skewed 45° like the box faces;
   - inside, the left post's inner face shows as a strip receding to the
     back wall (the right post's inner face is hidden from this angle). */
.bookcase {
  position: relative;
  margin: var(--plank-depth) var(--plank-depth) 0 0; /* room for the top and side faces */
  padding: 16px 16px 22px;
  /* upright grain: the side posts are most of the visible frame */
  background:
    var(--grain-v),
    linear-gradient(to bottom, var(--wood-edge), var(--wood-frame) 4px, var(--wood) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.15),
    inset 0 -3px 0 rgba(0, 0, 0, 0.35),
    /* soft light from the top left: the casing's shadow falls down and to
       the right (past its side face), a tight one plus a wide, faint one */
    calc(var(--plank-depth) + 8px) 12px 18px rgba(0, 0, 0, 0.55),
    calc(var(--plank-depth) + 30px) 40px 70px rgba(0, 0, 0, 0.7);
}

.bookcase::before,
.bookcase::after {
  content: '';
  position: absolute;
  pointer-events: none;
}

/* Outer right side: in shadow */
.bookcase::before {
  top: 0;
  left: 100%;
  width: var(--plank-depth);
  height: 100%;
  transform: skewY(-45deg);
  transform-origin: left;
  background: var(--grain-v), linear-gradient(to right, var(--wood), var(--wood-wall));
  box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.08);
}

/* Top surface: lit, lighter towards the front edge */
.bookcase::after {
  left: 0;
  bottom: 100%;
  width: 100%;
  height: var(--plank-depth);
  transform: skewX(-45deg);
  transform-origin: bottom;
  background: var(--grain-h), linear-gradient(to top, var(--wood-edge), var(--wood-top) 30%, var(--wood-back));
}

.bookcase-back {
  /* inner face of the left post: in shade, darkening towards the back
     wall, with a thin lit edge where it turns from the post's front face */
  --post-face: linear-gradient(to right, var(--wood-edge) 0 1px, var(--wood) 1px, #2c2019 100%);
  background:
    var(--post-face) 0 0 / var(--plank-depth) 100% no-repeat,
    /* the post shades the back wall next to it */
    linear-gradient(to right, transparent var(--plank-depth),
      rgba(0, 0, 0, 0.75) var(--plank-depth),
      rgba(0, 0, 0, 0.35) calc(var(--plank-depth) + 10px),
      transparent calc(var(--plank-depth) + 34px)),
    var(--wood-wall);
  /* the crown shades the back wall below it */
  box-shadow: inset 0 26px 30px -12px rgba(0, 0, 0, 0.95);
}

/* Section label: a tag clipped to the front edge of the plank under the
   section's first row (the plank front starts --plank-front below the
   content top); the 17px tag starts 1px below the plank top and hangs past
   it. */
.shelf-tag {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 500;
  white-space: nowrap;
  color: var(--label-ink);
  position: absolute;
  z-index: 2;
  left: 20px;
  top: calc(var(--shelf-pad-top) + var(--plank-front) + 1px);
  height: 17px;
  padding: 1px 8px;
  font-size: 11px;
  line-height: 15px;
  background: var(--label-paper);
  border-radius: 1px 1px 2px 2px;
  box-shadow: 0 2px 3px rgba(0, 0, 0, 0.55), inset 0 0 0 1px rgba(0, 0, 0, 0.12);
}

.shelf-count {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  opacity: 0.6;
  margin-left: 3px;
}

/* Boxes wrap onto as many shelves as needed. The planks are a background
   tile (one box height + gap, repeated down from the content top) lined up
   with the fixed box height, so every row of boxes — including a half-full
   last row — stands on a full-width plank. The tile size must be explicit:
   sized to the content box, the last row's plank (which sits in the bottom
   padding) would be cut off.
   Sections stack directly: each shelf's bottom padding holds its last
   plank plus that plank's 8px wall shadow, and its top padding is the rest
   of the usual gap, so spacing is the same between and within sections.
   Each plank, top to bottom: its top surface receding by --plank-depth behind
   the boxes' bottoms (darker at the back), a lit front lip, the front
   edge, then a shadow on the wall below. */
.shelf {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  column-gap: var(--box-gap);
  row-gap: var(--shelf-gap);
  --plank-front: calc(var(--box-h) + var(--set-back)); /* where the front lip sits */
  --under-plank: calc(var(--plank-front) + var(--plank));
  /* soft shadow each plank casts down the wall (light from the top left).
     18px fits the space below a plank in every tile (≥ 19px on mobile);
     across sections it continues seamlessly, as the next section's top
     padding shows the rest of the same tile. */
  --plank-shadow:
    rgba(0, 0, 0, 0.7) var(--under-plank),
    rgba(0, 0, 0, 0.4) calc(var(--under-plank) + 5px),
    rgba(0, 0, 0, 0.15) calc(var(--under-plank) + 12px),
    transparent calc(var(--under-plank) + 18px);
  --shelf-pad-top: calc(var(--shelf-gap) - var(--set-back) - var(--plank) - 8px);
  position: relative;
  padding: var(--shelf-pad-top) 20px calc(var(--set-back) + var(--plank) + 8px);
  /* grain from the shelf's left edge, so its one 2000px-wide tile (wider
     than any shelf) never repeats sideways and the wall reads as one panel;
     planks from the content top */
  background-origin: border-box, content-box;
  background-clip: border-box;
  /* grain on top of the planks (it also lightly streaks the back wall, as
     a wooden back panel would be) */
  background-image: var(--grain-h), linear-gradient(to bottom,
    transparent 0 calc(var(--plank-front) - var(--plank-depth)),
    var(--wood-back) calc(var(--plank-front) - var(--plank-depth)),
    var(--wood-top) var(--plank-front),
    var(--wood-edge) var(--plank-front) calc(var(--plank-front) + 2px),
    var(--wood) calc(var(--plank-front) + 2px) var(--under-plank),
    var(--plank-shadow));
  /* 100% is the content width, so tile sideways too, or the planks would
     stop short of the casing by the horizontal padding */
  background-size: 2000px 160px, 100% calc(var(--box-h) + var(--shelf-gap));
  background-repeat: repeat;
}

/* The left post's inner face, painted over the whole strip so it reads as
   one continuous wall — except where a plank crosses it. No grain: the
   overlay restarts at every section, so a texture would show a seam at
   each section boundary (the face is in shade anyway). There, the plank's top surface must end in a 45° diagonal (front-left
   corner up to back-left corner) and its front edge runs in front of the
   wall. Two mask layers per plank tile, combined as a union:
   - above the diagonal (x + y < plank front; in a 135° gradient a stop at
     d marks the line x + y = d·√2),
   - below the plank's front edge (the wall again, with the plank's shadow
     repainted on it).
   Tiles are lined up with the plank tiles, which start at the content top. */
.shelf::before {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: var(--plank-depth);
  pointer-events: none;
  --tile: var(--plank-depth) calc(var(--box-h) + var(--shelf-gap));
  --diag: calc(var(--plank-front) * 0.70710678);
  background-image:
    linear-gradient(to bottom, transparent var(--under-plank), var(--plank-shadow)),
    var(--post-face);
  background-size: var(--tile), 100% 100%;
  background-position: 0 var(--shelf-pad-top), 0 0;
  background-repeat: repeat-y, no-repeat;
  -webkit-mask-image:
    linear-gradient(135deg, #000 var(--diag), transparent var(--diag)),
    linear-gradient(to bottom, transparent var(--under-plank), #000 var(--under-plank));
  mask-image:
    linear-gradient(135deg, #000 var(--diag), transparent var(--diag)),
    linear-gradient(to bottom, transparent var(--under-plank), #000 var(--under-plank));
  -webkit-mask-size: var(--tile);
  mask-size: var(--tile);
  -webkit-mask-repeat: repeat-y;
  mask-repeat: repeat-y;
  -webkit-mask-position: 0 var(--shelf-pad-top);
  mask-position: 0 var(--shelf-pad-top);
}

/* Each box is drawn as a case seen slightly from above-right: the cover is
   the front face, ::after is the top face and ::before the right side face,
   both skewed 45° and textured with the matching edge of the cover art
   (--cover, set inline). Not clipped (no overflow: hidden), so the faces
   can sit outside the box; the art itself carries the rounded corners. */
.game-box {
  --cover-fallback: linear-gradient(var(--bg-elevated), var(--bg-elevated));
  position: relative;
  width: var(--box-w);
  height: var(--box-h);
  padding: 0;
  border: none;
  border-radius: 2px;
  background: var(--bg-elevated);
  cursor: pointer;
  /* a tight contact line where the box meets the plank (anything lower
     darkens the plank in front of the box and makes it look like it
     floats) + a soft shadow on the back wall behind it */
  box-shadow:
    0 1px 1px rgba(0, 0, 0, 0.6),
    12px -2px 14px rgba(0, 0, 0, 0.75),
    24px 0 34px rgba(0, 0, 0, 0.5);
  transition: transform 0.15s;
}
.game-box:hover,
.game-box:focus-visible { transform: translateY(-6px); }
.game-box:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.game-box::before,
.game-box::after {
  content: '';
  position: absolute;
  pointer-events: none;
}

/* Right side: the cover's right edge, shaded */
.game-box::before {
  top: 0;
  left: 100%;
  width: var(--depth);
  height: 100%;
  transform: skewY(-45deg);
  transform-origin: left;
  background:
    linear-gradient(rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0.55)),
    var(--cover, var(--cover-fallback)) right / auto 100% no-repeat;
}

/* Top: the cover's top edge, lit from above */
.game-box::after {
  left: 0;
  bottom: 100%;
  width: 100%;
  height: var(--depth);
  transform: skewX(-45deg);
  transform-origin: bottom;
  background:
    linear-gradient(rgba(255, 255, 255, 0.12), rgba(0, 0, 0, 0.15)),
    var(--cover, var(--cover-fallback)) top / 100% auto no-repeat;
}

.game-box img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 2px;
}

/* Shrink-wrap sheen: a diagonal highlight plus a light catch on the left edge */
.box-gloss {
  position: absolute;
  inset: 0;
  border-radius: 2px;
  pointer-events: none;
  background: linear-gradient(115deg,
    rgba(255, 255, 255, 0.22) 0%,
    rgba(255, 255, 255, 0.06) 30%,
    rgba(255, 255, 255, 0) 45%,
    rgba(0, 0, 0, 0) 75%,
    rgba(0, 0, 0, 0.18) 100%);
  box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.18), inset 0 1px 0 rgba(255, 255, 255, 0.12);
}

.box-fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  padding: 10px;
  font-family: var(--font-display);
  font-size: 14px;
  line-height: 1.3;
  text-align: center;
  color: var(--text-muted);
  border: 1px solid var(--border);
  border-radius: 3px;
}

.box-tag {
  position: absolute;
  left: 50%;
  bottom: 8px;
  transform: translateX(-50%);
  font-size: 11px;
  font-weight: 600;
  padding: 1px 8px;
  border-radius: var(--radius);
  background: rgba(28, 25, 23, 0.85);
  white-space: nowrap;
}
.box-tag.wished { color: var(--wished); }
.box-tag.sold { color: var(--sold); }

/* Table / Shelf switch in the toolbar */
.view-toggle {
  display: flex;
  gap: 2px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 3px;
}
#clearFiltersBtn[hidden] + .view-toggle { margin-left: auto; }

.view-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  color: var(--text-muted);
  padding: 4px 8px;
  border-radius: 4px;
  cursor: pointer;
}
.view-btn:hover { color: var(--text); }
.view-btn.active { background: var(--bg-elevated); color: var(--text); }

/* ---------------------------------------------------
   Statistics view
--------------------------------------------------- */
.stats-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}
.stats-head h2 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 22px;
  margin: 0;
}

.stat-tiles {
  display: flex;
  gap: 10px;
}
.stat-tile {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 7px 14px;
  font-size: 13.5px;
}
.stat-tile-label { color: var(--text-muted); }
.stat-tile-value {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.stat-swatch {
  width: 10px;
  height: 10px;
  border-radius: 3px;
}
.stat-swatch.owned,  .bar-seg.owned,  .hbar-seg.owned  { background: var(--owned); }
.stat-swatch.wished, .bar-seg.wished, .hbar-seg.wished { background: var(--wished); }
.stat-swatch.sold,   .bar-seg.sold,   .hbar-seg.sold   { background: var(--sold); }

.chart-panel {
  --yaxis-w: 44px;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 28px 24px 16px 16px;
  overflow-x: auto;
}

.chart {
  display: flex;
  height: 460px;
  min-width: calc(var(--cols) * 56px + var(--yaxis-w));
}

.chart-yaxis {
  position: relative;
  width: var(--yaxis-w);
  flex-shrink: 0;
}
.chart-yaxis span {
  position: absolute;
  right: 10px;
  transform: translateY(50%);
  font-size: 12px;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}

.chart-plot {
  position: relative;
  flex: 1;
  border-left: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}

.chart-gridline {
  position: absolute;
  left: 0;
  right: 0;
  border-top: 1px solid var(--border-soft);
}

.chart-bars {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: repeat(var(--cols), 1fr);
  align-items: end;
}

.bar-col {
  height: 100%;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.bar-stack {
  position: relative;
  width: min(56%, 72px);
  display: flex;
  flex-direction: column-reverse; /* first series (Owned) sits at the bottom */
  border-radius: 4px 4px 0 0;
  overflow: visible;
}

.bar-seg {
  width: 100%;
  min-height: 2px;
  transition: filter 0.15s;
}
.bar-seg:last-child { border-radius: 4px 4px 0 0; }
.bar-stack:hover .bar-seg { filter: brightness(1.15); }

.bar-total {
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  padding-bottom: 4px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

.chart-xlabels {
  display: grid;
  grid-template-columns: repeat(var(--cols), 1fr);
  margin-left: var(--yaxis-w);
  min-width: calc(var(--cols) * 56px);
  padding-top: 10px;
}
/* Mobile chart: horizontal bars, one row per platform (shown < 760px) */
.hbar-chart {
  display: none;
  gap: 10px;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 14px;
}

.hbar-row {
  display: grid;
  grid-template-columns: minmax(0, 96px) 1fr;
  align-items: center;
  gap: 10px;
}

.hbar-label {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.hbar-track {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

.hbar {
  /* longest bar fills the track, leaving room for the total next to it */
  width: calc((100% - 36px) * var(--frac));
  height: 18px;
  display: flex; /* first series (Owned) sits on the left */
  border-radius: 0 4px 4px 0;
  overflow: hidden;
}

.hbar-seg {
  height: 100%;
  min-width: 2px;
}

.hbar-total {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

.bar-label {
  text-align: center;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding: 0 4px;
}

/* ---------------------------------------------------
   Responsive: mobile
--------------------------------------------------- */
@media (max-width: 760px) {
  .topbar {
    position: static; /* only the title/counter row would be worth pinning, and
                          that's not worth the header's added structural
                          complexity — the whole header just scrolls with the
                          page on mobile instead. */
  }

  /* Row 1: Statistics and Add game shrink to icon buttons; the brand
     doubles as the link back to the collection. */
  .topbar-inner {
    padding: 10px 16px;
    gap: 8px;
  }
  .nav-label,
  .page-link[data-page="list"] { display: none; }
  .page-nav { margin-left: auto; align-self: center; }
  .page-link,
  .add-btn {
    width: 38px;
    height: 38px;
    justify-content: center;
    padding: 0;
    margin: 0;
    border: 1px solid var(--border);
    border-radius: var(--radius);
  }
  .page-link { background: var(--bg-elevated); }
  body.is-stats-view .page-link[data-page="stats"] { border-color: var(--accent); color: var(--accent); }
  .icon { width: 18px; height: 18px; }

  /* Row 2: full-width status tabs, then search + platform, then Clear filters */
  .toolbar-inner {
    padding: 10px 16px 12px;
    flex-wrap: wrap;
    gap: 8px;
  }
  .status-tabs {
    width: 100%;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 2px;
    padding: 2px;
  }
  /* Label above count; WebKit needs the explicit width to fill the grid cell */
  .status-tabs .tab {
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 4px 2px;
    font-size: 12px;
    line-height: 1.3;
  }
  .tab-count { margin-left: 0; font-size: 11px; }

  /* 16px keeps iOS from zooming on focus */
  /* Search shares a line with the Table/Shelf switch; Platform, Genre and
     More filters share the next one in equal thirds (the 25% basis forces
     that line break). 16px keeps iOS from zooming on focus. */
  .filter-select, #filterInput, .more-btn { font-size: 16px; padding: 6px 8px; }
  #filterInput { order: 1; flex: 1 1 calc(100% - 96px); }
  .view-toggle { order: 2; margin-left: 0; }
  #clearFiltersBtn[hidden] + .view-toggle { margin-left: 0; }
  .view-btn { padding: 6px 9px; }
  .filter-select, .more-filters { order: 3; flex: 1 1 25%; min-width: 0; max-width: none; }
  .more-btn { width: 100%; white-space: nowrap; }
  .more-label-long { display: none; }
  .more-label-short { display: inline; }
  /* Panel spans the toolbar width instead of hanging off the button */
  .toolbar-inner { position: relative; }
  .more-filters { position: static; }
  .more-panel { left: 16px; right: 16px; top: calc(100% - 4px); width: auto; }
  #clearFiltersBtn { order: 4; width: 100%; text-align: right; }

  /* Exactly 3 boxes per row. Inset: bookcase frame (16), its outer side
     face (10 = --plank-depth), shelf padding (24), plus 2px slack. */
  .bookcase { --cols: 3; }
  .shelves {
    --shelf-inset: 52px;
    --box-gap: 14px;
    --depth: 4px;
    --plank-depth: 10px;
    --set-back: 5px;
    --shelf-gap: 36px;
  }
  .bookcase { padding: 8px 8px 14px; }
  .shelf { padding-left: 12px; padding-right: 12px; }
  .shelf-tag { left: 12px; }
  .box-tag { font-size: 10px; bottom: 5px; padding: 1px 6px; }

  main { padding: 16px; }

  .chart-panel { display: none; }
  .hbar-chart { display: grid; }
  .stats-head h2 { font-size: 18px; }
  .stat-tiles { flex-wrap: wrap; }

  table.game-table { display: none; }
  .table-wrap { display: none; }
  .game-cards { display: flex; }

  .detail-header { flex-direction: column; gap: 16px; }
  .detail-cover { width: 100%; height: auto; max-width: 320px; object-fit: contain; }
  .screenshots-row { grid-template-columns: 1fr; }
  .form-grid { grid-template-columns: 1fr; }

  .save-row { flex-direction: column; align-items: stretch; }
  .save-row-primary { flex-direction: column; align-items: stretch; }
  .save-row-primary .btn,
  .save-row > .btn-danger { width: 100%; }
  #saveStatusMsg { text-align: center; }
}

/* Respect reduced motion */
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}
