/* =====================================================================
   LIST PAGE (list.html) — also loaded by index.html for its card/
   body-texture reuse, see css/home.css's own header comment.
   ===================================================================== */

/* A faint diamond crosshatch across the whole viewport, fixed and pinned
   behind everything (negative z-index — paints above body's own radial
   gradient in css/base.css but below every actual element, so it never
   competes with real content) — pointercrate's list page has a similar
   bit of texture in its background instead of flat black. Only shows
   where nothing opaque sits on top of it, which in practice means the
   side gutters beyond the centered .page column and the gaps between
   cards — "the page has texture," not a pattern you consciously notice.
   Scoped to this file (loaded by list.html, and by index.html for its
   card-reusing spotlight section — see css/home.css) rather than
   base.css since it's not meant sitewide (level/stats/queue.html don't
   load list.css at all). */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    repeating-linear-gradient(45deg, color-mix(in srgb, var(--primary) 6%, transparent) 0 1px, transparent 1px 34px),
    repeating-linear-gradient(-45deg, color-mix(in srgb, var(--primary) 6%, transparent) 0 1px, transparent 1px 34px);
}

.list-hero {
  padding: 34px 0 22px;
  border-bottom: 1px solid var(--line-soft);
  margin-bottom: 26px;
}

.list-hero h1 {
  font-size: clamp(24px, 3.6vw, 34px);
  font-weight: 700;
  color: var(--text-hi);
  line-height: 1.15;
}
.list-hero p {
  margin-top: 10px;
  max-width: 640px;
  font-size: 13px;
  line-height: 1.6;
  color: var(--text-dim);
}

.controls-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 20px;
  align-items: center;
}

.search-box {
  flex: 1 1 220px;
  display: flex;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--line);
  background: var(--bg-surface);
  border-radius: var(--radius);
  padding: 9px 12px;
  transition: border-color .15s, box-shadow .15s;
}
.search-box:focus-within {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 18%, transparent);
}
.search-box input {
  flex: 1;
  background: none;
  border: none;
  color: var(--text-hi);
  font-size: 13.5px;
}
.search-box input:focus { outline: none; }
.search-box svg { flex-shrink: 0; color: var(--text-dim); }

.jump-box {
  display: flex;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--line);
  background: var(--bg-surface);
  border-radius: var(--radius);
  padding: 5px 5px 5px 12px;
  flex: 0 0 auto;
  transition: border-color .15s, box-shadow .15s;
}
.jump-box:focus-within {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 18%, transparent);
}
.jump-hash { color: var(--text-dim); font-family: ui-monospace, monospace; font-size: 13px; }
.jump-box input {
  width: 52px;
  background: none;
  border: none;
  color: var(--text-hi);
  font-size: 13.5px;
  font-family: ui-monospace, monospace;
}
.jump-box input:focus { outline: none; }
.jump-box input::-webkit-outer-spin-button,
.jump-box input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.jump-box .btn-ghost { padding: 6px 14px; font-size: 12px; }

/* A <select>, not a button, but styled to sit flush with the other
   btn-ghost controls in the row — appearance:none strips the native
   chrome (which ignores our colors on most platforms) in favor of a
   custom arrow drawn as a background SVG. color-scheme:dark keeps the
   *option list* dropdown dark too — that part can't be styled directly,
   it's OS-rendered, but the UA respects color-scheme for its palette. */
.view-toggle-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: var(--text-dim);
}

.legend {
  display: flex;
  gap: 14px;
  margin-top: 14px;
  flex-wrap: wrap;
  font-size: 11.5px;
  color: var(--text-dim);
}
.legend .swatch {
  width: 9px; height: 9px; border-radius: 2px; display: inline-block; margin-right: 5px;
}

/* Personal completion progress (js/completion.js) — purely local, no
   account behind it, so this is just a visual gut-check of how much of
   the tracked list a returning visitor has already marked beaten. Lives
   in the filter panel (next to "Hide completed") rather than the hero —
   it's a niche, personal number that read as visual noise sitting up
   front before you've marked anything. */
.completion-progress {
  position: relative;
  height: 20px;
  border-radius: 999px;
  background: var(--bg-surface-2);
  border: 1px solid var(--line);
  overflow: hidden;
}
.completion-progress:empty { display: none; }
.completion-fill {
  position: absolute;
  inset: 0;
  width: 0;
  background: linear-gradient(90deg, #16a34a, #4ade80);
  transition: width .5s cubic-bezier(.16,1,.3,1);
}
.completion-label {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .02em;
  color: var(--text-hi);
  text-shadow: 0 1px 3px rgba(0,0,0,.7);
}

/* --- the card grid: one page = 75 levels, laid out 5 columns x 15 rows
   at desktop width, degrading to fewer columns (more rows) on narrower
   screens — see the pager below for how pages are navigated. --- */
.demon-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 14px;
}
@media (min-width: 480px)  { .demon-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 700px)  { .demon-grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 940px)  { .demon-grid { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 1180px) { .demon-grid { grid-template-columns: repeat(5, 1fr); } }

.demon-card {
  position: relative;
  background: var(--bg-surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  display: flex;
  flex-direction: column;
  transition: transform .2s cubic-bezier(.16,1,.3,1), border-color .2s, box-shadow .2s;
  overflow: hidden;
  animation: card-in .5s cubic-bezier(.16,1,.3,1) both;
  animation-delay: calc(min(var(--i, 0), 24) * 16ms);
}

@keyframes card-in {
  from { opacity: 0; transform: translateY(16px) scale(.98); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

/* A thin bar in the level's difficulty color — gives every card a distinct
   identity at a glance instead of the whole grid reading as one flat gray. */
.demon-card::before {
  content: '';
  display: block;
  height: 3px;
  flex-shrink: 0;
  background: var(--tier-color, var(--primary));
}

.demon-card:hover {
  transform: translateY(-4px);
  border-color: var(--tier-color, var(--text-dim));
  box-shadow: 0 16px 32px -12px color-mix(in srgb, var(--tier-color, var(--primary)) 45%, transparent), var(--shadow-card);
}

.demon-card:has(.card-link:active) {
  transform: translateY(-1px) scale(.98);
  transition-duration: .08s;
}

.card-link {
  display: block;
  position: relative;
}

.card-thumb-wrap {
  position: relative;
  aspect-ratio: 16/9;
  background: var(--bg-void);
  overflow: hidden;
}
.card-thumb-wrap img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform 0.3s ease;
}
.demon-card:hover .card-thumb-wrap img { transform: scale(1.05); }

/* Darkens under the play badge on hover so it stays legible over bright thumbnails. */
.card-thumb-wrap::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(0,0,0,0.5), rgba(0,0,0,0) 60%);
  opacity: 0;
  transition: opacity .3s ease;
  pointer-events: none;
}
.demon-card:hover .card-thumb-wrap::after { opacity: 1; }

.play-badge {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(10,10,10,0.6);
  border: 1px solid rgba(255,255,255,0.25);
  backdrop-filter: blur(3px);
  color: var(--tier-color, var(--primary));
  opacity: 0;
  transform: translate(-50%, -50%) scale(.7);
  transition: opacity .25s ease, transform .3s cubic-bezier(.16,1,.3,1), background-color .2s ease;
  pointer-events: none;
}
.play-badge svg {
  width: 18px;
  height: 18px;
  margin-left: 2px;
  filter: drop-shadow(0 0 6px var(--tier-color, var(--primary)));
}
.demon-card:hover .play-badge {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
  background: rgba(10,10,10,0.75);
}

.card-rank {
  position: absolute;
  top: 8px;
  left: 8px;
  font-size: 12px;
  font-weight: 700;
  padding: 4px 9px 3px;
  background: rgba(10,10,10,0.78);
  color: var(--tier-color, var(--primary));
  border: 1px solid var(--tier-color, var(--primary));
  border-radius: 5px;
  backdrop-filter: blur(3px);
  box-shadow: 0 0 10px -1px var(--tier-color, var(--primary));
}

/* Personal "beaten this?" toggle (js/completion.js) — bottom-right of the
   thumbnail in card mode (top-left is already .card-rank, top-right the
   .new-ribbon), an inline flex item at the start of the row in list mode. */
.complete-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(10,10,10,0.78);
  border: 1px solid rgba(255,255,255,0.3);
  color: rgba(255,255,255,0.55);
  backdrop-filter: blur(3px);
  cursor: pointer;
  transition: background .15s, border-color .15s, color .15s, transform .12s;
}
.complete-toggle:hover { transform: scale(1.1); border-color: #4ade80; color: #4ade80; }
.complete-toggle[aria-pressed="true"] {
  background: #22c55e;
  border-color: #22c55e;
  color: #06210f;
}
.card-thumb-wrap .complete-toggle {
  position: absolute;
  bottom: 8px;
  right: 8px;
  width: 26px;
  height: 26px;
  z-index: 2;
}
.demon-row .complete-toggle {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
}
.demon-card.completed .card-thumb-wrap { outline: 2px solid #4ade80; outline-offset: -2px; }
.demon-row.completed { border-left-color: #4ade80; }

/* Card-mode "New" tag: a diagonal ribbon across the thumbnail's top-right
   corner (classic "Sale" sticker look) rather than a plain badge — the
   thumbnail's own overflow:hidden clips it to a clean diagonal edge on
   both sides, no extra masking needed. Sized/rotated for this card's
   fixed 16:9 thumb-wrap specifically; not reused as-is at other sizes,
   see .new-badge (css/base.css) for the plain inline version used
   everywhere a ribbon wouldn't fit (list mode, the detail page, the
   home page's spotlight cards). */
.new-ribbon {
  position: absolute;
  top: 14px;
  right: -34px;
  width: 130px;
  padding: 4px 0 3px;
  background: var(--badge-color, var(--primary));
  color: var(--badge-color-on, var(--primary-on, #1a0d00));
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-align: center;
  transform: rotate(45deg);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
  outline: 1px solid rgba(255, 255, 255, 0.25);
  outline-offset: -1px;
  pointer-events: none;
}
.card-title .new-badge {
  display: inline-block;
  margin-left: 6px;
  font-size: 9px;
  padding: 2px 6px 1px;
  vertical-align: middle;
  transform: translateY(-1px);
}

.card-body {
  padding: 12px 14px 13px;
}

.card-title {
  font-size: 16px;
  font-weight: 700;
  color: var(--text-hi);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.card-meta {
  margin-top: 5px;
  font-size: 12px;
  color: var(--text-dim);
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.card-meta strong { color: var(--text-mid); font-weight: 500; }

/* --- view count comparison, side by side --- */
.view-compare {
  margin-top: 11px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
}

.view-stat {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 8px;
  border-radius: 6px;
  background: var(--bg-surface-2);
  border: 1px solid var(--line-soft);
  min-width: 0;
}

.view-stat .dot {
  width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0;
}
.view-stat.verifier .dot { background: var(--text-mid); }
.view-stat.showcase .dot { background: var(--primary); }

.view-stat .stat-text {
  min-width: 0;
  overflow: hidden;
}
.view-stat .stat-label {
  font-size: 9px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-dim);
  display: block;
}
.view-stat .stat-value {
  font-family: ui-monospace, monospace;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-hi);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: block;
}
.view-stat.leader .stat-value { color: var(--gold); }
.view-stat.leader { border-color: rgba(255,207,74,0.35); animation: leader-pop .3s ease; }
@keyframes leader-pop {
  0%   { transform: scale(1); }
  50%  { transform: scale(1.05); }
  100% { transform: scale(1); }
}

.view-stat .stat-value.loading { color: var(--text-dim); }
.view-stat .stat-value.na { color: var(--text-dim); }

/* --- "List" display mode (Settings > Level display) — a dense AREDL-style
   row list instead of thumbnail cards. Reuses .demon-card as the root
   element (same hover/entrance-animation base, same hydration hooks —
   see cardTemplate()/hydrateCards() in js/list.js) so only what actually
   differs between the two layouts needs its own rules here. --- */
.demon-grid.view-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.demon-row::before { display: none; } /* the card grid's top color bar becomes a left edge stripe instead, below */
.demon-row {
  border-left: 3px solid var(--tier-color, var(--primary));
}
.demon-row:hover {
  transform: translateX(3px);
  border-color: var(--tier-color, var(--text-dim));
  border-left-color: var(--tier-color, var(--primary));
  box-shadow: 0 4px 16px -8px color-mix(in srgb, var(--tier-color, var(--primary)) 45%, transparent), var(--shadow-card);
}
.demon-row .card-link {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 14px;
}
.row-rank {
  flex: 0 0 40px;
  font-family: ui-monospace, monospace;
  font-weight: 700;
  font-size: 13px;
  color: var(--tier-color, var(--primary));
  text-align: right;
}
.row-thumb {
  flex: 0 0 auto;
  width: 68px;
  aspect-ratio: 16/9;
  border-radius: 4px;
  overflow: hidden;
  background: var(--bg-void);
}
.row-thumb img { width: 100%; height: 100%; object-fit: cover; }
.row-title { flex: 1 1 auto; min-width: 0; }
.row-title .card-title { font-size: 14px; }
.row-meta {
  flex-direction: row;
  gap: 16px;
  margin-top: 3px;
}
.row-meta span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.row-stats {
  flex: 0 0 auto;
  margin-top: 0;
  grid-template-columns: repeat(2, minmax(120px, 1fr));
}
@media (max-width: 720px) {
  .row-meta { display: none; }
  .row-stats { grid-template-columns: 1fr; gap: 4px; }
}
@media (max-width: 480px) {
  .row-stats { display: none; }
}

.pager-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  margin-top: 30px;
}

.pager-status {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--text-mid);
  font-family: ui-monospace, monospace;
}
.pager-status input {
  width: 52px;
  text-align: center;
  padding: 6px 4px;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--bg-surface);
  color: var(--text-hi);
  font-family: inherit;
  font-size: inherit;
}
.pager-status input:focus { outline: 2px solid var(--primary); outline-offset: 1px; }
.pager-status input::-webkit-outer-spin-button,
.pager-status input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

.empty-state {
  text-align: center;
  padding: 60px 20px;
  color: var(--text-dim);
  font-size: 13.5px;
}

/* skeleton cards while loading */
.demon-card.skeleton-card { padding: 0; }
.demon-card.skeleton-card .card-thumb-wrap { }
.sk-line { height: 12px; margin: 8px 14px; }
.sk-line.w60 { width: 60%; }
.sk-line.w40 { width: 40%; }
