/* ════════════════════════════════════════════════════════════
   D10 LEAKS — packs catalogue

   Layered on legal.css, which supplies the tokens, nav, page shell,
   footer and player. Everything below is the catalogue itself.

   The look matches the pricing page: real glass (blurred backdrop +
   a top-lit sheen over it), a masked gradient hairline instead of a
   flat 1px border, and a cursor spotlight driven through the CSSOM
   so the page's CSP is unaffected.
   ════════════════════════════════════════════════════════════ */

/* Three-up grid needs more than the 800px reading measure legal.css sets,
   so the page opts wider while running text stays capped. */
.page-wrap--wide { max-width: 1180px; }
.page-wrap--wide > p { max-width: 74ch; }

/* ── hero stats ──────────────────────────────────────────────────
   Filled by packs.js once the catalogue lands. Before that the numbers
   are placeholder dots, so the row never jumps in and shoves the grid
   down after paint. */
.pk-stats {
  margin: 26px 0 0;
  display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
.pk-stat {
  position: relative; overflow: hidden;
  padding: 16px 18px; border-radius: 14px;
  border: 1px solid rgba(255,255,255,.07);
  background:
    linear-gradient(180deg, rgba(255,255,255,.05) 0%, rgba(255,255,255,.012) 55%, rgba(255,255,255,0) 100%),
    rgba(13,14,19,.5);
  backdrop-filter: blur(18px) saturate(140%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.07), 0 18px 40px -26px rgba(0,0,0,.9);
}
.pk-stat-n {
  display: block;
  font-family: 'Unbounded', sans-serif; font-weight: 200;
  font-size: 1.7rem; line-height: 1; letter-spacing: -.02em; color: var(--silver);
}
.pk-stat-l {
  display: block; margin-top: 8px;
  font-family: 'IBM Plex Mono', monospace; font-size: .6rem;
  letter-spacing: .2em; text-transform: uppercase; color: var(--muted);
}
/* The live tile gets a pulsing dot, so "updated live" is shown rather
   than only claimed. */
.pk-stat--live .pk-stat-n { display: flex; align-items: center; gap: 10px; font-size: 1.05rem; color: var(--silver); }
.pk-dot {
  width: 8px; height: 8px; border-radius: 50%; background: var(--red);
  box-shadow: 0 0 0 0 rgba(255,20,40,.6);
  animation: pkPulse 2.4s var(--ease) infinite;
}
@keyframes pkPulse {
  70%  { box-shadow: 0 0 0 9px rgba(255,20,40,0); }
  100% { box-shadow: 0 0 0 0 rgba(255,20,40,0); }
}

/* ── filters ─────────────────────────────────────────────────── */
.pk-filters { display: flex; flex-wrap: wrap; gap: 8px; margin: 22px 0 4px; }
.pk-filter {
  font-family: 'IBM Plex Mono', monospace; font-size: 10px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--muted);
  background: rgba(255,255,255,.03);
  border: 1px solid rgba(233,234,239,.12); border-radius: 999px;
  padding: 9px 17px; cursor: pointer;
  transition: color .3s var(--ease), border-color .3s var(--ease),
              background .3s var(--ease), box-shadow .3s var(--ease);
}
.pk-filter:hover { color: var(--silver); border-color: rgba(255,255,255,.22); background: rgba(255,255,255,.055); }
.pk-filter.on {
  color: #fff; border-color: rgba(255,20,40,.55);
  background: linear-gradient(180deg, rgba(255,20,40,.22), rgba(255,20,40,.08));
  box-shadow: 0 0 0 1px rgba(255,20,40,.12), 0 10px 26px -14px rgba(255,20,40,.8);
}

/* ── groups ──────────────────────────────────────────────────── */
.pk-group { margin-top: 44px; }
.pk-group-head {
  display: flex; align-items: baseline; gap: 14px;
  padding-bottom: 12px; border-bottom: 1px solid var(--line);
}
.pk-group-title {
  position: relative; padding-left: 15px;
  font-family: 'Unbounded', sans-serif; font-weight: 200; font-size: 22px;
  color: var(--silver); margin: 0; letter-spacing: -.01em;
}
/* Small red tick beside the heading, the same accent the nav uses. */
.pk-group-title::before {
  content: ''; position: absolute; left: 0; top: .18em; bottom: .18em;
  width: 2px; border-radius: 2px;
  background: linear-gradient(180deg, var(--red), rgba(255,20,40,0));
}
.pk-group-count {
  font-family: 'IBM Plex Mono', monospace; font-size: 10px;
  letter-spacing: .2em; text-transform: uppercase; color: var(--muted);
}

.pk-row {
  display: grid; gap: 18px; margin-top: 20px;
  grid-template-columns: repeat(auto-fill, minmax(248px, 1fr));
}

/* ── card ────────────────────────────────────────────────────── */
.pk-card {
  position: relative; isolation: isolate;
  display: flex; flex-direction: column; overflow: hidden;
  border-radius: 18px;
  border: 1px solid rgba(255,255,255,.075);
  background:
    linear-gradient(180deg, rgba(255,255,255,.05) 0%, rgba(255,255,255,.012) 46%, rgba(255,255,255,0) 100%),
    rgba(13,14,19,.52);
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.08),      /* lit top edge */
    inset 0 -1px 0 rgba(0,0,0,.42),           /* grounded bottom edge */
    0 22px 50px -24px rgba(0,0,0,.85);
  text-decoration: none; color: inherit;
  transition: transform .5s var(--ease), box-shadow .5s var(--ease), border-color .5s var(--ease);
}

/* Hairline that catches light unevenly, like a real edge. The two-layer
   mask cuts the fill out of the middle, leaving only the 1px ring. */
.pk-card::before {
  content: ''; position: absolute; inset: 0; border-radius: inherit; padding: 1px;
  background: linear-gradient(148deg, rgba(255,255,255,.26) 0%, rgba(255,255,255,0) 38%, rgba(255,20,40,.28) 94%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  pointer-events: none; opacity: .8; z-index: 3;
  transition: opacity .5s var(--ease);
}

/* Cursor spotlight. packs.js writes --mx/--my through the CSSOM, not a
   style attribute, so script-src/style-src stay clean. */
.pk-card::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none; z-index: 2;
  background: radial-gradient(300px circle at var(--mx, 50%) var(--my, 0%), rgba(255,20,40,.15), transparent 62%);
  opacity: 0; transition: opacity .45s var(--ease);
}

a.pk-card:hover {
  /* legal.css dims and underlines every <a> on hover. A card is a tile, not a
     line of text: dimming it fights the lift and the underline looks broken. */
  opacity: 1; text-decoration: none;
  transform: translateY(-6px);
  border-color: rgba(255,255,255,.12);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.13),
    inset 0 -1px 0 rgba(0,0,0,.42),
    0 34px 68px -26px rgba(0,0,0,.92),
    0 0 0 1px rgba(255,20,40,.16);
}
a.pk-card:hover::before { opacity: 1; }
a.pk-card:hover::after  { opacity: 1; }
/* Keyboard users get the same treatment as the mouse. */
a.pk-card:focus-visible {
  outline: none; transform: translateY(-6px);
  box-shadow: 0 0 0 2px rgba(255,20,40,.6), 0 34px 68px -26px rgba(0,0,0,.92);
}

/* ── media ───────────────────────────────────────────────────── */
.pk-media { position: relative; aspect-ratio: 16/9; overflow: hidden; background: #0a0b0f; }
.pk-media img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform .8s var(--ease), filter .6s var(--ease);
  filter: saturate(.92);
}
a.pk-card:hover .pk-media img { transform: scale(1.06); filter: saturate(1.05); }

/* Scrim so the overlaid pills stay readable over any thumbnail, however
   bright, and the image dissolves into the card instead of ending on a line. */
.pk-media::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(180deg, rgba(0,0,0,.5) 0%, rgba(0,0,0,0) 34%, rgba(0,0,0,.06) 62%, rgba(13,14,19,.92) 100%);
}

/* Listings with no thumbnail still get a tile, so the grid stays even
   instead of going ragged wherever a seller skipped the preview. */
.pk-media--void { display: grid; place-items: center; background: radial-gradient(120% 100% at 50% 0%, rgba(255,20,40,.14), rgba(10,11,15,0) 62%), #0a0b0f; }
.pk-void-txt {
  font-family: 'Unbounded', sans-serif; font-weight: 200; font-size: 15px;
  letter-spacing: .16em; text-transform: uppercase; color: rgba(233,234,239,.16);
}

.pk-tag, .pk-pill {
  position: absolute; z-index: 2;
  font-family: 'IBM Plex Mono', monospace;
  border-radius: 999px; white-space: nowrap;
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
}
.pk-tag {
  top: 11px; left: 11px; padding: 5px 11px;
  font-size: 8.5px; letter-spacing: .18em; text-transform: uppercase;
  color: var(--silver);
  background: rgba(10,11,15,.55); border: 1px solid rgba(255,255,255,.14);
}
/* Price rides the artwork rather than the body: it is the thing people
   scan for, and on the image it reads first. */
.pk-pill {
  bottom: 11px; right: 11px; padding: 7px 13px;
  font-size: 12px; font-weight: 400; letter-spacing: .02em; color: #fff;
  background: rgba(255,20,40,.86); border: 1px solid rgba(255,255,255,.2);
  box-shadow: 0 10px 26px -12px rgba(255,20,40,.9);
}
.pk-pill--ask {
  background: rgba(10,11,15,.62); border-color: rgba(255,255,255,.16);
  color: var(--mid); font-size: 9.5px; letter-spacing: .16em; text-transform: uppercase;
  box-shadow: none;
}

/* ── body ────────────────────────────────────────────────────── */
.pk-body { position: relative; z-index: 2; display: flex; flex-direction: column; gap: 8px; padding: 16px 18px 15px; }
.pk-name {
  font-family: 'Space Grotesk', sans-serif; font-size: 15px; font-weight: 500;
  color: var(--silver); line-height: 1.35; word-break: break-word;
  transition: color .3s var(--ease);
}
a.pk-card:hover .pk-name { color: #fff; }
.pk-seller { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .1em; color: var(--muted); }

/* Footer row of the card: label left, arrow right. The arrow nudges on
   hover, which is enough of a cue without an extra button. */
.pk-go {
  margin-top: 6px; padding-top: 12px;
  border-top: 1px solid rgba(233,234,239,.08);
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  font-family: 'IBM Plex Mono', monospace; font-size: 8.5px;
  letter-spacing: .22em; text-transform: uppercase;
  color: var(--muted); transition: color .3s var(--ease);
}
a.pk-card:hover .pk-go { color: var(--red); }
.pk-go svg { width: 13px; height: 13px; flex: 0 0 auto; transition: transform .4s var(--ease); }
a.pk-card:hover .pk-go svg { transform: translateX(4px); }

/* ── skeletons ───────────────────────────────────────────────────
   Shown while /api/catalog is in flight. The grid is laid out before the
   data lands, so nothing reflows underneath the reader when it does. */
.pk-skel { pointer-events: none; }
/* No scrim over a placeholder: it would flatten the shimmer at the bottom. */
.pk-skel .pk-media::after { display: none; }
.pk-skel .pk-media, .pk-skel .pk-line {
  background: linear-gradient(100deg, rgba(255,255,255,.035) 30%, rgba(255,255,255,.075) 50%, rgba(255,255,255,.035) 70%);
  background-size: 220% 100%;
  animation: pkShimmer 1.5s linear infinite;
}
.pk-line { height: 11px; border-radius: 5px; }
.pk-line--sm { width: 42%; height: 8px; }
@keyframes pkShimmer { to { background-position: -220% 0; } }

/* ── entrance ────────────────────────────────────────────────────
   .js-anim is set by packs.js, so with JS off or broken the cards are
   simply visible instead of stranded at opacity 0. */
.js-anim .pk-card:not(.pk-skel) {
  opacity: 0; transform: translateY(20px) scale(.99);
  transition: opacity .7s var(--ease), transform .7s var(--ease),
              box-shadow .5s var(--ease), border-color .5s var(--ease);
}
.js-anim .pk-card.in { opacity: 1; transform: none; }
/* Stagger across each row so it assembles rather than snapping in. Capped
   at six: past that the delay is longer than anyone waits. */
.js-anim .pk-card:nth-child(1) { transition-delay: .00s; }
.js-anim .pk-card:nth-child(2) { transition-delay: .05s; }
.js-anim .pk-card:nth-child(3) { transition-delay: .10s; }
.js-anim .pk-card:nth-child(4) { transition-delay: .15s; }
.js-anim .pk-card:nth-child(5) { transition-delay: .20s; }
.js-anim .pk-card:nth-child(6) { transition-delay: .25s; }
/* The delay is for the first paint only; on hover it would make the lift
   feel laggy, so it is dropped once the card is in. */
.js-anim .pk-card.in:hover { transition-delay: 0s; }

/* ── empty / no matches ──────────────────────────────────────── */
.pk-empty {
  margin-top: 34px; padding: 34px; text-align: center;
  border: 1px dashed rgba(233,234,239,.16); border-radius: 18px; color: var(--muted);
}
.pk-none { margin-top: 40px; text-align: center; color: var(--muted); font-size: 15px; }

.pk-cta {
  display: inline-flex; align-items: center; justify-content: center;
  margin-top: 16px; padding: 13px 26px;
  font-family: 'IBM Plex Mono', monospace; font-size: 11px;
  letter-spacing: .22em; text-transform: uppercase; color: #fff;
  text-decoration: none; border-radius: 999px;
  border: 1px solid rgba(255,20,40,.6);
  background: linear-gradient(180deg, rgba(255,20,40,.2), rgba(255,20,40,.06));
  transition: background .35s var(--ease), box-shadow .35s var(--ease), transform .35s var(--ease);
}
.pk-cta:hover {
  opacity: 1; text-decoration: none;
  background: linear-gradient(180deg, rgba(255,20,40,.34), rgba(255,20,40,.14));
  box-shadow: 0 14px 34px -16px rgba(255,20,40,.9);
  transform: translateY(-2px);
}
.pk-cta--ghost { border-color: rgba(233,234,239,.2); color: var(--mid); background: rgba(255,255,255,.02); }
.pk-cta--ghost:hover { background: rgba(255,255,255,.06); color: var(--silver); box-shadow: none; opacity: 1; text-decoration: none; }

/* ── footer CTA ──────────────────────────────────────────────────
   The catalogue only carries what sellers listed, so make it obvious
   Discord has more rather than letting the page read as the inventory. */
.pk-foot {
  position: relative; overflow: hidden;
  margin: 62px 0 10px; padding: 40px 30px; text-align: center;
  border-radius: 20px; border: 1px solid rgba(255,255,255,.075);
  background:
    linear-gradient(180deg, rgba(255,255,255,.05) 0%, rgba(255,20,40,.03) 50%, rgba(255,255,255,0) 100%),
    rgba(13,14,19,.5);
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.08), 0 26px 60px -30px rgba(0,0,0,.9);
}
/* Soft red bloom behind the copy, so the block has a light source. */
.pk-foot::before {
  content: ''; position: absolute; left: 50%; top: -60%;
  width: 620px; height: 300px; translate: -50% 0; pointer-events: none;
  background: radial-gradient(closest-side, rgba(255,20,40,.16), transparent 72%);
}
.pk-foot > * { position: relative; }
.pk-foot h2 {
  font-family: 'Unbounded', sans-serif; font-weight: 200; font-size: 24px;
  color: var(--silver); margin: 0 0 10px; letter-spacing: -.01em;
}
.pk-foot p { color: var(--muted); max-width: 52ch; margin: 0 auto; line-height: 1.7; font-size: 15px; }
.pk-foot-actions { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; margin-top: 24px; }

/* ── search + sort ───────────────────────────────────────────────
   One row on every screen. Both controls share a fixed height so they
   line up exactly rather than drifting apart as their padding changes.
   Search takes the free space; sort stays as wide as its content. */
.pk-controls { display: flex; gap: 10px; align-items: center; margin-top: 30px; flex-wrap: nowrap; }

.pk-search { position: relative; flex: 1 1 auto; min-width: 0; display: flex; align-items: center; }
.pk-search-ico { position: absolute; left: 15px; width: 15px; height: 15px; color: var(--muted); pointer-events: none; z-index: 1; transition: color .25s var(--ease); }
.pk-search:focus-within .pk-search-ico { color: var(--red); }
.pk-search input {
  box-sizing: border-box; width: 100%; height: 46px;
  background: rgba(255,255,255,.028); color: var(--silver);
  border: 1px solid rgba(233,234,239,.12); border-radius: 999px;
  padding: 0 38px 0 40px;
  font-family: 'Space Grotesk', sans-serif; font-size: 14px; outline: none;
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  transition: border-color .3s var(--ease), background .3s var(--ease), box-shadow .3s var(--ease);
}
.pk-search input::placeholder { color: #6d6e78; }
.pk-search input:focus {
  border-color: rgba(255,20,40,.5); background: rgba(255,255,255,.05);
  box-shadow: 0 0 0 3px rgba(255,20,40,.09);
}
/* Safari draws its own clear button on type=search; we supply our own. */
.pk-search input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
.pk-clear {
  position: absolute; right: 11px; z-index: 1;
  background: none; border: 0; color: var(--muted);
  font-size: 18px; line-height: 1; cursor: pointer; padding: 4px 7px; border-radius: 50%;
  transition: color .25s var(--ease), background .25s var(--ease);
}
.pk-clear:hover { color: var(--silver); background: rgba(255,255,255,.07); }

.pk-sort {
  box-sizing: border-box; flex: 0 0 auto; height: 46px;
  display: flex; align-items: center; gap: 8px;
  background: rgba(255,255,255,.028);
  border: 1px solid rgba(233,234,239,.12); border-radius: 999px; padding: 0 16px;
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  transition: border-color .3s var(--ease), background .3s var(--ease);
}
.pk-sort:hover { border-color: rgba(255,255,255,.2); background: rgba(255,255,255,.05); }
.pk-sort-lbl {
  font-family: 'IBM Plex Mono', monospace; font-size: 9px; letter-spacing: .2em;
  text-transform: uppercase; color: var(--muted); white-space: nowrap;
}
.pk-sort select {
  background: transparent; border: 0; color: var(--silver); outline: none; cursor: pointer;
  font-family: 'Space Grotesk', sans-serif; font-size: 13px; padding: 0; height: 100%;
}
.pk-sort select option { background: #0b0c10; color: var(--silver); }

/* ── mobile ──────────────────────────────────────────────────── */
@media (max-width: 900px) and (pointer: coarse) {
  /* Same reason as legal.css and pricing.css: fixed/blurred layers get
     re-sampled every scroll frame and wreck smoothness on phones. */
  .pk-card, .pk-stat, .pk-foot, .pk-search input, .pk-sort {
    backdrop-filter: none; -webkit-backdrop-filter: none;
  }
  .pk-card, .pk-stat, .pk-foot { background: rgba(16,17,22,.92); }
  .pk-tag, .pk-pill { backdrop-filter: none; -webkit-backdrop-filter: none; }
}

@media (max-width: 640px) {
  .pk-row { grid-template-columns: repeat(2, 1fr); gap: 11px; margin-top: 15px; }
  .pk-group { margin-top: 30px; }
  .pk-group-title { font-size: 18px; padding-left: 12px; }
  .pk-card { border-radius: 14px; }
  .pk-body { padding: 12px 13px 11px; gap: 6px; }
  .pk-name { font-size: 13px; line-height: 1.3; }
  .pk-seller { font-size: 8.5px; }
  .pk-go { font-size: 7.5px; letter-spacing: .16em; padding-top: 9px; margin-top: 4px; }
  .pk-pill { bottom: 8px; right: 8px; padding: 5px 10px; font-size: 11px; }
  .pk-tag { top: 8px; left: 8px; padding: 4px 8px; font-size: 7.5px; }
  .pk-filters { margin: 18px 0 0; }
  .pk-filter { padding: 8px 13px; font-size: 9px; }
  .pk-stats { margin-top: 20px; gap: 8px; grid-template-columns: repeat(2, 1fr); }
  .pk-stat { padding: 13px 14px; border-radius: 12px; }
  .pk-stat-n { font-size: 1.35rem; }
  .pk-stat--live .pk-stat-n { font-size: .92rem; }
  .pk-stat-l { font-size: .54rem; margin-top: 6px; }
  .pk-controls { margin-top: 20px; gap: 8px; }
  .pk-search input { height: 40px; padding: 0 32px 0 35px; font-size: 13px; }
  .pk-search-ico { left: 12px; width: 14px; height: 14px; }
  .pk-clear { right: 8px; font-size: 17px; padding: 3px 6px; }
  .pk-sort { height: 40px; padding: 0 12px; gap: 0; }
  /* The dropdown says what it is; dropping the label keeps both controls
     on one line instead of stacking into two full-width bars. */
  .pk-sort-lbl { display: none; }
  .pk-sort select { font-size: 12px; }
  .pk-foot { margin: 40px 0 6px; padding: 28px 20px; border-radius: 16px; }
  .pk-foot h2 { font-size: 19px; }
  .pk-foot p { font-size: 14px; }
  .pk-foot-actions { gap: 9px; margin-top: 18px; }
  .pk-cta { padding: 11px 18px; font-size: 10px; letter-spacing: .16em; }
}
@media (max-width: 335px) {
  .pk-row { grid-template-columns: 1fr; }
}

/* Motion is decoration here. Anyone who has asked the OS for less of it
   gets the cards immediately, at rest. */
@media (prefers-reduced-motion: reduce) {
  .js-anim .pk-card:not(.pk-skel) { opacity: 1; transform: none; transition: none; }
  .pk-dot { animation: none; }
  .pk-skel .pk-media, .pk-skel .pk-line { animation: none; }
  a.pk-card:hover { transform: none; }
  a.pk-card:hover .pk-media img { transform: none; }
}
